From 5bf57b64c5acc431592163aa8efc980789ae3536 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 2 Dec 2022 20:43:28 +0800 Subject: [PATCH 001/553] define the objects --- .../cyfs-base/protos/standard_objects.proto | 89 ++++++++++++++----- .../cyfs-core/protos/core_objects.proto | 75 ++++++++++++++++ 2 files changed, 144 insertions(+), 20 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index 7e804ccb9..b8d6f7ba7 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -52,24 +52,6 @@ message FileBodyContent { ChunkList chunk_list = 1; } -// org -message Director { - bytes id = 1; - uint32 right = 2; -} - -message OrgMember { - bytes id = 1; - uint32 right = 2; - uint64 shares = 3; -} - -message OrgBodyContent { - repeated OrgMember members = 1; - repeated Director directors = 2; - uint64 total_equity = 3; -} - // people message PeopleBodyContent { repeated bytes ood_list = 1; @@ -78,12 +60,79 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } +message GroupMember { + bytes id = 1; + string title = 2; + string role = 3; // for acl + uint64 shares = 4; +} + +message GroupMethodACL { + string name = 1; + + // target + optional bytes target_dec_id = 2; + optional string r_path = 3; + + double min_support_percent = 4; + string permissions = 5; // ACL-String +} + +message GroupRoleACL { + string name = 1; + + // target + optional bytes target_dec_id = 2; + optional string r_path = 3; + + string method = 4; + double right_percent = 5; + bool is_operator = 6; + string permissions = 7; // ACL-String +} // simple_group +message SimpleGroupDescContent { + repeated GroupMember admins = 1; + uint32 conclusion_limit = 2; // the admins can make any conclusion with the signatures more than ${conclusion_limit} +} + message SimpleGroupBodyContent { repeated bytes members = 1; - repeated bytes ood_list = 2; - optional string ood_work_mode = 3; + + uint64 total_equity = 3; + + // acl + repeated GroupMethodACL methods = 5; + repeated GroupRoleACL roles = 6; + + repeated bytes ood_list = 7; + + optional uint64 history_block_max = 8; + optional uint64 history_block_lifespan = 9; +} + +// org +message OrgBodyContent { + repeated GroupMember admins = 1; + repeated GroupMember members = 2; + + uint64 total_equity = 3; + + optional bytes token_contract = 4; + + // acl + repeated GroupMethodACL methods = 5; + repeated GroupRoleACL roles = 6; + + repeated bytes ood_list = 7; + + optional uint64 history_block_max = 8; + optional uint64 history_block_lifespan = 9; +} + +message GroupPackedBodyContent { + bytes packed_body_id = 1; } // tx diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index ddb1df2b2..88a459af8 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -314,4 +314,79 @@ message SyncResponseObjectMetaInfo { optional string context = 3; optional string last_access_rpath = 4; optional uint32 access_string = 5; +} + +message GroupProposalDescContent { + // target + bytes r_path_hash = 1; + + // for app + string method = 2; + optional bytes params = 3; // blob, app define, it canbe: blob/hash/ObjectId/any other + + // time + optional bytes meta_block_id = 4; + uint64 timestamp = 5; + optional uint64 effective_begining = 6; + optional uint64 effective_ending = 7; +} + +message GroupConsensusBlockDescContent { + // target + bytes r_path_hash = 1; + + // input + bytes proposals_hash = 2; + + // result + bytes result_state_id = 3; + bytes proposal_result_states_hash = 4; + uint64 version = 5; + + // time + bytes meta_block_id = 6; + uint64 timestamp = 7; + + // prev + optional bytes prev_block_id = 8; // the first block is none +} + +// move to dec-object +message GroupConsensusBlockAckDescContent { + bytes block_id = 1; + + enum AckStep { + Verify = 1; + Ack = 2; + AckAck = 3; + } + + AckStep step = 2; +} + +message GroupRPathSubStatus { + string sub_path = 1; + repeated bytes state_id = 2; // for set +} + +message GroupRPathStatusDescContent { + bytes block_id = 1; + optional GroupRPathSubStatus sub_status = 2; + optional bytes sub_status_hash = 3; +} + +message GroupRPathStatusBodyContent { + repeated GroupRPathSubStatus sub_status = 1; +} + +message GroupActionDescContent { + // target + bytes r_path_hash = 1; + + // for app + string method = 2; + optional bytes params = 3; // blob, app define, it canbe: blob/hash/ObjectId/any other + + optional uint64 value = 4; + optional bytes conclusion 5; } \ No newline at end of file From c39bdd0ec332e41e2203ec4822c4d1feef6cf27b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 9 Dec 2022 14:57:25 +0800 Subject: [PATCH 002/553] merge the SimpleGroup and Org to Group --- src/component/cyfs-base-meta/src/tx.rs | 43 +- .../cyfs-base/protos/standard_objects.proto | 72 +- src/component/cyfs-base/src/codec/format.rs | 60 +- src/component/cyfs-base/src/objects/any.rs | 92 +- src/component/cyfs-base/src/objects/group.rs | 816 ++++++++++++++++++ src/component/cyfs-base/src/objects/mod.rs | 6 +- .../cyfs-base/src/objects/object_type.rs | 11 +- .../cyfs-base/src/objects/object_typeless.rs | 10 +- src/component/cyfs-base/src/objects/org.rs | 178 ---- .../cyfs-base/src/objects/simple_group.rs | 175 ---- .../cyfs-base/src/objects/standard.rs | 61 +- src/component/cyfs-base/src/objects/tx.rs | 6 +- .../cyfs-base/src/objects/unique_id.rs | 12 +- .../cyfs-stack/src/front/protocol.rs | 2 +- .../cyfs-stack/src/resolver/ood_resolver.rs | 6 +- .../cyfs-stack/src/util_api/local/local.rs | 4 +- .../cyfs-stack/src/zone/target_zone.rs | 4 +- .../cyfs-stack/src/zone/zone_manager.rs | 6 +- .../cyfs-meta/src/executor/context/object.rs | 7 +- .../src/executor/tx_proc/account_proc.rs | 339 +++++--- src/meta/cyfs-meta/src/executor/view.rs | 119 ++- src/meta/cyfs-meta/src/state_storage/state.rs | 13 +- src/tools/desc-tool/src/create.rs | 93 +- src/tools/desc-tool/src/desc.rs | 76 +- src/tools/desc-tool/src/main.rs | 10 +- src/tools/desc-tool/src/modify.rs | 31 +- src/tools/desc-tool/src/show.rs | 4 +- src/tools/desc-tool/src/sign.rs | 201 +++-- 28 files changed, 1607 insertions(+), 850 deletions(-) create mode 100644 src/component/cyfs-base/src/objects/group.rs delete mode 100644 src/component/cyfs-base/src/objects/org.rs delete mode 100644 src/component/cyfs-base/src/objects/simple_group.rs diff --git a/src/component/cyfs-base-meta/src/tx.rs b/src/component/cyfs-base-meta/src/tx.rs index d43f9e3e9..529d21a91 100644 --- a/src/component/cyfs-base-meta/src/tx.rs +++ b/src/component/cyfs-base-meta/src/tx.rs @@ -1,12 +1,16 @@ -use cyfs_base::*; -use sha2::{Digest, Sha256}; use crate::contract::*; -use crate::{MetaExtensionTx, NFTAgreeApplyTx, NFTApplyBuyTx, NFTAuctionTx, NFTBidTx, NFTBuyTx, NFTCancelApplyBuyTx, NFTCancelSellTx, NFTCreateTx, NFTCreateTx2, NFTLikeTx, NFTSellTx, NFTSellTx2, NFTSetNameTx, NFTTransTx, SNService, SPVTx}; +use crate::{ + MetaExtensionTx, NFTAgreeApplyTx, NFTApplyBuyTx, NFTAuctionTx, NFTBidTx, NFTBuyTx, + NFTCancelApplyBuyTx, NFTCancelSellTx, NFTCreateTx, NFTCreateTx2, NFTLikeTx, NFTSellTx, + NFTSellTx2, NFTSetNameTx, NFTTransTx, SNService, SPVTx, +}; use async_trait::async_trait; +use cyfs_base::*; use cyfs_core::CoreObjectType; use generic_array::typenum::U32; use generic_array::GenericArray; use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; use std::convert::TryFrom; #[derive(Clone, Debug, RawEncode, RawDecode)] @@ -317,13 +321,14 @@ pub enum SavedMetaObject { Device(Device), //BDT中定义 People(People), //BDT中定义 UnionAccount(UnionAccount), //两人公有账号,用于闪电网络 - Group(SimpleGroup), //M*N Group,最常见的Group BDT中定义 + SimpleGroup, //M*N Group,最常见的Group BDT中定义 File(File), Data(Data), - Org(Org), + Org, MinerGroup(MinerGroup), SNService(SNService), Contract(Contract), + Group(Group), } impl SavedMetaObject { @@ -336,16 +341,17 @@ impl SavedMetaObject { pub fn id(&self) -> ObjectId { match self { - SavedMetaObject::Device(o) => {o.desc().calculate_id()} - SavedMetaObject::People(o) => {o.desc().calculate_id()} - SavedMetaObject::UnionAccount(o) => {o.desc().calculate_id()} - SavedMetaObject::Group(o) => {o.desc().calculate_id()} - SavedMetaObject::File(o) => {o.desc().calculate_id()} - SavedMetaObject::Data(o) => {o.id.clone()} - SavedMetaObject::Org(o) => {o.desc().calculate_id()} - SavedMetaObject::MinerGroup(o) => {o.desc().calculate_id()} - SavedMetaObject::SNService(o) => {o.desc().calculate_id()} - SavedMetaObject::Contract(o) => {o.desc().calculate_id()} + SavedMetaObject::Device(o) => o.desc().calculate_id(), + SavedMetaObject::People(o) => o.desc().calculate_id(), + SavedMetaObject::UnionAccount(o) => o.desc().calculate_id(), + SavedMetaObject::SimpleGroup => panic!("SimpleGroup is deprecated, you can use the Group."), + SavedMetaObject::File(o) => o.desc().calculate_id(), + SavedMetaObject::Data(o) => o.id.clone(), + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + SavedMetaObject::MinerGroup(o) => o.desc().calculate_id(), + SavedMetaObject::SNService(o) => o.desc().calculate_id(), + SavedMetaObject::Contract(o) => o.desc().calculate_id(), + SavedMetaObject::Group(o) => o.desc().calculate_id(), } } } @@ -370,9 +376,8 @@ impl TryFrom for StandardObject { SavedMetaObject::Device(v) => Ok(Self::Device(v)), SavedMetaObject::People(v) => Ok(Self::People(v)), SavedMetaObject::UnionAccount(v) => Ok(Self::UnionAccount(v)), - SavedMetaObject::Group(v) => Ok(Self::SimpleGroup(v)), + SavedMetaObject::Group(v) => Ok(Self::Group(v)), SavedMetaObject::File(v) => Ok(Self::File(v)), - SavedMetaObject::Org(v) => Ok(Self::Org(v)), SavedMetaObject::Contract(v) => Ok(Self::Contract(v)), _ => Err(BuckyError::from(BuckyErrorCode::NotSupport)), } @@ -387,9 +392,8 @@ impl TryFrom for SavedMetaObject { StandardObject::Device(v) => Self::Device(v), StandardObject::People(v) => Self::People(v), StandardObject::UnionAccount(v) => Self::UnionAccount(v), - StandardObject::SimpleGroup(v) => SavedMetaObject::Group(v), + StandardObject::Group(v) => SavedMetaObject::Group(v), StandardObject::File(v) => Self::File(v), - StandardObject::Org(v) => Self::Org(v), StandardObject::Contract(v) => Self::Contract(v), _ => { return Err(BuckyError::from(BuckyErrorCode::NotSupport)); @@ -936,7 +940,6 @@ mod tx_test { #[test] fn test_people_codec() { - for code in OLD_LIST { let code = hex::decode(code).unwrap(); let ret = SavedMetaObject::clone_from_slice(code.as_slice()).unwrap(); diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index b8d6f7ba7..0098c88fc 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -84,51 +84,69 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; optional string r_path = 3; - string method = 4; + double right_percent = 5; bool is_operator = 6; string permissions = 7; // ACL-String } -// simple_group -message SimpleGroupDescContent { - repeated GroupMember admins = 1; - uint32 conclusion_limit = 2; // the admins can make any conclusion with the signatures more than ${conclusion_limit} +message GroupJoinSignature { + bytes signature = 1; // Sign(member_id, group_id, timestamp, hash, is_admin) + bytes member_id = 2; + uint64 timestamp = 3; + bool is_admin = 4; + bytes hash = 5; // Hash(Encode(Group)) } -message SimpleGroupBodyContent { - repeated bytes members = 1; +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; - uint64 total_equity = 3; + repeated GroupMember members = 4; + + uint64 total_equity = 5; // acl - repeated GroupMethodACL methods = 5; - repeated GroupRoleACL roles = 6; + repeated GroupMethodACL method_acls = 6; + repeated GroupRoleACL role_acls = 7; - repeated bytes ood_list = 7; + repeated bytes ood_list = 8; // 1/0 for every member/admin - optional uint64 history_block_max = 8; - optional uint64 history_block_lifespan = 9; -} + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms -// org -message OrgBodyContent { - repeated GroupMember admins = 1; - repeated GroupMember members = 2; + repeated bytes revoked_conclusions = 12; - uint64 total_equity = 3; - - optional bytes token_contract = 4; + uint64 version = 13; - // acl - repeated GroupMethodACL methods = 5; - repeated GroupRoleACL roles = 6; + repeated GroupJoinSignature join_signatures = 14; // signature for every member/admin +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; + uint32 conclusion_limit = 4; // the admins can make any conclusion with the signatures more than ${conclusion_limit} +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} - repeated bytes ood_list = 7; +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} - optional uint64 history_block_max = 8; - optional uint64 history_block_lifespan = 9; +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; } message GroupPackedBodyContent { diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index e3964852c..75863c9d1 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -1,5 +1,6 @@ use crate::*; +use itertools::Itertools; use serde::Serialize; use serde_json::{Map, Value}; @@ -481,8 +482,7 @@ impl ObjectFormat for StandardObject { match self { StandardObject::Device(o) => o.format_json(), StandardObject::People(o) => o.format_json(), - StandardObject::SimpleGroup(o) => o.format_json(), - StandardObject::Org(o) => o.format_json(), + StandardObject::Group(o) => o.format_json(), StandardObject::AppGroup(o) => o.format_json(), StandardObject::UnionAccount(o) => o.format_json(), StandardObject::ChunkId(chunk_id) => chunk_id.format_json(), @@ -494,6 +494,10 @@ impl ObjectFormat for StandardObject { StandardObject::Action(o) => o.format_json(), StandardObject::ObjectMap(o) => o.format_json(), StandardObject::Contract(o) => o.format_json(), + StandardObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } } } @@ -561,7 +565,7 @@ impl ObjectFormat for PeopleBodyContent { } // simple group -impl ObjectFormat for SimpleGroupDescContent { +impl ObjectFormat for GroupDescContent { fn format_json(&self) -> serde_json::Value { let map = serde_json::Map::new(); @@ -569,29 +573,22 @@ impl ObjectFormat for SimpleGroupDescContent { } } -impl ObjectFormat for SimpleGroupBodyContent { +impl ObjectFormat for GroupBodyContent { fn format_json(&self) -> serde_json::Value { let mut map = serde_json::Map::new(); - JsonCodecHelper::encode_str_array_field(&mut map, "members", self.members()); - JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", &self.ood_list()); - JsonCodecHelper::encode_string_field(&mut map, "ood_work_mode", &self.ood_work_mode()); - - map.into() - } -} - -// org -impl ObjectFormat for OrgDescContent { - fn format_json(&self) -> serde_json::Value { - let map = serde_json::Map::new(); + JsonCodecHelper::encode_string_field(&mut map, "name", self.name()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "members", + &self.members().iter().map(|m| m.id).collect_vec(), + ); + JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", self.ood_list()); map.into() } } -impl ObjectFormatAutoWithSerde for OrgBodyContent {} - // appgroup impl ObjectFormat for AppGroupDescContent { fn format_json(&self) -> serde_json::Value { @@ -907,19 +904,31 @@ fn test() { let secret = PrivateKey::generate_rsa(1024).unwrap(); let public = secret.public(); - let mut device = Device::new(Some(owner), UniqueId::default(), - vec![], vec![], vec![], - public, Area::new(1,2,3,4), DeviceCategory::OOD).build(); + let mut device = Device::new( + Some(owner), + UniqueId::default(), + vec![], + vec![], + vec![], + public, + Area::new(1, 2, 3, 4), + DeviceCategory::OOD, + ) + .build(); device.set_bdt_version(Some(2)); println!("new device obj: {}", device.format_json().to_string()); - let (mut old_device, _) = Device::decode_from_file("c:\\cyfs\\etc\\desc\\device.desc".as_ref(), &mut vec![]).unwrap(); + let (mut old_device, _) = + Device::decode_from_file("c:\\cyfs\\etc\\desc\\device.desc".as_ref(), &mut vec![]).unwrap(); println!("old device obj: {}", old_device.format_json().to_string()); old_device.set_bdt_version(Some(5)); - println!("old device set bdt ver obj: {}", old_device.format_json().to_string()); + println!( + "old device set bdt ver obj: {}", + old_device.format_json().to_string() + ); } use std::collections::{hash_map::Entry, HashMap}; @@ -961,7 +970,10 @@ impl FormatFactory { v.insert(f); } Entry::Occupied(mut o) => { - warn!("register ext object format but already exists! obj_type={}", obj_type); + warn!( + "register ext object format but already exists! obj_type={}", + obj_type + ); o.insert(f); } } diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index 661f9fabf..a88a27aa1 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -14,8 +14,7 @@ macro_rules! match_any_obj { AnyNamedObject::Standard(o) => match o { StandardObject::Device($o) => $body, StandardObject::People($o) => $body, - StandardObject::SimpleGroup($o) => $body, - StandardObject::Org($o) => $body, + StandardObject::Group($o) => $body, StandardObject::AppGroup($o) => $body, StandardObject::UnionAccount($o) => $body, StandardObject::ChunkId($chunk_id) => $chunk_body, @@ -27,6 +26,10 @@ macro_rules! match_any_obj { StandardObject::Action($o) => $body, StandardObject::ObjectMap($o) => $body, StandardObject::Contract($o) => $body, + StandardObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + StandardObject::Org => panic!("Org is deprecated, you can use the Group."), }, AnyNamedObject::Core($o) => $body, AnyNamedObject::DECApp($o) => $body, @@ -229,32 +232,26 @@ impl AnyNamedObject { // reset the object's body with the same obj_type object pub fn set_body_expect(&mut self, other: &Self) { assert_eq!(self.obj_type(), other.obj_type()); - + match self { - Self::Standard(o) => { - match other { - Self::Standard(other) => { - o.set_body_expect(other); - } - _ => unreachable!(), + Self::Standard(o) => match other { + Self::Standard(other) => { + o.set_body_expect(other); } - } - Self::Core(o) => { - match other { - Self::Core(other) => { - *o.body_mut() = other.body().to_owned(); - } - _ => unreachable!(), + _ => unreachable!(), + }, + Self::Core(o) => match other { + Self::Core(other) => { + *o.body_mut() = other.body().to_owned(); } - } - Self::DECApp(o) => { - match other { - Self::DECApp(other) => { - *o.body_mut() = other.body().to_owned(); - } - _ => unreachable!(), + _ => unreachable!(), + }, + Self::DECApp(o) => match other { + Self::DECApp(other) => { + *o.body_mut() = other.body().to_owned(); } - } + _ => unreachable!(), + }, } } @@ -327,7 +324,6 @@ impl AnyNamedObject { } } - impl RawEncode for AnyNamedObject { fn raw_measure(&self, purpose: &Option) -> BuckyResult { match self { @@ -378,13 +374,6 @@ impl<'de> RawDecode<'de> for AnyNamedObject { buf, )); } - ObjectTypeCode::Org => { - let (org, buf) = Org::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/org error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); - } ObjectTypeCode::AppGroup => { let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); @@ -395,15 +384,12 @@ impl<'de> RawDecode<'de> for AnyNamedObject { buf, )); } - ObjectTypeCode::SimpleGroup => { - let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); + ObjectTypeCode::Group => { + let (group, buf) = Group::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/group error:{}", e); e })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), - buf, - )); + return Ok((AnyNamedObject::Standard(StandardObject::Group(group)), buf)); } ObjectTypeCode::UnionAccount => { let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { @@ -616,40 +602,34 @@ mod tests { } } - - macro_rules! any_for_standard_target { ($as_name:ident, $into_name:ident, $target:ident) => { impl AnyNamedObject { pub fn $as_name(&self) -> &$target { match self { - AnyNamedObject::Standard(s) => { - match s { - StandardObject::$target(f) => f, - _ => unreachable!(), - } - } + AnyNamedObject::Standard(s) => match s { + StandardObject::$target(f) => f, + _ => unreachable!(), + }, _ => unreachable!(), } } pub fn $into_name(self) -> $target { match self { - AnyNamedObject::Standard(s) => { - match s { - StandardObject::$target(f) => f, - _ => unreachable!(), - } - } + AnyNamedObject::Standard(s) => match s { + StandardObject::$target(f) => f, + _ => unreachable!(), + }, _ => unreachable!(), } } } - } + }; } any_for_standard_target!(as_file, into_file, File); any_for_standard_target!(as_dir, into_dir, Dir); any_for_standard_target!(as_people, into_people, People); any_for_standard_target!(as_device, into_device, Device); -any_for_standard_target!(as_simple_group, into_simple_group, SimpleGroup); -any_for_standard_target!(as_object_map, into_object_map, ObjectMap); \ No newline at end of file +any_for_standard_target!(as_group, into_group, Group); +any_for_standard_target!(as_object_map, into_object_map, ObjectMap); diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs new file mode 100644 index 000000000..0577d6e82 --- /dev/null +++ b/src/component/cyfs-base/src/objects/group.rs @@ -0,0 +1,816 @@ +use crate::codec as cyfs_base; +use crate::*; + +use std::collections::HashSet; +use std::convert::TryFrom; + +#[derive(Clone, Debug, RawEncode, RawDecode)] +pub enum GroupDescContent { + SimpleGroup(SimpleGroupDescContent), + Org(OrgDescContent), +} + +#[derive(Clone, Debug, RawEncode, RawDecode)] +pub enum GroupBodyContent { + SimpleGroup(SimpleGroupBodyContent), + Org(OrgBodyContent), +} + +impl DescContent for GroupDescContent { + fn obj_type() -> u16 { + ObjectTypeCode::Group.into() + } + + type OwnerType = SubDescNone; + type AreaType = Option; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +impl BodyContent for GroupBodyContent { + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } +} + +impl GroupBodyContent { + pub fn name(&self) -> &str { + self.common().name.as_str() + } + + pub fn icon(&self) -> &Option { + &self.common().icon + } + + pub fn description(&self) -> &str { + self.common().description.as_str() + } + + pub fn members(&self) -> &Vec { + &self.common().members + } + + pub fn members_mut(&mut self) -> &mut Vec { + &mut self.common_mut().members + } + + pub fn ood_list(&self) -> &Vec { + &self.common().ood_list + } + + pub fn ood_list_mut(&mut self) -> &mut Vec { + &mut self.common_mut().ood_list + } + + fn common(&self) -> &CommonGroupBodyContent { + match self { + GroupBodyContent::Org(body) => &body.common, + GroupBodyContent::SimpleGroup(body) => &body.common, + } + } + + fn common_mut(&mut self) -> &mut CommonGroupBodyContent { + match self { + GroupBodyContent::Org(body) => &mut body.common, + GroupBodyContent::SimpleGroup(body) => &mut body.common, + } + } +} + +pub type GroupType = NamedObjType; +pub type GroupBuilder = NamedObjectBuilder; + +pub type GroupDesc = NamedObjectDesc; +pub type GroupId = NamedObjectId; +pub type Group = NamedObjectBase; + +impl GroupDesc { + pub fn group_id(&self) -> GroupId { + GroupId::try_from(self.calculate_id()).unwrap() + } +} + +impl Group { + pub fn new_simple_group( + founder_id: ObjectId, + admins: Vec, + conclusion_limit: Option, + area: Area, + ) -> GroupBuilder { + let desc_content = SimpleGroupDescContent { + unique_id: UniqueId::create_with_random(), + conclusion_limit: conclusion_limit.map_or((admins.len() as u32 >> 1) + 1, |n| n), + admins, + founder_id, + }; + + let body_content = SimpleGroupBodyContent::default(); + + GroupBuilder::new( + GroupDescContent::SimpleGroup(desc_content), + GroupBodyContent::SimpleGroup(body_content), + ) + .area(area) + } + + pub fn new_org(founder_id: ObjectId, area: Area) -> GroupBuilder { + let desc_content = OrgDescContent { + founder_id, + unique_id: UniqueId::create_with_random(), + }; + + let body_content = OrgBodyContent::default(); + + GroupBuilder::new( + GroupDescContent::Org(desc_content), + GroupBodyContent::Org(body_content), + ) + .area(area) + } + + pub fn name(&self) -> &str { + self.common().name.as_str() + } + + pub fn set_name(&mut self, name: String) { + self.common_mut().name = name; + } + + pub fn icon(&self) -> &Option { + &self.common().icon + } + + pub fn set_icon(&mut self, icon: Option) { + self.common_mut().icon = icon; + } + + pub fn description(&self) -> &str { + self.common().description.as_str() + } + + pub fn set_description(&mut self, description: String) { + self.common_mut().description = description; + } + + pub fn admins(&self) -> &[GroupMember] { + if self.is_org() { + self.check_org_body_content().admins.as_slice() + } else { + self.check_simple_group_desc_content().admins.as_slice() + } + } + + pub fn members(&self) -> &[GroupMember] { + self.common().members.as_slice() + } + + pub fn set_members(&mut self, members: Vec) { + self.common_mut().members = members; + } + + pub fn ood_list(&self) -> &[DeviceId] { + self.common().ood_list.as_slice() + } + + pub fn set_ood_list(&mut self, oods: Vec) { + self.common_mut().ood_list = oods; + } + + pub fn join_member( + &self, + member_id: &ObjectId, + private_key: &PrivateKey, + ) -> BuckyResult<&GroupJoinSignature> { + unimplemented!() + } + + pub fn verify(&self, signature: &GroupJoinSignature) -> BuckyResult { + unimplemented!() + } + + pub fn verify_all(&self) -> BuckyResult { + unimplemented!() + } + + pub fn verify_member(&self, member_id: &ObjectId, is_admin: bool) -> BuckyResult { + unimplemented!() + } + + pub fn is_simple_group(&self) -> bool { + match self.desc().content() { + GroupDescContent::SimpleGroup(_) => true, + _ => false, + } + } + + pub fn is_org(&self) -> bool { + match self.desc().content() { + GroupDescContent::Org(_) => true, + _ => false, + } + } + + pub fn check_simple_group_desc_content(&self) -> &SimpleGroupDescContent { + match self.desc().content() { + GroupDescContent::SimpleGroup(desc) => desc, + _ => panic!("group type not match, expect: simple"), + } + } + + pub fn check_org_desc_content(&self) -> &OrgDescContent { + match self.desc().content() { + GroupDescContent::Org(desc) => desc, + _ => panic!("group type not match, expect: org"), + } + } + + pub fn check_simple_group_body_content(&self) -> &SimpleGroupBodyContent { + match self.body().as_ref().unwrap().content() { + GroupBodyContent::SimpleGroup(body) => body, + _ => panic!("group type not match, expect: simple"), + } + } + + pub fn check_org_body_content(&self) -> &OrgBodyContent { + match self.body().as_ref().unwrap().content() { + GroupBodyContent::Org(body) => body, + _ => panic!("group type not match, expect: org"), + } + } + + pub fn check_simple_group_body_content_mut(&mut self) -> &mut SimpleGroupBodyContent { + match self.body_mut().as_mut().unwrap().content_mut() { + GroupBodyContent::SimpleGroup(body) => body, + _ => panic!("group type not match, expect: simple"), + } + } + + pub fn check_org_body_content_mut(&mut self) -> &mut OrgBodyContent { + match self.body_mut().as_mut().unwrap().content_mut() { + GroupBodyContent::Org(body) => body, + _ => panic!("group type not match, expect: org"), + } + } + + fn common(&self) -> &CommonGroupBodyContent { + self.body().as_ref().unwrap().content().common() + } + + fn common_mut(&mut self) -> &mut CommonGroupBodyContent { + self.body_mut().as_mut().unwrap().content_mut().common_mut() + } +} + +#[derive(Clone, Debug)] +pub struct GroupMember { + pub id: ObjectId, + pub title: String, + pub role: String, + pub shares: u64, +} + +impl GroupMember { + pub fn from_member_id(id: ObjectId) -> GroupMember { + GroupMember { + id, + title: "".to_string(), + role: "".to_string(), + shares: 0, + } + } +} + +impl TryFrom for GroupMember { + type Error = BuckyError; + + fn try_from(mut value: protos::GroupMember) -> BuckyResult { + let ret = Self { + id: ProtobufCodecHelper::decode_buf(value.id)?, + title: value.title, + role: value.role, + shares: value.shares, + }; + + Ok(ret) + } +} + +impl TryFrom<&GroupMember> for protos::GroupMember { + type Error = BuckyError; + + fn try_from(value: &GroupMember) -> BuckyResult { + let mut ret = Self::new(); + + ret.id = value.id.to_vec()?; + ret.title = value.title.clone(); + ret.role = value.role.clone(); + ret.shares = value.shares; + + Ok(ret) + } +} + +#[derive(Clone, Debug)] +pub struct GroupMethodACL { + pub name: String, + pub target_dec_id: Option, + pub r_path: Option, + pub min_support_percent: f64, + pub permissions: String, // ACL-String +} + +impl TryFrom for GroupMethodACL { + type Error = BuckyError; + + fn try_from(mut value: protos::GroupMethodACL) -> BuckyResult { + let ret = Self { + name: value.take_name(), + target_dec_id: if value.has_target_dec_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_target_dec_id())?) + } else { + None + }, + r_path: if value.has_r_path() { + Some(value.take_r_path()) + } else { + None + }, + min_support_percent: value.min_support_percent, + permissions: value.take_permissions(), // ACL-String + }; + + Ok(ret) + } +} + +impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { + type Error = BuckyError; + + fn try_from(value: &GroupMethodACL) -> BuckyResult { + let mut ret = Self::new(); + + ret.name = value.name.clone(); + if let Some(dec_id) = &value.target_dec_id { + ret.set_target_dec_id(dec_id.to_vec()?); + } + if let Some(r_path) = &value.r_path { + ret.set_r_path(r_path.clone()); + } + ret.min_support_percent = value.min_support_percent; + ret.permissions = value.permissions.clone(); + + Ok(ret) + } +} + +#[derive(Clone, Debug)] +pub struct GroupRoleACL { + pub name: String, + pub target_dec_id: Option, + pub r_path: Option, + pub method: String, + + pub right_percent: f64, + pub is_operator: bool, + pub permissions: String, // ACL-String +} + +impl TryFrom for GroupRoleACL { + type Error = BuckyError; + + fn try_from(mut value: protos::GroupRoleACL) -> BuckyResult { + let ret = Self { + name: value.take_name(), + target_dec_id: if value.has_target_dec_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_target_dec_id())?) + } else { + None + }, + r_path: if value.has_r_path() { + Some(value.take_r_path()) + } else { + None + }, + method: value.take_method(), + right_percent: value.right_percent, + is_operator: value.is_operator, + permissions: value.take_permissions(), // ACL-String + }; + + Ok(ret) + } +} + +impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { + type Error = BuckyError; + + fn try_from(value: &GroupRoleACL) -> BuckyResult { + let mut ret = Self::new(); + + ret.set_name(value.name.clone()); + if let Some(dec_id) = &value.target_dec_id { + ret.set_target_dec_id(dec_id.to_vec()?); + } + if let Some(r_path) = &value.r_path { + ret.set_r_path(r_path.clone()); + } + ret.method = value.method.clone(); + ret.right_percent = value.right_percent; + ret.is_operator = value.is_operator; + ret.permissions = value.permissions.clone(); + + Ok(ret) + } +} + +#[derive(Clone, Debug)] +pub struct GroupJoinSignature { + signature: Signature, + member_id: ObjectId, + timestamp: u64, + is_admin: bool, + hash: HashValue, +} + +impl TryFrom for GroupJoinSignature { + type Error = BuckyError; + + fn try_from(mut value: protos::GroupJoinSignature) -> BuckyResult { + let ret = Self { + signature: ProtobufCodecHelper::decode_buf(value.signature)?, + member_id: ProtobufCodecHelper::decode_buf(value.member_id)?, + timestamp: value.timestamp, + is_admin: value.is_admin, + hash: ProtobufCodecHelper::decode_buf(value.hash)?, + }; + + Ok(ret) + } +} + +impl TryFrom<&GroupJoinSignature> for protos::GroupJoinSignature { + type Error = BuckyError; + + fn try_from(value: &GroupJoinSignature) -> BuckyResult { + let mut ret = Self::new(); + + ret.signature = value.signature.to_vec()?; + ret.member_id = value.member_id.to_vec()?; + ret.timestamp = value.timestamp; + ret.is_admin = value.is_admin; + ret.hash = value.hash.to_vec()?; + + Ok(ret) + } +} + +#[derive(Clone, Debug, Default)] +struct CommonGroupBodyContent { + name: String, + icon: Option, + description: String, + + members: Vec, + total_equity: u64, + + // map优化以快速匹配 + method_acls: Vec, + + role_acls: Vec, + + ood_list: Vec, + history_block_max: u64, + history_block_lifespan: u64, + + revoked_conclusions: HashSet, + + version: u64, + consensus_interval: u64, + join_signatures: Vec, +} + +impl CommonGroupBodyContent { + fn new( + name: String, + icon: Option, + description: String, + members: Vec, + ood_list: Vec, + ) -> Self { + Self { + name, + icon, + description, + members, + total_equity: 0, + method_acls: vec![], + role_acls: vec![], + ood_list, + history_block_max: 0, + history_block_lifespan: 0, + revoked_conclusions: HashSet::default(), + version: 0, + consensus_interval: 0, + join_signatures: vec![], + } + } +} + +impl TryFrom for CommonGroupBodyContent { + type Error = BuckyError; + + fn try_from(mut value: protos::CommonGroupBodyContent) -> BuckyResult { + let ret = Self { + name: value.take_name(), + icon: if value.has_icon() { + Some(ProtobufCodecHelper::decode_buf(value.take_icon())?) + } else { + None + }, + description: value.take_description(), + members: ProtobufCodecHelper::decode_value_list(value.take_members())?, + total_equity: value.total_equity, + method_acls: ProtobufCodecHelper::decode_value_list(value.take_method_acls())?, + role_acls: ProtobufCodecHelper::decode_value_list(value.take_role_acls())?, + ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, + history_block_max: value.get_history_block_max(), + history_block_lifespan: value.get_history_block_lifespan(), + revoked_conclusions: HashSet::from_iter(ProtobufCodecHelper::decode_buf_list( + value.take_revoked_conclusions(), + )?), + version: value.version, + consensus_interval: if value.has_consensus_interval() { + value.get_consensus_interval() + } else { + 0 + }, + join_signatures: ProtobufCodecHelper::decode_value_list( + value.take_join_signatures().into_vec(), + )?, + }; + + Ok(ret) + } +} + +impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { + type Error = BuckyError; + + fn try_from(value: &CommonGroupBodyContent) -> BuckyResult { + let mut ret = Self::new(); + + ret.name = value.name.clone(); + if let Some(icon) = &value.icon { + ret.set_icon(icon.to_vec()?); + } + ret.description = value.description.clone(); + + ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); + ret.total_equity = value.total_equity; + ret.set_method_acls(ProtobufCodecHelper::encode_nested_list(&value.method_acls)?); + ret.set_role_acls(ProtobufCodecHelper::encode_nested_list(&value.role_acls)?); + ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( + value.ood_list.as_slice(), + )?); + if value.history_block_max > 0 { + ret.set_history_block_max(value.history_block_max); + } + if value.history_block_lifespan > 0 { + ret.set_history_block_lifespan(value.history_block_lifespan); + } + ret.set_revoked_conclusions(ProtobufCodecHelper::encode_buf_list( + value.revoked_conclusions.to_vec()?.as_slice(), + )?); + ret.version = value.version; + if value.consensus_interval > 0 { + ret.set_consensus_interval(value.consensus_interval); + } + ret.set_join_signatures(ProtobufCodecHelper::encode_nested_list( + &value.join_signatures, + )?); + + Ok(ret) + } +} + +#[derive(Clone, Debug)] +pub struct SimpleGroupDescContent { + unique_id: UniqueId, + founder_id: ObjectId, + admins: Vec, + conclusion_limit: u32, +} + +impl TryFrom for SimpleGroupDescContent { + type Error = BuckyError; + + fn try_from(mut value: protos::SimpleGroupDescContent) -> BuckyResult { + let ret = Self { + unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, + admins: ProtobufCodecHelper::decode_value_list(value.admins)?, + conclusion_limit: value.conclusion_limit, + founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, + }; + + Ok(ret) + } +} + +impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { + type Error = BuckyError; + + fn try_from(value: &SimpleGroupDescContent) -> BuckyResult { + let mut ret = Self::new(); + + ret.unique_id = value.unique_id.to_vec()?; + ret.founder_id = value.founder_id.to_vec()?; + ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); + ret.conclusion_limit = value.conclusion_limit; + + Ok(ret) + } +} + +#[derive(Clone, Debug, Default)] +pub struct SimpleGroupBodyContent { + common: CommonGroupBodyContent, +} + +impl SimpleGroupBodyContent { + fn new( + name: String, + icon: Option, + description: String, + members: Vec, + ood_list: Vec, + ) -> Self { + Self { + common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), + } + } +} + +impl TryFrom for SimpleGroupBodyContent { + type Error = BuckyError; + + fn try_from(mut value: protos::SimpleGroupBodyContent) -> BuckyResult { + let ret = Self { + common: ProtobufCodecHelper::decode_value(value.take_common())?, + }; + + Ok(ret) + } +} + +impl TryFrom<&SimpleGroupBodyContent> for protos::SimpleGroupBodyContent { + type Error = BuckyError; + + fn try_from(value: &SimpleGroupBodyContent) -> BuckyResult { + let mut ret = Self::new(); + + ret.set_common(ProtobufCodecHelper::encode_nested_item(&value.common)?); + + Ok(ret) + } +} + +#[derive(Clone, Debug)] +pub struct OrgDescContent { + unique_id: UniqueId, + founder_id: ObjectId, +} + +impl TryFrom for OrgDescContent { + type Error = BuckyError; + + fn try_from(mut value: protos::OrgDescContent) -> BuckyResult { + let ret = Self { + unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, + founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, + }; + + Ok(ret) + } +} + +impl TryFrom<&OrgDescContent> for protos::OrgDescContent { + type Error = BuckyError; + + fn try_from(value: &OrgDescContent) -> BuckyResult { + let mut ret = Self::new(); + + ret.unique_id = value.unique_id.to_vec()?; + ret.founder_id = value.founder_id.to_vec()?; + + Ok(ret) + } +} + +#[derive(Clone, Debug, Default)] +pub struct OrgBodyContent { + admins: Vec, + token_contract: Option, + common: CommonGroupBodyContent, +} + +impl OrgBodyContent { + fn new( + name: String, + icon: Option, + description: String, + admins: Vec, + members: Vec, + ood_list: Vec, + ) -> Self { + Self { + common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), + admins, + token_contract: None, + } + } + + pub fn admins(&self) -> &Vec { + &self.admins + } + + pub fn set_admins(&mut self, admins: Vec) { + self.admins = admins; + } +} + +impl TryFrom for OrgBodyContent { + type Error = BuckyError; + + fn try_from(mut value: protos::OrgBodyContent) -> BuckyResult { + let ret = Self { + admins: ProtobufCodecHelper::decode_value_list(value.take_admins())?, + token_contract: if value.has_token_contract() { + Some(ProtobufCodecHelper::decode_buf( + value.take_token_contract(), + )?) + } else { + None + }, + common: ProtobufCodecHelper::decode_value(value.take_common())?, + }; + + Ok(ret) + } +} + +impl TryFrom<&OrgBodyContent> for protos::OrgBodyContent { + type Error = BuckyError; + + fn try_from(value: &OrgBodyContent) -> BuckyResult { + let mut ret = Self::new(); + + ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); + ret.set_common(ProtobufCodecHelper::encode_nested_item(&value.common)?); + + if let Some(token_contract) = value.token_contract { + ret.set_token_contract(token_contract.to_vec()?); + } + + Ok(ret) + } +} + +crate::inner_impl_default_protobuf_raw_codec!(SimpleGroupDescContent); +crate::inner_impl_default_protobuf_raw_codec!(SimpleGroupBodyContent); + +crate::inner_impl_default_protobuf_raw_codec!(OrgDescContent); +crate::inner_impl_default_protobuf_raw_codec!(OrgBodyContent); + +#[cfg(test)] +mod test { + use crate::*; + + #[test] + fn simple_group() { + // let threshold = 0; + + // let members = vec![ObjectId::default()]; + + // let ood_list = vec![DeviceId::default()]; + + // let obj = SimpleGroup::new( + // threshold, + // vec![], + // members, + // OODWorkMode::Standalone, + // ood_list, + // Area::default(), + // ) + // .build(); + // // let p = Path::new("f:\\temp\\simple_group.obj"); + // // if p.parent().unwrap().exists() { + // // obj.clone().encode_to_file(p, false); + // // } + + // let buf = obj.to_vec().unwrap(); + + // let decode_obj = SimpleGroup::clone_from_slice(&buf).unwrap(); + + // assert!(obj.desc().simple_group_id() == decode_obj.desc().simple_group_id()); + } +} diff --git a/src/component/cyfs-base/src/objects/mod.rs b/src/component/cyfs-base/src/objects/mod.rs index 448318736..a3ea14b12 100644 --- a/src/component/cyfs-base/src/objects/mod.rs +++ b/src/component/cyfs-base/src/objects/mod.rs @@ -19,11 +19,10 @@ mod object_map; mod object_signs; mod object_type; mod object_typeless; -mod org; mod people; mod proof_of_service; mod raw_diff; -mod simple_group; +mod group; mod standard; mod tx; mod union_account; @@ -51,11 +50,10 @@ pub use object_map::*; pub use object_signs::*; pub use object_type::*; pub use object_typeless::*; -pub use org::*; pub use people::*; pub use proof_of_service::*; pub use raw_diff::*; -pub use simple_group::*; +pub use group::*; pub use standard::*; pub use tx::*; pub use union_account::*; diff --git a/src/component/cyfs-base/src/objects/object_type.rs b/src/component/cyfs-base/src/objects/object_type.rs index f24afebf9..6b7a6f613 100644 --- a/src/component/cyfs-base/src/objects/object_type.rs +++ b/src/component/cyfs-base/src/objects/object_type.rs @@ -7,8 +7,7 @@ use std::str::FromStr; pub enum ObjectTypeCode { Device = 1, People = 2, - SimpleGroup = 3, - Org = 4, + Group = 3, AppGroup = 5, UnionAccount = 6, Chunk = 7, @@ -28,8 +27,7 @@ impl From for ObjectTypeCode { match v { 1u16 => ObjectTypeCode::Device, 2u16 => ObjectTypeCode::People, - 3u16 => ObjectTypeCode::SimpleGroup, - 4u16 => ObjectTypeCode::Org, + 3u16 => ObjectTypeCode::Group, 5u16 => ObjectTypeCode::AppGroup, 6u16 => ObjectTypeCode::UnionAccount, 7u16 => ObjectTypeCode::Chunk, @@ -52,8 +50,7 @@ impl From<&ObjectTypeCode> for u16 { match v { ObjectTypeCode::Device => 1u16, ObjectTypeCode::People => 2u16, - ObjectTypeCode::SimpleGroup => 3u16, - ObjectTypeCode::Org => 4u16, + ObjectTypeCode::Group => 3u16, ObjectTypeCode::AppGroup => 5u16, ObjectTypeCode::UnionAccount => 6u16, ObjectTypeCode::Chunk => 7u16, @@ -188,4 +185,4 @@ pub trait ObjectType: Clone { type DescType: ObjectDesc + Sync + Send; type ContentType: Sync + Send; -} \ No newline at end of file +} diff --git a/src/component/cyfs-base/src/objects/object_typeless.rs b/src/component/cyfs-base/src/objects/object_typeless.rs index aa3046e57..949cc5019 100644 --- a/src/component/cyfs-base/src/objects/object_typeless.rs +++ b/src/component/cyfs-base/src/objects/object_typeless.rs @@ -1293,8 +1293,8 @@ impl TryFrom for AnyNamedObject { e })?, ))), - ObjectTypeCode::Org => Ok(AnyNamedObject::Standard(StandardObject::Org( - Org::try_from(value).map_err(|e| { + ObjectTypeCode::Group => Ok(AnyNamedObject::Standard(StandardObject::Group( + Group::try_from(value).map_err(|e| { log::error!("AnyNamedObject::try_from/Org error:{}", e); e })?, @@ -1305,12 +1305,6 @@ impl TryFrom for AnyNamedObject { e })?, ))), - ObjectTypeCode::SimpleGroup => Ok(AnyNamedObject::Standard( - StandardObject::SimpleGroup(SimpleGroup::try_from(value).map_err(|e| { - log::error!("AnyNamedObject::try_from/SimpleGroup error:{}", e); - e - })?), - )), ObjectTypeCode::UnionAccount => Ok(AnyNamedObject::Standard( StandardObject::UnionAccount(UnionAccount::try_from(value).map_err(|e| { log::error!("AnyNamedObject::try_from/UnionAccount error:{}", e); diff --git a/src/component/cyfs-base/src/objects/org.rs b/src/component/cyfs-base/src/objects/org.rs deleted file mode 100644 index e9e6af335..000000000 --- a/src/component/cyfs-base/src/objects/org.rs +++ /dev/null @@ -1,178 +0,0 @@ -use crate::*; - -use std::convert::TryFrom; -use serde::Serialize; - -#[derive(Clone, Debug, RawEncode, RawDecode)] -pub struct OrgDescContent {} - -impl DescContent for OrgDescContent { - fn obj_type() -> u16 { - ObjectTypeCode::Org.into() - } - - type OwnerType = Option; - type AreaType = SubDescNone; - type AuthorType = SubDescNone; - type PublicKeyType = SubDescNone; -} - -#[derive(Clone, Debug, Serialize)] -pub struct Director { - pub id: ObjectId, - pub right: u8, -} - -pub struct BoardOfDirector {} - -pub enum DepartmentMember {} - -pub struct Department {} - -#[derive(Clone, Debug, Serialize)] -pub struct OrgMember { - pub id: ObjectId, - pub right: u8, - pub shares: u64, -} - -#[derive(Clone, Debug, Serialize)] -pub struct OrgBodyContent { - pub members: Vec, - pub directors: Vec, - pub total_equity: u64, -} - -impl BodyContent for OrgBodyContent { - fn format(&self) -> u8 { - OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF - } -} - -// body使用protobuf编解码 -impl TryFrom for Director { - type Error = BuckyError; - - fn try_from(mut value: protos::Director) -> BuckyResult { - Ok(Self { - id: ProtobufCodecHelper::decode_buf(value.take_id())?, - right: value.get_right() as u8, - }) - } -} - -impl TryFrom<&Director> for protos::Director { - type Error = BuckyError; - - fn try_from(value: &Director) -> BuckyResult { - let mut ret = Self::new(); - ret.set_id(value.id.to_vec()?); - ret.set_right(value.right as u32); - - Ok(ret) - } -} - -impl TryFrom for OrgMember { - type Error = BuckyError; - - fn try_from(mut value: protos::OrgMember) -> BuckyResult { - Ok(Self { - id: ProtobufCodecHelper::decode_buf(value.take_id())?, - right: value.get_right() as u8, - shares: value.get_shares(), - }) - } -} - -impl TryFrom<&OrgMember> for protos::OrgMember { - type Error = BuckyError; - - fn try_from(value: &OrgMember) -> BuckyResult { - let mut ret = Self::new(); - ret.set_id(value.id.to_vec()?); - ret.set_right(value.right as u32); - ret.set_shares(value.shares); - - Ok(ret) - } -} - -impl TryFrom for OrgBodyContent { - type Error = BuckyError; - - fn try_from(mut value: protos::OrgBodyContent) -> BuckyResult { - Ok(Self { - members: ProtobufCodecHelper::decode_nested_list(value.take_members())?, - directors: ProtobufCodecHelper::decode_nested_list(value.take_directors())?, - total_equity: value.total_equity, - }) - } -} - -impl TryFrom<&OrgBodyContent> for protos::OrgBodyContent { - type Error = BuckyError; - - fn try_from(value: &OrgBodyContent) -> BuckyResult { - let mut ret = Self::new(); - ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); - ret.set_directors(ProtobufCodecHelper::encode_nested_list(&value.directors)?); - ret.set_total_equity(value.total_equity); - - Ok(ret) - } -} - -crate::inner_impl_default_protobuf_raw_codec!(OrgBodyContent); - -pub type OrgType = NamedObjType; -pub type OrgBuilder = NamedObjectBuilder; - -pub type OrgDesc = NamedObjectDesc; -pub type OrgId = NamedObjectId; -pub type Org = NamedObjectBase; - -impl OrgDesc { - pub fn action_id(&self) -> OrgId { - OrgId::try_from(self.calculate_id()).unwrap() - } -} - -impl NamedObjectBase { - pub fn new(members: Vec, directors: Vec) -> OrgBuilder { - let desc_content = OrgDescContent {}; - let body_content = OrgBodyContent { - members, - directors, - total_equity: 0, - }; - OrgBuilder::new(desc_content, body_content) - } - - pub fn members(&self) -> &Vec { - &self.body().as_ref().unwrap().content().members - } - - pub fn members_mut(&mut self) -> &mut Vec { - &mut self.body_mut().as_mut().unwrap().content_mut().members - } -} - -#[cfg(test)] -mod test { - use crate::*; - //use std::path::Path; - - #[test] - fn org() { - let action = Org::new(vec![], vec![]).build(); - - // let p = Path::new("f:\\temp\\org.obj"); - // if p.parent().unwrap().exists() { - // action.clone().encode_to_file(p, false); - // } - - let buf = action.to_vec().unwrap(); - let _obj = Org::clone_from_slice(&buf).unwrap(); - } -} diff --git a/src/component/cyfs-base/src/objects/simple_group.rs b/src/component/cyfs-base/src/objects/simple_group.rs deleted file mode 100644 index 9bbdf5e4f..000000000 --- a/src/component/cyfs-base/src/objects/simple_group.rs +++ /dev/null @@ -1,175 +0,0 @@ -use crate::*; - -use std::convert::TryFrom; -use std::str::FromStr; - -#[derive(Clone, Debug, RawEncode, RawDecode)] -pub struct SimpleGroupDescContent {} - -impl DescContent for SimpleGroupDescContent { - fn obj_type() -> u16 { - ObjectTypeCode::SimpleGroup.into() - } - - type OwnerType = SubDescNone; - type AreaType = Option; - type AuthorType = SubDescNone; - type PublicKeyType = MNPublicKey; -} - -#[derive(Clone, Debug)] -pub struct SimpleGroupBodyContent { - members: Vec, - ood_list: Vec, - ood_work_mode: Option, -} - -impl BodyContent for SimpleGroupBodyContent { - fn format(&self) -> u8 { - OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF - } -} - -impl SimpleGroupBodyContent { - pub fn new( - members: Vec, - ood_work_mode: OODWorkMode, - ood_list: Vec, - ) -> Self { - Self { - members, - ood_work_mode: Some(ood_work_mode), - ood_list, - } - } - - pub fn members(&self) -> &Vec { - &self.members - } - - pub fn members_mut(&mut self) -> &mut Vec { - &mut self.members - } - - pub fn ood_list(&self) -> &Vec { - &self.ood_list - } - - pub fn ood_list_mut(&mut self) -> &mut Vec { - &mut self.ood_list - } - - pub fn ood_work_mode(&self) -> OODWorkMode { - self.ood_work_mode - .clone() - .unwrap_or(OODWorkMode::Standalone) - } - - pub fn set_ood_work_mode(&mut self, ood_work_mode: OODWorkMode) { - self.ood_work_mode = Some(ood_work_mode); - } -} - -// body使用protobuf编解码 -impl TryFrom for SimpleGroupBodyContent { - type Error = BuckyError; - - fn try_from(mut value: protos::SimpleGroupBodyContent) -> BuckyResult { - let mut ret = Self { - members: ProtobufCodecHelper::decode_buf_list(value.take_members())?, - ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, - ood_work_mode: None, - }; - - if value.has_ood_work_mode() { - ret.ood_work_mode = Some(OODWorkMode::from_str(value.get_ood_work_mode())?); - } - - Ok(ret) - } -} - -impl TryFrom<&SimpleGroupBodyContent> for protos::SimpleGroupBodyContent { - type Error = BuckyError; - - fn try_from(value: &SimpleGroupBodyContent) -> BuckyResult { - let mut ret = Self::new(); - - ret.set_members(ProtobufCodecHelper::encode_buf_list(&value.members)?); - ret.set_ood_list(ProtobufCodecHelper::encode_buf_list(&value.ood_list)?); - - if let Some(ood_work_mode) = &value.ood_work_mode { - ret.set_ood_work_mode(ood_work_mode.to_string()); - } - - Ok(ret) - } -} - -crate::inner_impl_default_protobuf_raw_codec!(SimpleGroupBodyContent); - -pub type SimpleGroupType = NamedObjType; -pub type SimpleGroupBuilder = NamedObjectBuilder; - -pub type SimpleGroupDesc = NamedObjectDesc; -pub type SimpleGroupId = NamedObjectId; -pub type SimpleGroup = NamedObjectBase; - -impl SimpleGroupDesc { - pub fn simple_group_id(&self) -> SimpleGroupId { - SimpleGroupId::try_from(self.calculate_id()).unwrap() - } -} - -impl SimpleGroup { - pub fn new( - threshold: u8, - owners: Vec, - members: Vec, - ood_work_mode: OODWorkMode, - ood_list: Vec, - area: Area, - ) -> SimpleGroupBuilder { - let desc_content = SimpleGroupDescContent {}; - - let body_content = SimpleGroupBodyContent::new(members, ood_work_mode, ood_list); - - SimpleGroupBuilder::new(desc_content, body_content) - .area(area) - .public_key((threshold, owners)) - } -} - -#[cfg(test)] -mod test { - use crate::*; - - #[test] - fn simple_group() { - let threshold = 0; - - let members = vec![ObjectId::default()]; - - let ood_list = vec![DeviceId::default()]; - - let obj = SimpleGroup::new( - threshold, - vec![], - members, - OODWorkMode::Standalone, - ood_list, - Area::default(), - ) - .build(); - // let p = Path::new("f:\\temp\\simple_group.obj"); - // if p.parent().unwrap().exists() { - // obj.clone().encode_to_file(p, false); - // } - - let buf = obj.to_vec().unwrap(); - - let decode_obj = SimpleGroup::clone_from_slice(&buf).unwrap(); - - assert!(obj.desc().simple_group_id() == decode_obj.desc().simple_group_id()); - } -} diff --git a/src/component/cyfs-base/src/objects/standard.rs b/src/component/cyfs-base/src/objects/standard.rs index cae3bd847..6d84b31c4 100644 --- a/src/component/cyfs-base/src/objects/standard.rs +++ b/src/component/cyfs-base/src/objects/standard.rs @@ -4,8 +4,8 @@ use crate::*; pub enum StandardObject { Device(Device), People(People), - SimpleGroup(SimpleGroup), - Org(Org), + SimpleGroup, + Org, AppGroup(AppGroup), UnionAccount(UnionAccount), ChunkId(ChunkId), @@ -17,6 +17,7 @@ pub enum StandardObject { Action(Action), ObjectMap(ObjectMap), Contract(Contract), + Group(Group), } #[macro_export] @@ -25,8 +26,7 @@ macro_rules! match_standard_obj { match $on { StandardObject::Device($o) => $body, StandardObject::People($o) => $body, - StandardObject::SimpleGroup($o) => $body, - StandardObject::Org($o) => $body, + StandardObject::Group($o) => $body, StandardObject::AppGroup($o) => $body, StandardObject::UnionAccount($o) => $body, StandardObject::ChunkId($chunk_id) => $chunk_body, @@ -38,6 +38,10 @@ macro_rules! match_standard_obj { StandardObject::Action($o) => $body, StandardObject::ObjectMap($o) => $body, StandardObject::Contract($o) => $body, + StandardObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } }; } @@ -64,7 +68,7 @@ macro_rules! match_standard_pubkey_obj { match $on { StandardObject::Device($o) => $body, StandardObject::People($o) => $body, - StandardObject::SimpleGroup($o) => $body, + // StandardObject::Group($o) => $body, _ => $other_body, } }; @@ -83,7 +87,16 @@ macro_rules! match_standard_author_obj { macro_rules! match_standard_ood_list_obj { ($on:ident, $o:ident, $body:tt, $other_body:tt) => { match $on { - StandardObject::SimpleGroup($o) => $body, + StandardObject::Group($o) => $body, + StandardObject::People($o) => $body, + _ => $other_body, + } + }; +} + +macro_rules! match_standard_ood_work_mode_obj { + ($on:ident, $o:ident, $body:tt, $other_body:tt) => { + match $on { StandardObject::People($o) => $body, _ => $other_body, } @@ -152,7 +165,7 @@ impl StandardObject { } pub fn ood_work_mode(&self) -> BuckyResult { - match_standard_ood_list_obj!( + match_standard_ood_work_mode_obj!( self, o, { @@ -187,14 +200,8 @@ impl StandardObject { } _ => unreachable!(), }, - Self::SimpleGroup(o) => match other { - Self::SimpleGroup(other) => { - *o.body_mut() = other.body().clone(); - } - _ => unreachable!(), - }, - Self::Org(o) => match other { - Self::Org(other) => { + Self::Group(o) => match other { + Self::Group(other) => { *o.body_mut() = other.body().clone(); } _ => unreachable!(), @@ -262,6 +269,10 @@ impl StandardObject { Self::ChunkId(_) => { unreachable!(); } + Self::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + Self::Org => panic!("Org is deprecated, you can use the Group."), } } } @@ -271,8 +282,7 @@ impl RawEncode for StandardObject { match self { StandardObject::Device(o) => o.raw_measure(purpose), StandardObject::People(o) => o.raw_measure(purpose), - StandardObject::SimpleGroup(o) => o.raw_measure(purpose), - StandardObject::Org(o) => o.raw_measure(purpose), + StandardObject::Group(o) => o.raw_measure(purpose), StandardObject::AppGroup(o) => o.raw_measure(purpose), StandardObject::UnionAccount(o) => o.raw_measure(purpose), StandardObject::ChunkId(o) => o.raw_measure(purpose), @@ -284,6 +294,10 @@ impl RawEncode for StandardObject { StandardObject::Action(o) => o.raw_measure(purpose), StandardObject::ObjectMap(o) => o.raw_measure(purpose), StandardObject::Contract(o) => o.raw_measure(purpose), + StandardObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } } @@ -295,8 +309,7 @@ impl RawEncode for StandardObject { match self { StandardObject::Device(o) => o.raw_encode(buf, purpose), StandardObject::People(o) => o.raw_encode(buf, purpose), - StandardObject::SimpleGroup(o) => o.raw_encode(buf, purpose), - StandardObject::Org(o) => o.raw_encode(buf, purpose), + StandardObject::Group(o) => o.raw_encode(buf, purpose), StandardObject::AppGroup(o) => o.raw_encode(buf, purpose), StandardObject::UnionAccount(o) => o.raw_encode(buf, purpose), StandardObject::ChunkId(o) => o.raw_encode(buf, purpose), @@ -308,6 +321,10 @@ impl RawEncode for StandardObject { StandardObject::Action(o) => o.raw_encode(buf, purpose), StandardObject::ObjectMap(o) => o.raw_encode(buf, purpose), StandardObject::Contract(o) => o.raw_encode(buf, purpose), + StandardObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } } } @@ -327,10 +344,8 @@ impl<'de> RawDecode<'de> for StandardObject { ObjectTypeCode::People => { People::raw_decode(buf).map(|(obj, buf)| (StandardObject::People(obj), buf)) } - ObjectTypeCode::SimpleGroup => SimpleGroup::raw_decode(buf) - .map(|(obj, buf)| (StandardObject::SimpleGroup(obj), buf)), - ObjectTypeCode::Org => { - Org::raw_decode(buf).map(|(obj, buf)| (StandardObject::Org(obj), buf)) + ObjectTypeCode::Group => { + Group::raw_decode(buf).map(|(obj, buf)| (StandardObject::Group(obj), buf)) } ObjectTypeCode::AppGroup => { AppGroup::raw_decode(buf).map(|(obj, buf)| (StandardObject::AppGroup(obj), buf)) diff --git a/src/component/cyfs-base/src/objects/tx.rs b/src/component/cyfs-base/src/objects/tx.rs index 8574f3a3f..7fdad3244 100644 --- a/src/component/cyfs-base/src/objects/tx.rs +++ b/src/component/cyfs-base/src/objects/tx.rs @@ -7,7 +7,7 @@ use std::convert::TryFrom; #[derive(Clone, Debug, RawEncode, RawDecode)] pub enum TxCondition { //时间 -//BTC 交易确认 + //BTC 交易确认 } #[derive(Copy, Clone, Debug, Serialize, Deserialize, RawEncode, RawDecode, Eq, PartialEq)] @@ -38,7 +38,7 @@ impl ProtobufTransform> for CoinTokenId { pub enum TxCaller { People(PeopleDesc), Device(DeviceDesc), - Group(SimpleGroupDesc), + Group(GroupDesc), Union(UnionAccountDesc), Miner(ObjectId), Id(ObjectId), @@ -50,7 +50,7 @@ impl TryFrom<&StandardObject> for TxCaller { match obj { StandardObject::People(desc) => Ok(Self::People(desc.desc().clone())), StandardObject::Device(desc) => Ok(Self::Device(desc.desc().clone())), - StandardObject::SimpleGroup(desc) => Ok(Self::Group(desc.desc().clone())), + StandardObject::Group(desc) => Ok(Self::Group(desc.desc().clone())), StandardObject::UnionAccount(desc) => Ok(Self::Union(desc.desc().clone())), _ => Err(BuckyError::new(BuckyErrorCode::Failed, "Failed")), } diff --git a/src/component/cyfs-base/src/objects/unique_id.rs b/src/component/cyfs-base/src/objects/unique_id.rs index 1d28aa561..afe8b72b9 100644 --- a/src/component/cyfs-base/src/objects/unique_id.rs +++ b/src/component/cyfs-base/src/objects/unique_id.rs @@ -1,9 +1,9 @@ use crate::*; +use base58::ToBase58; use generic_array::typenum::{marker_traits::Unsigned, U16}; use generic_array::GenericArray; use std::fmt; -use base58::ToBase58; // unique id in const info #[derive(Clone, Eq, PartialEq)] @@ -80,6 +80,14 @@ impl UniqueId { sha256.input(src); Self::create(&sha256.result()) } + + pub fn create_with_random() -> Self { + let mut id = Self::default(); + let (l, h) = id.as_mut_slice().split_at_mut(8); + l.copy_from_slice(&rand::random::().to_be_bytes()); + h.copy_from_slice(&rand::random::().to_be_bytes()); + id + } } impl RawFixedBytes for UniqueId { @@ -181,4 +189,4 @@ mod test { let hash = id.raw_hash_value().unwrap(); println!("hash: {}", hash); } -} \ No newline at end of file +} diff --git a/src/component/cyfs-stack/src/front/protocol.rs b/src/component/cyfs-stack/src/front/protocol.rs index b925add11..27718e51d 100644 --- a/src/component/cyfs-stack/src/front/protocol.rs +++ b/src/component/cyfs-stack/src/front/protocol.rs @@ -709,7 +709,7 @@ impl FrontProtocolHandler { match seg_object.obj_type_code() { ObjectTypeCode::Device | ObjectTypeCode::People - | ObjectTypeCode::SimpleGroup => { + | ObjectTypeCode::Group => { // treat as two seg mode target = Some(seg_object); target_dec_id = Self::parse_dec_seg(url, &segs, 1)?; diff --git a/src/component/cyfs-stack/src/resolver/ood_resolver.rs b/src/component/cyfs-stack/src/resolver/ood_resolver.rs index e39088270..a43135c74 100644 --- a/src/component/cyfs-stack/src/resolver/ood_resolver.rs +++ b/src/component/cyfs-stack/src/resolver/ood_resolver.rs @@ -104,7 +104,7 @@ impl OodResolver { let obj_type = object_id.obj_type_code(); // People,SimpleGroup 对象存在ood_list - if obj_type == ObjectTypeCode::People || obj_type == ObjectTypeCode::SimpleGroup { + if obj_type == ObjectTypeCode::People || obj_type == ObjectTypeCode::Group { match object.ood_list() { Ok(list) => { if list.len() > 0 { @@ -230,7 +230,7 @@ impl OodResolver { let obj_type = object_id.obj_type_code(); // People,SimpleGroup 对象存在ood_list - if obj_type == ObjectTypeCode::People || obj_type == ObjectTypeCode::SimpleGroup { + if obj_type == ObjectTypeCode::People || obj_type == ObjectTypeCode::Group { if object.is_some() { match object.as_ref().unwrap().ood_list() { Ok(list) => { @@ -335,4 +335,4 @@ impl OodResolver { } } } -} \ No newline at end of file +} diff --git a/src/component/cyfs-stack/src/util_api/local/local.rs b/src/component/cyfs-stack/src/util_api/local/local.rs index 098a2590c..985171548 100644 --- a/src/component/cyfs-stack/src/util_api/local/local.rs +++ b/src/component/cyfs-stack/src/util_api/local/local.rs @@ -116,9 +116,7 @@ impl UtilLocalService { let obj_type = object_id.obj_type_code(); let zone = match obj_type { - ObjectTypeCode::Device - | ObjectTypeCode::People - | ObjectTypeCode::SimpleGroup => { + ObjectTypeCode::Device | ObjectTypeCode::People | ObjectTypeCode::Group => { let zone = self .zone_manager .resolve_zone(&object_id, req.object_raw) diff --git a/src/component/cyfs-stack/src/zone/target_zone.rs b/src/component/cyfs-stack/src/zone/target_zone.rs index 5b471bcf7..ff4d005b4 100644 --- a/src/component/cyfs-stack/src/zone/target_zone.rs +++ b/src/component/cyfs-stack/src/zone/target_zone.rs @@ -48,7 +48,7 @@ impl TargetZoneManager { Ok((zone.zone_id(), device_id)) } - ObjectTypeCode::People | ObjectTypeCode::SimpleGroup => { + ObjectTypeCode::People | ObjectTypeCode::Group => { let zone = self.zone_manager.resolve_zone(target, object_raw).await?; Ok((zone.zone_id(), zone.ood().clone())) } @@ -178,7 +178,7 @@ impl TargetZoneManager { } } - ObjectTypeCode::People | ObjectTypeCode::SimpleGroup => { + ObjectTypeCode::People | ObjectTypeCode::Group => { if info.owner_id == *target { let ret = TargetZoneInfo { is_current_zone: true, diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 5f47fa983..6819b991d 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -418,7 +418,7 @@ impl ZoneManager { // 目前owner只支持people和simplegroup // People,SimpleGroup对象存在ood_list match obj_type { - ObjectTypeCode::People | ObjectTypeCode::SimpleGroup => { + ObjectTypeCode::People | ObjectTypeCode::Group => { // 查找owner对象 info!("will search owner: type={:?}, {}", obj_type, owner_id); let object = self.search_object(&owner_id).await?; @@ -642,7 +642,7 @@ impl ZoneManager { // 目前owner只支持people和simplegroup // People,SimpleGroup对象存在ood_list - if obj_type == ObjectTypeCode::People || obj_type == ObjectTypeCode::SimpleGroup { + if obj_type == ObjectTypeCode::People || obj_type == ObjectTypeCode::Group { match owner_object.ood_list() { Ok(list) => { if list.len() > 0 { @@ -730,7 +730,7 @@ impl ZoneManager { })?; match object_id.obj_type_code() { - ObjectTypeCode::People | ObjectTypeCode::SimpleGroup => { + ObjectTypeCode::People | ObjectTypeCode::Group => { // 需要校验签名 let obj = Arc::new(obj); diff --git a/src/meta/cyfs-meta/src/executor/context/object.rs b/src/meta/cyfs-meta/src/executor/context/object.rs index 07c4164d1..e747fe5ae 100644 --- a/src/meta/cyfs-meta/src/executor/context/object.rs +++ b/src/meta/cyfs-meta/src/executor/context/object.rs @@ -45,9 +45,6 @@ pub fn id_from_desc(desc: &SavedMetaObject) -> ObjectId { SavedMetaObject::Data(obj) => { obj.id.clone() }, - SavedMetaObject::Org(org) => { - org.desc().calculate_id() - }, SavedMetaObject::MinerGroup(group) => { group.desc().calculate_id() }, @@ -57,6 +54,10 @@ pub fn id_from_desc(desc: &SavedMetaObject) -> ObjectId { SavedMetaObject::SNService(service) => { service.desc().calculate_id() } + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), } } diff --git a/src/meta/cyfs-meta/src/executor/tx_proc/account_proc.rs b/src/meta/cyfs-meta/src/executor/tx_proc/account_proc.rs index e55fac2b3..07ab08014 100644 --- a/src/meta/cyfs-meta/src/executor/tx_proc/account_proc.rs +++ b/src/meta/cyfs-meta/src/executor/tx_proc/account_proc.rs @@ -1,18 +1,27 @@ -use cyfs_base::*; use crate::executor::context; +use crate::executor::context::UnionAccountState; use crate::executor::transaction::ExecuteContext; use crate::executor::tx_executor::TxExecutor; use crate::helper::{get_meta_err_code, ArcWeakHelper}; -use std::convert::TryFrom; -use crate::executor::context::UnionAccountState; -use cyfs_base_meta::*; -use crate::{State}; use crate::meta_backend::MetaBackend; +use crate::State; +use cyfs_base::*; +use cyfs_base_meta::*; +use std::convert::TryFrom; impl TxExecutor { - pub async fn execute_trans_balance(&self, context: &mut ExecuteContext, fee_counter: &mut context::FeeCounter, tx: &TransBalanceTx, _backend: &mut MetaBackend, _config: &evm::Config) -> BuckyResult> { + pub async fn execute_trans_balance( + &self, + context: &mut ExecuteContext, + fee_counter: &mut context::FeeCounter, + tx: &TransBalanceTx, + _backend: &mut MetaBackend, + _config: &evm::Config, + ) -> BuckyResult> { if let context::AccountMethods::Single(methods) = context.caller().methods() { - let logs = methods.trans_balance(fee_counter, &tx.ctid, &tx.to/*, backend, config*/).await?; + let logs = methods + .trans_balance(fee_counter, &tx.ctid, &tx.to /*, backend, config*/) + .await?; // 下边是扣除租金的相关逻辑 for (to_id, _v) in &tx.to { @@ -32,16 +41,30 @@ impl TxExecutor { // } // } - self.rent_manager.to_rc()?.check_and_deduct_rent_arrears_for_desc(context.block(), &to_id, &tx.ctid).await?; + self.rent_manager + .to_rc()? + .check_and_deduct_rent_arrears_for_desc(context.block(), &to_id, &tx.ctid) + .await?; let owned_names = self.ref_state.to_rc()?.get_owned_names(to_id).await?; for name in owned_names { - let mut name_state = self.ref_state.to_rc()?.get_name_state(name.as_str()).await?; + let mut name_state = self + .ref_state + .to_rc()? + .get_name_state(name.as_str()) + .await?; if name_state == NameState::Lock { - let rent_state = self.rent_manager.to_rc()?.check_and_deduct_rent_arrears_for_name(context.block(), name.as_str()).await?; + let rent_state = self + .rent_manager + .to_rc()? + .check_and_deduct_rent_arrears_for_name(context.block(), name.as_str()) + .await?; if rent_state.rent_arrears == 0 { name_state = NameState::Normal; - self.ref_state.to_rc()?.update_name_state(name.as_str(), name_state).await?; + self.ref_state + .to_rc()? + .update_name_state(name.as_str(), name_state) + .await?; } } } @@ -56,38 +79,30 @@ impl TxExecutor { // break; // } // } - } + } Ok(logs) } else { Err(crate::meta_err!(ERROR_INVALID)) } } - pub async fn execute_withdraw_to_owner(&self, - context: &mut ExecuteContext, - _fee_counter: &mut context::FeeCounter, - tx: &WithdrawToOwner) -> BuckyResult<()> { + pub async fn execute_withdraw_to_owner( + &self, + context: &mut ExecuteContext, + _fee_counter: &mut context::FeeCounter, + tx: &WithdrawToOwner, + ) -> BuckyResult<()> { let beneficiary = self.ref_state.to_rc()?.get_beneficiary(&tx.id).await?; let owner = if beneficiary != tx.id { Some(beneficiary) } else { let desc_obj_ret = self.ref_state.to_rc()?.get_obj_desc(&tx.id).await?; match desc_obj_ret { - SavedMetaObject::Device(device) => { - device.desc().owner().clone() - } - SavedMetaObject::People(_) => { - None - } - SavedMetaObject::UnionAccount(_) => { - None - } - SavedMetaObject::Group(_) => { - None - } - SavedMetaObject::File(file) => { - file.desc().owner().clone() - } + SavedMetaObject::Device(device) => device.desc().owner().clone(), + SavedMetaObject::People(_) => None, + SavedMetaObject::UnionAccount(_) => None, + SavedMetaObject::Group(_) => None, + SavedMetaObject::File(file) => file.desc().owner().clone(), SavedMetaObject::Data(data) => { let ret = AnyNamedObject::clone_from_slice(data.data.as_slice()); if ret.is_ok() { @@ -96,84 +111,95 @@ impl TxExecutor { None } } - SavedMetaObject::Org(_) => { - None - } - SavedMetaObject::MinerGroup(_) => { - None - } - SavedMetaObject::SNService(_) => { - None - } - SavedMetaObject::Contract(contract) => { - contract.desc().owner().clone() + SavedMetaObject::MinerGroup(_) => None, + SavedMetaObject::SNService(_) => None, + SavedMetaObject::Contract(contract) => contract.desc().owner().clone(), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), } }; if owner.is_some() && owner.as_ref().unwrap() == context.caller().id() { - self.ref_state.to_rc()?.dec_balance(&tx.ctid, &tx.id, tx.value).await?; - self.ref_state.to_rc()?.inc_balance(&tx.ctid, &context.caller().id(), tx.value).await?; - return Ok(()) + self.ref_state + .to_rc()? + .dec_balance(&tx.ctid, &tx.id, tx.value) + .await?; + self.ref_state + .to_rc()? + .inc_balance(&tx.ctid, &context.caller().id(), tx.value) + .await?; + return Ok(()); } Err(crate::meta_err!(ERROR_INVALID)) } -//理解下面逻辑需了解ffs-meta的闪电网络工作原理 -// 1.双方决定建立union account -// 2.由任一方执行CreateUnionTX,在Meta上建立union account(需要持续付租金) -// 3.另一方可按需要执行TransBalanceTX,在union account中增加余额 -// 4.双方进行链下交易,不断地创建有双签名的SetUnionTx,Set操作的left + right的和总是为0 -// 5.任何一方都可以在必要的时候,将有双签名的SetUnionTx上链条,只有最新的SetUnionTx会生效 -// 操作完成后,UnionAccount中的余额状态会公开的改变 -// 6.任何一方,都可以在必要的时候,调用带return flag的SetUnionTx,将UnionAccount中所属自己的余额反还。 -// 改操作在上链后永远不会立刻生效,而是需要等待一定的时间后才会操作UnionAccount -// 7.当一方发现另一方提交了单签名的SetUnionTx,可以提交最新的,有多签名的SetUnionTx来保障自己的收益 -// 综上:使用闪电网络,需要最少3个操作,创建->使用->返还 -// 问题:union account的租金谁出? 还是和Address Account一样,是不需要租金,永久保存的特殊存在? -// 扩展:包含超过2个object的超级union account? - - pub async fn execute_create_union(&self - , context: &mut ExecuteContext - , fee_counter: &mut context::FeeCounter - , tx: &CreateUnionTx) -> BuckyResult<()> { + //理解下面逻辑需了解ffs-meta的闪电网络工作原理 + // 1.双方决定建立union account + // 2.由任一方执行CreateUnionTX,在Meta上建立union account(需要持续付租金) + // 3.另一方可按需要执行TransBalanceTX,在union account中增加余额 + // 4.双方进行链下交易,不断地创建有双签名的SetUnionTx,Set操作的left + right的和总是为0 + // 5.任何一方都可以在必要的时候,将有双签名的SetUnionTx上链条,只有最新的SetUnionTx会生效 + // 操作完成后,UnionAccount中的余额状态会公开的改变 + // 6.任何一方,都可以在必要的时候,调用带return flag的SetUnionTx,将UnionAccount中所属自己的余额反还。 + // 改操作在上链后永远不会立刻生效,而是需要等待一定的时间后才会操作UnionAccount + // 7.当一方发现另一方提交了单签名的SetUnionTx,可以提交最新的,有多签名的SetUnionTx来保障自己的收益 + // 综上:使用闪电网络,需要最少3个操作,创建->使用->返还 + // 问题:union account的租金谁出? 还是和Address Account一样,是不需要租金,永久保存的特殊存在? + // 扩展:包含超过2个object的超级union account? + + pub async fn execute_create_union( + &self, + context: &mut ExecuteContext, + fee_counter: &mut context::FeeCounter, + tx: &CreateUnionTx, + ) -> BuckyResult<()> { let union_account = &tx.body.account; let mut public_key_list = Vec::new(); - let ret = context.ref_state().to_rc()?.get_obj_desc(&union_account.desc().content().left()).await; + let ret = context + .ref_state() + .to_rc()? + .get_obj_desc(&union_account.desc().content().left()) + .await; if let Err(err) = &ret { let err_code = get_meta_err_code(err)?; return if err_code == ERROR_NOT_FOUND { Err(crate::meta_err!(ERROR_CANT_FIND_LEFT_USER_DESC)) } else { Err(crate::meta_err2!(err_code, err.msg())) - } + }; } let left_account = ret.unwrap(); match left_account { - SavedMetaObject::Device(device) => { - public_key_list.push((union_account.desc().content().left().clone(), device.desc().public_key().clone())) - } + SavedMetaObject::Device(device) => public_key_list.push(( + union_account.desc().content().left().clone(), + device.desc().public_key().clone(), + )), // SavedMetaObject::People(people) => { // public_key_list.push((union_account.desc().content().right().clone(), people.desc())) // } - _ => { - return Err(crate::meta_err!(ERROR_LEFT_ACCOUNT_TYPE)) - } + _ => return Err(crate::meta_err!(ERROR_LEFT_ACCOUNT_TYPE)), } - let ret = context.ref_state().to_rc()?.get_obj_desc(&union_account.desc().content().right()).await; + let ret = context + .ref_state() + .to_rc()? + .get_obj_desc(&union_account.desc().content().right()) + .await; if let Err(err) = &ret { let err_code = get_meta_err_code(err)?; return if err_code == ERROR_NOT_FOUND { Err(crate::meta_err!(ERROR_CANT_FIND_RIGHT_USER_DESC)) } else { Err(crate::meta_err2!(err_code, err.msg())) - } + }; } let right_account = ret.unwrap(); match right_account { - SavedMetaObject::Device(device) => { - public_key_list.push((union_account.desc().content().right().clone(), device.desc().public_key().clone())) - } + SavedMetaObject::Device(device) => public_key_list.push(( + union_account.desc().content().right().clone(), + device.desc().public_key().clone(), + )), // SavedMetaObject::People(people) => { // public_key_list.push((union_account.desc().content().right().clone(), people.desc())) // } @@ -187,28 +213,71 @@ impl TxExecutor { } let account_id = tx.body.account.desc().calculate_id(); - context.ref_state().to_rc()?.create_obj_desc(&account_id, &SavedMetaObject::try_from(StandardObject::UnionAccount(tx.body.account.clone()))?).await?; + context + .ref_state() + .to_rc()? + .create_obj_desc( + &account_id, + &SavedMetaObject::try_from(StandardObject::UnionAccount(tx.body.account.clone()))?, + ) + .await?; //转账 if tx.body.left_balance > 0 { - self.ref_state.to_rc()?.dec_balance(&tx.body.ctid, &union_account.desc().content().left(), tx.body.left_balance).await?; - let account_state = UnionAccountState::new(union_account.desc(), &self.ref_state.to_rc()?)?; - account_state.deposit(fee_counter, &union_account.desc().content().left(), &tx.body.ctid, tx.body.left_balance).await?; + self.ref_state + .to_rc()? + .dec_balance( + &tx.body.ctid, + &union_account.desc().content().left(), + tx.body.left_balance, + ) + .await?; + let account_state = + UnionAccountState::new(union_account.desc(), &self.ref_state.to_rc()?)?; + account_state + .deposit( + fee_counter, + &union_account.desc().content().left(), + &tx.body.ctid, + tx.body.left_balance, + ) + .await?; } if tx.body.right_balance > 0 { - self.ref_state.to_rc()?.dec_balance(&tx.body.ctid, &union_account.desc().content().right(), tx.body.right_balance).await?; - let account_state = UnionAccountState::new(union_account.desc(), &self.ref_state.to_rc()?)?; - account_state.deposit(fee_counter, &union_account.desc().content().right(), &tx.body.ctid, tx.body.right_balance).await?; + self.ref_state + .to_rc()? + .dec_balance( + &tx.body.ctid, + &union_account.desc().content().right(), + tx.body.right_balance, + ) + .await?; + let account_state = + UnionAccountState::new(union_account.desc(), &self.ref_state.to_rc()?)?; + account_state + .deposit( + fee_counter, + &union_account.desc().content().right(), + &tx.body.ctid, + tx.body.right_balance, + ) + .await?; } Ok(()) } - pub async fn execute_deviate_union(&self - , context: &mut ExecuteContext - , fee_counter: &mut context::FeeCounter - , tx: &DeviateUnionTx) -> BuckyResult<()> { + pub async fn execute_deviate_union( + &self, + context: &mut ExecuteContext, + fee_counter: &mut context::FeeCounter, + tx: &DeviateUnionTx, + ) -> BuckyResult<()> { //获取联合账户信息 - let ret = context.ref_state().to_rc()?.get_obj_desc(&tx.body.union).await?; + let ret = context + .ref_state() + .to_rc()? + .get_obj_desc(&tx.body.union) + .await?; let union_account = if let SavedMetaObject::UnionAccount(union_account) = ret { union_account } else { @@ -216,42 +285,50 @@ impl TxExecutor { }; let mut public_key_list = Vec::new(); - let ret = context.ref_state().to_rc()?.get_obj_desc(&union_account.desc().content().left()).await; + let ret = context + .ref_state() + .to_rc()? + .get_obj_desc(&union_account.desc().content().left()) + .await; if let Err(err) = &ret { let err_code = get_meta_err_code(err)?; return if err_code == ERROR_NOT_FOUND { Err(crate::meta_err!(ERROR_CANT_FIND_LEFT_USER_DESC)) } else { Err(crate::meta_err2!(err_code, err.msg())) - } + }; } let left_account = ret.unwrap(); match left_account { - SavedMetaObject::Device(device) => { - public_key_list.push((union_account.desc().content().left().clone(), device.desc().public_key().clone())) - } + SavedMetaObject::Device(device) => public_key_list.push(( + union_account.desc().content().left().clone(), + device.desc().public_key().clone(), + )), // SavedMetaObject::People(people) => { // public_key_list.push((union_account.desc().content().right().clone(), people.desc())) // } - _ => { - return Err(crate::meta_err!(ERROR_LEFT_ACCOUNT_TYPE)) - } + _ => return Err(crate::meta_err!(ERROR_LEFT_ACCOUNT_TYPE)), } - let ret = context.ref_state().to_rc()?.get_obj_desc(&union_account.desc().content().right()).await; + let ret = context + .ref_state() + .to_rc()? + .get_obj_desc(&union_account.desc().content().right()) + .await; if let Err(err) = &ret { let err_code = get_meta_err_code(err)?; return if err_code == ERROR_NOT_FOUND { Err(crate::meta_err!(ERROR_CANT_FIND_RIGHT_USER_DESC)) } else { Err(crate::meta_err2!(err_code, err.msg())) - } + }; } let right_account = ret.unwrap(); match right_account { - SavedMetaObject::Device(device) => { - public_key_list.push((union_account.desc().content().right().clone(), device.desc().public_key().clone())) - } + SavedMetaObject::Device(device) => public_key_list.push(( + union_account.desc().content().right().clone(), + device.desc().public_key().clone(), + )), // SavedMetaObject::People(people) => { // public_key_list.push((union_account.desc().content().right().clone(), people.desc())) // } @@ -265,16 +342,19 @@ impl TxExecutor { } let account_state = UnionAccountState::new(union_account.desc(), &self.ref_state.to_rc()?)?; - account_state.deviate(fee_counter, &tx.body.ctid, tx.body.deviation, tx.body.seq).await?; + account_state + .deviate(fee_counter, &tx.body.ctid, tx.body.deviation, tx.body.seq) + .await?; Ok(()) } - - pub async fn execute_withdraw_from_union(&self - , context: &mut ExecuteContext - , _fee_counter: &mut context::FeeCounter - , tx: &WithdrawFromUnionTx) -> BuckyResult<()> { + pub async fn execute_withdraw_from_union( + &self, + context: &mut ExecuteContext, + _fee_counter: &mut context::FeeCounter, + tx: &WithdrawFromUnionTx, + ) -> BuckyResult<()> { if let context::AccountMethods::Single(_) = context.caller().methods() { //获取联合账户信息 let ret = context.ref_state().to_rc()?.get_obj_desc(&tx.union).await?; @@ -285,15 +365,16 @@ impl TxExecutor { }; let caller_id = context.caller().id().clone(); - if union_account.desc().content().right() != &caller_id && union_account.desc().content().left() != &caller_id { + if union_account.desc().content().right() != &caller_id + && union_account.desc().content().left() != &caller_id + { return Err(crate::meta_err!(ERROR_ACCESS_DENIED)); } - self.union_withdraw_manager.to_rc()?.withdraw(context.block() - , &tx.union - , &caller_id - , &tx.ctid - , tx.value).await + self.union_withdraw_manager + .to_rc()? + .withdraw(context.block(), &tx.union, &caller_id, &tx.ctid, tx.value) + .await // context::UnionAccountState::load(&tx.union // , &context.ref_state().to_rc()?)? // .withdraw( @@ -308,7 +389,10 @@ impl TxExecutor { // 1. caller就是target本身,有权限 // 2. caller是target的某一层owner,有权限 // 否则都算无权限 - async fn check_permission(context: &mut ExecuteContext, target: &ObjectId) -> BuckyResult { + async fn check_permission( + context: &mut ExecuteContext, + target: &ObjectId, + ) -> BuckyResult { let caller = context.caller().id().clone(); let mut check = target.clone(); loop { @@ -321,15 +405,24 @@ impl TxExecutor { let obj = AnyNamedObject::try_from(desc)?; // 一直找到没有owner的对象为止 if obj.owner().is_none() { - return Ok(false) + return Ok(false); } check = obj.owner().as_ref().unwrap().clone(); } } - pub async fn execute_set_benefi_tx(&self, context: &mut ExecuteContext, _fee_counter: &mut context::FeeCounter, tx: &SetBenefiTx) -> BuckyResult<()> { + pub async fn execute_set_benefi_tx( + &self, + context: &mut ExecuteContext, + _fee_counter: &mut context::FeeCounter, + tx: &SetBenefiTx, + ) -> BuckyResult<()> { // 获取address现在的受益人信息, 没有受益人的情况,benefi是address自己 - let benefi = context.ref_state().to_rc()?.get_beneficiary(&tx.address).await?; + let benefi = context + .ref_state() + .to_rc()? + .get_beneficiary(&tx.address) + .await?; // 检查caller是不是受益人,或者受益人的owner let mut permission = Self::check_permission(context, &benefi).await?; @@ -340,14 +433,20 @@ impl TxExecutor { } if !permission { - return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, "caller is not benefi or benefi`s owner")); + return Err(BuckyError::new( + BuckyErrorCode::PermissionDenied, + "caller is not benefi or benefi`s owner", + )); } // 修改benefi - context.ref_state().to_rc()?.set_beneficiary(&tx.address, &tx.to).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary(&tx.address, &tx.to) + .await?; Ok(()) } - } //Ok(feed),Error(errno) diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 30c5d9510..a31b3c053 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,38 +1,39 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; -use crate::archive_storage::*; use super::context; -use crate::{ViewBalanceResult, State}; +use crate::archive_storage::*; use crate::executor::context::AccountMethods; -use crate::helper::{ArcWeakHelper}; -use cyfs_base::*; +use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; - -struct ViewExecuteContext { +use crate::state_storage::{StateRef, StateWeakRef}; +use crate::{State, ViewBalanceResult}; +use cyfs_base::*; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; -} +struct ViewExecuteContext {} -impl ViewExecuteContext { - -} +impl ViewExecuteContext {} pub struct ViewMethodExecutor { method: M, ref_state: StateWeakRef, ref_archive: ArchiveWeakRef, block: BlockDesc, - evm_config: evm::Config + evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, ref_archive: &ArchiveRef, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + ref_archive: &ArchiveRef, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), ref_archive: ArchiveRef::downgrade(ref_archive), block: block.clone(), - evm_config: evm::Config::istanbul(), // 先把evm的config创建在这里,以后能自己设置了,应该是外边传进来的 + evm_config: evm::Config::istanbul(), // 先把evm的config创建在这里,以后能自己设置了,应该是外边传进来的 } } } @@ -48,14 +49,18 @@ impl ViewMethodExecutor { vec.push((*ctid, account.balance_of(ctid).await?)); } result = ViewBalanceResult::Single(vec) - }, + } AccountMethods::Union(u) => { let mut vec = vec![]; for ctid in &self.method.ctid { - vec.push((*ctid, u.get_union_balance(ctid).await?, u.get_deviation_seq(ctid).await?)); + vec.push(( + *ctid, + u.get_union_balance(ctid).await?, + u.get_deviation_seq(ctid).await?, + )); } result = ViewBalanceResult::Union(vec) - }, + } } Ok(result) @@ -70,7 +75,10 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { - self.ref_state.to_rc()?.get_name_info(&self.method.name).await + self.ref_state + .to_rc()? + .get_name_info(&self.method.name) + .await } } @@ -80,7 +88,11 @@ impl ViewMethodExecutor { match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { Ok(obj) => { let status: u8 = 0/* success*/; - let _ = self.ref_archive.to_rc()?.set_meta_object_stat(&self.method.id, status).await; + let _ = self + .ref_archive + .to_rc()? + .set_meta_object_stat(&self.method.id, status) + .await; match obj { SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), SavedMetaObject::People(obj) => Ok(obj.to_vec()?), @@ -88,19 +100,25 @@ impl ViewMethodExecutor { SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), SavedMetaObject::File(obj) => Ok(obj.to_vec()?), SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::Org(obj) => Ok(obj.to_vec()?), SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), } - }, + } Err(e) => { let status: u8 = 1 /* failed */; - let _ = self.ref_archive.to_rc()?.set_meta_object_stat(&self.method.id, status).await; + let _ = self + .ref_archive + .to_rc()? + .set_meta_object_stat(&self.method.id, status) + .await; return Err(e); - }, - } - + } + } } } @@ -113,37 +131,54 @@ impl ViewMethodExecutor { &self.block, ObjectId::default(), None, - self.evm_config.clone() + self.evm_config.clone(), ); // 这里的gas_limit要怎么设置?为了避免出问题,这里设置一个定值 let view_gas_limit = 100000; - let config= evm::Config::istanbul(); - let state = MemoryStackState::new(StackSubstateMetadata::new(view_gas_limit, &config), &backend); + let config = evm::Config::istanbul(); + let state = MemoryStackState::new( + StackSubstateMetadata::new(view_gas_limit, &config), + &backend, + ); let mut executor = StackExecutor::new(state, &config); - let (ret, value) = executor.transact_call(ObjectId::default(), self.method.address, 0, self.method.data.clone(), view_gas_limit); + let (ret, value) = executor.transact_call( + ObjectId::default(), + self.method.address, + 0, + self.method.data.clone(), + view_gas_limit, + ); Ok(ViewContractResult { ret: evm_reason_to_code(ret) as u32, - value + value, }) } } impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { - let benefi = self.ref_state.to_rc()?.get_beneficiary(&self.method.address).await?; - Ok(ViewBenefiResult{ - address: benefi - }) + let benefi = self + .ref_state + .to_rc()? + .get_beneficiary(&self.method.address) + .await?; + Ok(ViewBenefiResult { address: benefi }) } } impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { - let logs = self.ref_state.to_rc()?.get_log(&self.method.address, self.method.from, self.method.to, &self.method.topics).await?; - Ok(ViewLogResult{ - logs - }) + let logs = self + .ref_state + .to_rc()? + .get_log( + &self.method.address, + self.method.from, + self.method.to, + &self.method.topics, + ) + .await?; + Ok(ViewLogResult { logs }) } } - diff --git a/src/meta/cyfs-meta/src/state_storage/state.rs b/src/meta/cyfs-meta/src/state_storage/state.rs index 8121eefcf..71f58d8f3 100644 --- a/src/meta/cyfs-meta/src/state_storage/state.rs +++ b/src/meta/cyfs-meta/src/state_storage/state.rs @@ -19,9 +19,10 @@ pub struct DescExtra { pub enum AccountInfo { People(PeopleDesc), Device(DeviceDesc), - Group(SimpleGroupDesc), + SimpleGroup, Union(UnionAccountDesc), MinerGroup(MinerGroup), + Group(GroupDesc), } impl AccountInfo { @@ -33,8 +34,8 @@ impl AccountInfo { Self::Device(desc) => { desc.calculate_id() } - Self::Group(desc) => { - desc.calculate_id() + Self::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } Self::Union(desc) => { desc.calculate_id() @@ -42,6 +43,9 @@ impl AccountInfo { Self::MinerGroup(group) => { group.desc().calculate_id() } + Self::Group(desc) => { + desc.calculate_id() + } } } @@ -62,6 +66,9 @@ impl AccountInfo { Self::MinerGroup(_) => { Err(BuckyError::new(BuckyErrorCode::Failed, "Failed")) } + Self::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") + } } } } diff --git a/src/tools/desc-tool/src/create.rs b/src/tools/desc-tool/src/create.rs index 80e3f762f..2e9b8e842 100644 --- a/src/tools/desc-tool/src/create.rs +++ b/src/tools/desc-tool/src/create.rs @@ -128,55 +128,56 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { return; } ("sgroup", Some(matches)) => { - match matches.value_of("threshold").unwrap().parse::() { - Ok(threshold) => { - let owners = if let Some(strs) = matches.values_of_lossy("owners") { - let mut owners = vec![]; - for str in &strs { - if let Ok((obj, _)) = AnyNamedObject::decode_from_file(&Path::new(str).with_extension("desc"), &mut vec![]) { - if let Some(pk) = obj.public_key() { - match pk { - PublicKeyRef::Single(pk) => {owners.push(pk.clone())} - PublicKeyRef::MN((_, pks)) => { - owners.append(&mut pks.clone()) - } - } - } else { - warn!("desc {} not have pubkey, ignore", str); - } - } else { - error!("decode desc file {} fail", str); - } - } - owners - } else { - vec![] - }; + // TODO + // match matches.value_of("threshold").unwrap().parse::() { + // Ok(threshold) => { + // let owners = if let Some(strs) = matches.values_of_lossy("owners") { + // let mut owners = vec![]; + // for str in &strs { + // if let Ok((obj, _)) = AnyNamedObject::decode_from_file(&Path::new(str).with_extension("desc"), &mut vec![]) { + // if let Some(pk) = obj.public_key() { + // match pk { + // PublicKeyRef::Single(pk) => {owners.push(pk.clone())} + // PublicKeyRef::MN((_, pks)) => { + // owners.append(&mut pks.clone()) + // } + // } + // } else { + // warn!("desc {} not have pubkey, ignore", str); + // } + // } else { + // error!("decode desc file {} fail", str); + // } + // } + // owners + // } else { + // vec![] + // }; - if threshold as usize > owners.len() { - error!("threshold must small owners count, detail info use --help"); - return; - } + // if threshold as usize > owners.len() { + // error!("threshold must small owners count, detail info use --help"); + // return; + // } - let group_desc = desc::create_simple_group_desc(threshold - , owners - , get_objids_from_matches(matches, "members") - , get_deviceids_from_matches(matches, "ood_list")); + // let group_desc = desc::create_simple_group_desc(threshold + // , owners + // , get_objids_from_matches(matches, "members") + // , get_deviceids_from_matches(matches, "ood_list")); - let groupid = group_desc.desc().calculate_id(); - let desc_file = Path::new(matches.value_of("save_path").unwrap_or("")).join(&groupid.to_string()).with_extension("desc"); - if let Err(e) = group_desc.encode_to_file(&desc_file, true) { - error!("write imple group desc file failed, err {}", e); - } else { - info!("write simple group desc file succ to {}", desc_file.display()); - write_id_file(matches, &groupid); - }; - }, - Err(_e) => { - error!("threshold must number, detail info use --help"); - return; - } - } + // let groupid = group_desc.desc().calculate_id(); + // let desc_file = Path::new(matches.value_of("save_path").unwrap_or("")).join(&groupid.to_string()).with_extension("desc"); + // if let Err(e) = group_desc.encode_to_file(&desc_file, true) { + // error!("write imple group desc file failed, err {}", e); + // } else { + // info!("write simple group desc file succ to {}", desc_file.display()); + // write_id_file(matches, &groupid); + // }; + // }, + // Err(_e) => { + // error!("threshold must number, detail info use --help"); + // return; + // } + // } } ("people", Some(matches)) => { let owner_id = matches.value_of("owner").map(|str| { diff --git a/src/tools/desc-tool/src/desc.rs b/src/tools/desc-tool/src/desc.rs index 3b43df3ab..58b6a250e 100644 --- a/src/tools/desc-tool/src/desc.rs +++ b/src/tools/desc-tool/src/desc.rs @@ -1,16 +1,29 @@ -use std::str::FromStr; -use std::path::Path; -use log::*; use cyfs_base::*; +use log::*; +use std::path::Path; +use std::str::FromStr; +pub fn create_simple_group_desc( + founder_id: ObjectId, + admins: Vec, + conclusion_limit: Option, + area: Area, +) -> Group { + let area_info = Area::default(); + Group::new_simple_group(founder_id, admins, conclusion_limit, area).build() +} -pub fn create_simple_group_desc(threshold: u8, owners: Vec, members: Option>, ood_list: Option>) -> SimpleGroup -{ +pub fn create_org_desc(founder_id: ObjectId, area: Area) -> Group { let area_info = Area::default(); - SimpleGroup::new(threshold, owners, members.unwrap_or(vec![]), OODWorkMode::Standalone, ood_list.unwrap_or(vec![]), area_info).build() + Group::new_org(founder_id, area).build() } -pub fn create_people_desc(area: Option, key_bits: usize, owner: Option, ood_list: Vec) -> (People, PrivateKey) { +pub fn create_people_desc( + area: Option, + key_bits: usize, + owner: Option, + ood_list: Vec, +) -> (People, PrivateKey) { let area_code = match area { Some(v) => v, None => { @@ -25,10 +38,22 @@ pub fn create_people_desc(area: Option, key_bits: usize, owner: Option, category: DeviceCategory, key_bits: usize, unique_id: &str, owner_id: Option, eps: Vec, sn_list: Vec, save_path: Option)->Option<(Device, PrivateKey)> { +pub fn create_device_desc( + area: Option, + category: DeviceCategory, + key_bits: usize, + unique_id: &str, + owner_id: Option, + eps: Vec, + sn_list: Vec, + save_path: Option, +) -> Option<(Device, PrivateKey)> { let area_code = match area { Some(v) => v, None => { @@ -42,11 +67,11 @@ pub fn create_device_desc(area: Option, category: DeviceCategory, key_bits match Endpoint::from_str(s) { Ok(ep) => { ep_objs.push(ep); - }, + } Err(_e) => { error!("ep {} format error", s); return None; - }, + } } } @@ -59,38 +84,47 @@ pub fn create_device_desc(area: Option, category: DeviceCategory, key_bits secret = PrivateKey::generate_rsa(key_bits).unwrap(); } let pubkey = secret.public(); - let peer_desc = Device::new(owner_id, unique, ep_objs, sn_list, vec![], pubkey, area_code, category).build(); + let peer_desc = Device::new( + owner_id, + unique, + ep_objs, + sn_list, + vec![], + pubkey, + area_code, + category, + ) + .build(); let peer_id = peer_desc.desc().calculate_id(); if save_path.is_none() { - return Some((peer_desc, secret)); + return Some((peer_desc, secret)); } - let file_base = Path::new(save_path.unwrap_or("".to_owned()).as_str()).join(&peer_id.to_string()); + let file_base = + Path::new(save_path.unwrap_or("".to_owned()).as_str()).join(&peer_id.to_string()); let secret_file_path = file_base.with_extension("sec"); let desc_file = file_base.with_extension("desc"); match secret.encode_to_file(secret_file_path.as_ref(), true) { Ok(_) => { info!("succ encode secret to {}", secret_file_path.display()); - }, + } Err(e) => { error!("encode secret to file failed, err {}", e); return None; - }, + } } match peer_desc.encode_to_file(desc_file.as_ref(), true) { Ok(_) => { info!("success encode peerdesc to {}", desc_file.display()); Some((peer_desc, secret)) - }, + } Err(e) => { error!("encode peerdesc to file failed, err {}", e); None - }, + } } - - -} \ No newline at end of file +} diff --git a/src/tools/desc-tool/src/main.rs b/src/tools/desc-tool/src/main.rs index 0a12f0f93..901f17fe5 100644 --- a/src/tools/desc-tool/src/main.rs +++ b/src/tools/desc-tool/src/main.rs @@ -25,11 +25,11 @@ fn calc_nonce(peer_desc_file: &str, _bits: u32) { // p.const_info.calc_pow(bits, &mut nonce) Ok(()) }, - StandardObject::SimpleGroup(_p) => { - // TODO: 加calc pow - // p.const_info.calc_pow(bits, &mut nonce) - Ok(()) - }, + // StandardObject::SimpleGroup(_p) => { + // // TODO: 加calc pow + // // p.const_info.calc_pow(bits, &mut nonce) + // Ok(()) + // }, _ => { error!("not support object type"); Err(BuckyError::new(BuckyErrorCode::NotSupport, "")) diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index b3ed03b5f..8f97b3f8a 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -41,23 +41,24 @@ pub fn modify_desc(matches: &ArgMatches) { p.encode_to_file(path.as_ref(), false).expect("write desc file err"); info!("modify success"); }, - StandardObject::SimpleGroup(mut g) => { - let content = g.body_mut().as_mut().unwrap().content_mut(); - if let Some(members) = get_objids_from_matches(matches, "members") { - content.members_mut().clone_from(&members); - } + StandardObject::Group(mut g) => { + // TODO + // let content = g.body_mut().as_mut().unwrap().content_mut(); + // if let Some(members) = get_objids_from_matches(matches, "members") { + // content.members_mut().clone_from(&members); + // } - if let Some(members) = get_objids_from_matches(matches, "add_members") { - for member in members { - if !content.members_mut().contains(&member) { - content.members_mut().push(member); - } else { - info!("obj {} already in group, skip.", &member); - } - } - } + // if let Some(members) = get_objids_from_matches(matches, "add_members") { + // for member in members { + // if !content.members_mut().contains(&member) { + // content.members_mut().push(member); + // } else { + // info!("obj {} already in group, skip.", &member); + // } + // } + // } - g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + // g.encode_to_file(path.as_ref(), false).expect("write desc file err"); } StandardObject::People(mut p) => { let content = p.body_mut().as_mut().unwrap().content_mut(); diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index 85ab90ddb..6520ca2d6 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -249,12 +249,12 @@ pub fn show_desc(matches: &ArgMatches) { ua.desc().content().right() ); } - StandardObject::SimpleGroup(g) => { + StandardObject::Group(g) => { println!("desc type: Group"); if matches.is_present("all") || matches.is_present("show_members") { print!("members: ["); for owner in g.body().as_ref().unwrap().content().members() { - print!("{}, ", owner); + print!("{}, ", owner.id); } println!("]"); } diff --git a/src/tools/desc-tool/src/sign.rs b/src/tools/desc-tool/src/sign.rs index d86ea4543..d245a74a9 100644 --- a/src/tools/desc-tool/src/sign.rs +++ b/src/tools/desc-tool/src/sign.rs @@ -1,98 +1,191 @@ -use clap::{App, SubCommand, Arg, ArgMatches}; +use clap::{App, Arg, ArgMatches, SubCommand}; -use cyfs_base::{PrivateKey, FileDecoder, AnyNamedObject, RsaCPUObjectSigner, SignatureSource, ObjectId, StandardObject, FileEncoder, ObjectLink, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF}; -use cyfs_base::{sign_and_push_named_object_desc, sign_and_push_named_object_body, sign_and_set_named_object_body, sign_and_set_named_object_desc}; +use cyfs_base::{ + sign_and_push_named_object_body, sign_and_push_named_object_desc, + sign_and_set_named_object_body, sign_and_set_named_object_desc, +}; +use cyfs_base::{ + AnyNamedObject, FileDecoder, FileEncoder, ObjectId, ObjectLink, PrivateKey, RsaCPUObjectSigner, + SignatureSource, StandardObject, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, +}; use log::*; use std::str::FromStr; pub fn sign_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("sign").about("sign desc") - .arg(Arg::with_name("desc").takes_value(true).index(1).required(true) - .help("desc file to sign")) - .arg(Arg::with_name("secret").takes_value(true).short("s").long("secret").required(true) - .help("secret file for sign")) - .arg(Arg::with_name("sign_desc").short("d").long("sign_desc") - .help("add sign for desc")) - .arg(Arg::with_name("sign_body").short("b").long("sign_body") - .help("add sign for body")) - .arg(Arg::with_name("sign_source").short("t").long("sign_source").takes_value(true) - .help("sign type, default single")) - .arg(Arg::with_name("append").short("a").long("append") - .help("append sign, otherwise replace all signs")) + SubCommand::with_name("sign") + .about("sign desc") + .arg( + Arg::with_name("desc") + .takes_value(true) + .index(1) + .required(true) + .help("desc file to sign"), + ) + .arg( + Arg::with_name("secret") + .takes_value(true) + .short("s") + .long("secret") + .required(true) + .help("secret file for sign"), + ) + .arg( + Arg::with_name("sign_desc") + .short("d") + .long("sign_desc") + .help("add sign for desc"), + ) + .arg( + Arg::with_name("sign_body") + .short("b") + .long("sign_body") + .help("add sign for body"), + ) + .arg( + Arg::with_name("sign_source") + .short("t") + .long("sign_source") + .takes_value(true) + .help("sign type, default single"), + ) + .arg( + Arg::with_name("append") + .short("a") + .long("append") + .help("append sign, otherwise replace all signs"), + ) } macro_rules! match_any_obj_mut { ($on:ident, $o:ident, $body:tt, $chunk_id:ident, $chunk_body:tt) => { match &mut $on { - AnyNamedObject::Standard(o) => { - match o { - StandardObject::Device($o) => {$body}, - StandardObject::People($o) => {$body}, - StandardObject::SimpleGroup($o) => {$body}, - StandardObject::Contract($o) => {$body}, - StandardObject::UnionAccount($o) => {$body}, - StandardObject::ChunkId($chunk_id) => {$chunk_body}, - StandardObject::File($o) => {$body}, - StandardObject::Org($o) => {$body}, - StandardObject::AppGroup($o) => {$body}, - StandardObject::Dir($o) => {$body}, - StandardObject::Diff($o) => {$body}, - StandardObject::ProofOfService($o) => {$body}, - StandardObject::Tx($o) => {$body}, - StandardObject::Action($o) => {$body}, - StandardObject::ObjectMap($o) => {$body}, + AnyNamedObject::Standard(o) => match o { + StandardObject::Device($o) => $body, + StandardObject::People($o) => $body, + StandardObject::Group($o) => $body, + StandardObject::Contract($o) => $body, + StandardObject::UnionAccount($o) => $body, + StandardObject::ChunkId($chunk_id) => $chunk_body, + StandardObject::File($o) => $body, + StandardObject::AppGroup($o) => $body, + StandardObject::Dir($o) => $body, + StandardObject::Diff($o) => $body, + StandardObject::ProofOfService($o) => $body, + StandardObject::Tx($o) => $body, + StandardObject::Action($o) => $body, + StandardObject::ObjectMap($o) => $body, + StandardObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } + StandardObject::Org => panic!("Org is deprecated, you can use the Group."), }, - AnyNamedObject::Core($o) => { - $body - }, - AnyNamedObject::DECApp($o) => { - $body - }, + AnyNamedObject::Core($o) => $body, + AnyNamedObject::DECApp($o) => $body, } - } + }; } pub async fn sign_desc(matches: &ArgMatches<'_>) { - if let Ok((private, _)) = PrivateKey::decode_from_file(matches.value_of("secret").unwrap().as_ref(), &mut vec![]) { - if let Ok((mut obj, _)) = AnyNamedObject::decode_from_file(matches.value_of("desc").unwrap().as_ref(), &mut vec![]) { + if let Ok((private, _)) = + PrivateKey::decode_from_file(matches.value_of("secret").unwrap().as_ref(), &mut vec![]) + { + if let Ok((mut obj, _)) = AnyNamedObject::decode_from_file( + matches.value_of("desc").unwrap().as_ref(), + &mut vec![], + ) { let signer = RsaCPUObjectSigner::new(private.public(), private); - let sign_type = matches.value_of("sign_source").map(|str|{ - match str { + let sign_type = matches + .value_of("sign_source") + .map(|str| match str { "self" => SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), "owner" => SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), str @ _ => { if let Ok(obj) = ObjectId::from_str(str) { - SignatureSource::Object(ObjectLink { obj_id: obj, obj_owner: None }) + SignatureSource::Object(ObjectLink { + obj_id: obj, + obj_owner: None, + }) } else if let Ok(index) = str.parse::() { SignatureSource::RefIndex(index) } else { SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER) } } - } - - }).unwrap_or(SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER)); + }) + .unwrap_or(SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER)); let mut signed = false; let append = matches.is_present("append"); if matches.is_present("sign_desc") { if append { - match_any_obj_mut!(obj, o, {sign_and_push_named_object_desc(&signer, o, &sign_type).await.unwrap(); signed = true;}, _id, {error!("not support sign for chunkid");}); + match_any_obj_mut!( + obj, + o, + { + sign_and_push_named_object_desc(&signer, o, &sign_type) + .await + .unwrap(); + signed = true; + }, + _id, + { + error!("not support sign for chunkid"); + } + ); } else { - match_any_obj_mut!(obj, o, {sign_and_set_named_object_desc(&signer, o, &sign_type).await.unwrap(); signed = true;}, _id, {error!("not support sign for chunkid");}); + match_any_obj_mut!( + obj, + o, + { + sign_and_set_named_object_desc(&signer, o, &sign_type) + .await + .unwrap(); + signed = true; + }, + _id, + { + error!("not support sign for chunkid"); + } + ); } - }; if matches.is_present("sign_body") { if append { - match_any_obj_mut!(obj, o, {sign_and_push_named_object_body(&signer, o, &sign_type).await.unwrap(); signed = true;}, _id, {error!("not support sign for chunkid");}); + match_any_obj_mut!( + obj, + o, + { + sign_and_push_named_object_body(&signer, o, &sign_type) + .await + .unwrap(); + signed = true; + }, + _id, + { + error!("not support sign for chunkid"); + } + ); } else { - match_any_obj_mut!(obj, o, {sign_and_set_named_object_body(&signer, o, &sign_type).await.unwrap(); signed = true;}, _id, {error!("not support sign for chunkid");}); + match_any_obj_mut!( + obj, + o, + { + sign_and_set_named_object_body(&signer, o, &sign_type) + .await + .unwrap(); + signed = true; + }, + _id, + { + error!("not support sign for chunkid"); + } + ); } } if signed { - obj.encode_to_file(matches.value_of("desc").unwrap().as_ref(), true).unwrap(); + obj.encode_to_file(matches.value_of("desc").unwrap().as_ref(), true) + .unwrap(); } } else { error!("invalid desc file"); From e5d5e09a08e451d39fa359e73b09d3616da9a2f1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 9 Dec 2022 21:07:59 +0800 Subject: [PATCH 003/553] Proposal impl --- src/component/cyfs-base/src/objects/group.rs | 8 +- .../cyfs-base/src/objects/object_id.rs | 2 + src/component/cyfs-core/Cargo.toml | 2 + .../cyfs-core/protos/core_objects.proto | 59 ++- src/component/cyfs-core/src/coreobj.rs | 8 + .../cyfs-core/src/group/group_proposal.rs | 431 ++++++++++++++++++ .../cyfs-core/src/group/group_rpath.rs | 104 +++++ src/component/cyfs-core/src/group/mod.rs | 5 + src/component/cyfs-core/src/lib.rs | 18 +- src/component/cyfs-group/Cargo.toml | 20 + src/component/cyfs-group/build.rs | 55 +++ .../protos/group_bft_protocol.proto | 14 + 12 files changed, 693 insertions(+), 33 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_proposal.rs create mode 100644 src/component/cyfs-core/src/group/group_rpath.rs create mode 100644 src/component/cyfs-core/src/group/mod.rs create mode 100644 src/component/cyfs-group/Cargo.toml create mode 100644 src/component/cyfs-group/build.rs create mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 0577d6e82..e180f4a66 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -184,15 +184,11 @@ impl Group { unimplemented!() } - pub fn verify(&self, signature: &GroupJoinSignature) -> BuckyResult { + pub fn verify(&self, signature: &GroupJoinSignature, member_id: &ObjectId, public_key: &PublicKey) -> BuckyResult { unimplemented!() } - pub fn verify_all(&self) -> BuckyResult { - unimplemented!() - } - - pub fn verify_member(&self, member_id: &ObjectId, is_admin: bool) -> BuckyResult { + pub fn verify_member(&self, member_id: &ObjectId, is_admin: bool, publick_key: &PublicKey) -> BuckyResult { unimplemented!() } diff --git a/src/component/cyfs-base/src/objects/object_id.rs b/src/component/cyfs-base/src/objects/object_id.rs index cc48591fc..cc8fa1711 100644 --- a/src/component/cyfs-base/src/objects/object_id.rs +++ b/src/component/cyfs-base/src/objects/object_id.rs @@ -12,6 +12,8 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::str::FromStr; +pub const OBJECT_ID_LEN: usize = 32; + #[derive(Debug, Clone, Eq, PartialEq)] pub enum ObjectCategory { Standard, diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index d821558fc..2c67427f7 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -28,3 +28,5 @@ once_cell = '1.12' hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } +sha2 = { version = '0.8' } +generic-array = { version = '0.12', default-features = false, features = ['serde'] } \ No newline at end of file diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 88a459af8..d29f53f82 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -316,9 +316,15 @@ message SyncResponseObjectMetaInfo { optional uint32 access_string = 5; } +message GroupRPathDescContent { + bytes group_id = 1; + bytes dec_id = 2; + string r_path = 3; +} + message GroupProposalDescContent { // target - bytes r_path_hash = 1; + bytes r_path_id = 1; // for app string method = 2; @@ -331,9 +337,30 @@ message GroupProposalDescContent { optional uint64 effective_ending = 7; } +message GroupProposalBodyContent { + optional bytes payload = 1; + + message Signature { + bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) + bytes proponent_id = 2; + string decide = 3; + } + + repeated Signature decide_signatures = 2; +} + +message GroupUpdateGroupDescContent { + repeated bytes dec_id = 1; // the proccesor decs + optional bytes payload = 2; +} + +message GroupUpdateGroupBodyContent { + optional bytes payload = 1; +} + message GroupConsensusBlockDescContent { // target - bytes r_path_hash = 1; + bytes r_path_id = 1; // input bytes proposals_hash = 2; @@ -341,27 +368,21 @@ message GroupConsensusBlockDescContent { // result bytes result_state_id = 3; bytes proposal_result_states_hash = 4; - uint64 version = 5; + bytes proposal_receiptes_hash = 5; + uint64 version_seq = 6; // time - bytes meta_block_id = 6; - uint64 timestamp = 7; + bytes meta_block_id = 7; + uint64 timestamp = 8; // prev - optional bytes prev_block_id = 8; // the first block is none + optional bytes prev_block_id = 9; // the first block is none } -// move to dec-object -message GroupConsensusBlockAckDescContent { - bytes block_id = 1; - - enum AckStep { - Verify = 1; - Ack = 2; - AckAck = 3; - } - - AckStep step = 2; +message GroupConsensusBlockBodyContent { + repeated bytes proposals = 1; + repeated bytes proposal_result_states = 2; + repeated bytes proposal_receiptes = 3; } message GroupRPathSubStatus { @@ -381,12 +402,12 @@ message GroupRPathStatusBodyContent { message GroupActionDescContent { // target - bytes r_path_hash = 1; + bytes r_path_id = 1; // for app string method = 2; optional bytes params = 3; // blob, app define, it canbe: blob/hash/ObjectId/any other optional uint64 value = 4; - optional bytes conclusion 5; + optional bytes conclusion = 5; } \ No newline at end of file diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3e135e9a4..7f0572430 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -60,6 +60,14 @@ pub enum CoreObjectType { // Perf PerfOperation = 600, + // Group + GroupRPath = 700, + GroupProposal = 701, + GroupUpdateGroup = 702, + GroupConsensusBlock = 703, + GroupRPathStatus = 704, + GroupAction = 705, + // IM通用对象 AddFriend = 1001, Msg = 1003, diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs new file mode 100644 index 000000000..62244f0d6 --- /dev/null +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -0,0 +1,431 @@ +use std::hash::Hash; + +use crate::CoreObjectType; +use async_trait::async_trait; +use cyfs_base::*; +use serde::Serialize; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] +pub struct GroupProposalDescContent { + r_path_id: ObjectId, + method: String, + params: Option>, + + meta_block_id: Option, + timestamp: u64, + effective_begining: Option, + effective_ending: Option, +} + +impl DescContent for GroupProposalDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupProposal as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupProposalDescContent") + } + + type OwnerType = Option; + type AreaType = Option; + type AuthorType = Option; + type PublicKeyType = SubDescNone; +} + +#[derive(Clone)] +pub struct GroupProposalSignature { + signature: Signature, + proponent_id: ObjectId, + decide: String, +} + +impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> + for GroupProposalSignature +{ + fn transform( + value: &crate::codec::protos::group_proposal_body_content::Signature, + ) -> BuckyResult { + Ok(Self { + signature: Signature::raw_decode(value.signature.as_slice())?.0, + proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, + decide: value.decide.clone(), + }) + } +} + +impl ProtobufTransform<&GroupProposalSignature> + for crate::codec::protos::group_proposal_body_content::Signature +{ + fn transform(value: &GroupProposalSignature) -> BuckyResult { + Ok(Self { + signature: value.signature.to_vec()?, + proponent_id: value.proponent_id.to_vec()?, + decide: value.decide.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] +#[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] +pub struct GroupProposalBodyContent { + payload: Option>, + + decide_signatures: Vec, +} + +impl BodyContent for GroupProposalBodyContent { + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } +} + +impl ProtobufTransform + for GroupProposalBodyContent +{ + fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { + let mut decide_signatures = vec![]; + for sign in value.decide_signatures.as_slice() { + decide_signatures.push(GroupProposalSignature::transform(sign)?); + } + + Ok(Self { + payload: value.payload, + decide_signatures, + }) + } +} + +impl ProtobufTransform<&GroupProposalBodyContent> + for crate::codec::protos::GroupProposalBodyContent +{ + fn transform(value: &GroupProposalBodyContent) -> BuckyResult { + let mut decide_signatures = vec![]; + for sign in value.decide_signatures.as_slice() { + decide_signatures.push( + crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + ); + } + + Ok(Self { + payload: value.payload.clone(), + decide_signatures, + }) + } +} + +type GroupProposalType = NamedObjType; +type GroupProposalBuilder = NamedObjectBuilder; + +pub type GroupProposalId = NamedObjectId; +pub type GroupProposal = NamedObjectBase; + +impl GroupProposalDescContent { + pub fn new( + r_path_id: ObjectId, + method: String, + params: Option>, + timestamp: Option, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> GroupProposalDescContent { + Self { + r_path_id, + method, + params, + meta_block_id, + timestamp: timestamp.map_or(bucky_time_now(), |t| t), + effective_begining, + effective_ending, + } + } +} + +impl GroupProposalBodyContent { + fn hash_decide_signature( + proposal_id: &ObjectId, + proponent_id: &ObjectId, + decide: &str, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(proposal_id.as_slice()); + sha256.input(proponent_id.as_slice()); + sha256.input(decide.as_bytes()); + sha256.result().into() + } +} + +#[async_trait] +pub trait GroupProposalObject { + fn create( + r_path_id: ObjectId, + method: String, + params: Option>, + timestamp: Option, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> GroupProposalBuilder; + + fn r_path_id(&self) -> &ObjectId; + fn method(&self) -> &str; + fn params(&self) -> &Option>; + fn params_hash(&self) -> BuckyResult>; + fn params_object_id(&self) -> BuckyResult>; + fn meta_block_id(&self) -> &Option; + fn timestamp(&self) -> u64; + fn effective_begining(&self) -> Option; + fn effective_ending(&self) -> Option; + + fn payload(&self) -> &Option>; + fn set_payload(&mut self, payload: Option>); + + async fn verify_member_decide( + &self, + member_id: &ObjectId, + publick_key: &PublicKey, + ) -> BuckyResult>; + + fn decided_members_no_verify(&self) -> &Vec; + + async fn decide( + &mut self, + member_id: ObjectId, + decide: String, + private_key: &PrivateKey, + ) -> BuckyResult<()>; + + fn merge_decide(&mut self, signatures: &[GroupProposalSignature]); +} + +#[async_trait] +impl GroupProposalObject for GroupProposal { + fn create( + r_path_id: ObjectId, + method: String, + params: Option>, + timestamp: Option, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> GroupProposalBuilder { + let desc = GroupProposalDescContent { + r_path_id, + method, + params, + meta_block_id, + timestamp: timestamp.map_or(bucky_time_now(), |t| t), + effective_begining, + effective_ending, + }; + + GroupProposalBuilder::new(desc, GroupProposalBodyContent::default()) + } + + fn r_path_id(&self) -> &ObjectId { + &self.desc().content().r_path_id + } + + fn method(&self) -> &str { + self.desc().content().method.as_str() + } + + fn params(&self) -> &Option> { + &self.desc().content().params + } + + fn params_hash(&self) -> BuckyResult> { + match &self.desc().content().params { + Some(params) => { + if params.len() != HASH_VALUE_LEN { + Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!( + "try parse GroupProposal.param as hash with error length: ${}", + params.len() + ), + )) + } else { + Ok(Some(HashValue::from(params.as_slice()))) + } + } + None => Ok(None), + } + } + + fn params_object_id(&self) -> BuckyResult> { + match &self.desc().content().params { + Some(params) => { + if params.len() != OBJECT_ID_LEN { + Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!( + "try parse GroupProposal.param as ObjectId with error length: ${}", + params.len() + ), + )) + } else { + Ok(Some(ObjectId::raw_decode(params.as_slice())?.0)) + } + } + None => Ok(None), + } + } + + fn meta_block_id(&self) -> &Option { + &self.desc().content().meta_block_id + } + + fn timestamp(&self) -> u64 { + self.desc().content().timestamp + } + + fn effective_begining(&self) -> Option { + self.desc().content().effective_begining + } + + fn effective_ending(&self) -> Option { + self.desc().content().effective_ending + } + + fn payload(&self) -> &Option> { + &self.body().as_ref().unwrap().content().payload + } + + fn set_payload(&mut self, payload: Option>) { + self.body_mut().as_mut().unwrap().content_mut().payload = payload; + } + + async fn verify_member_decide( + &self, + member_id: &ObjectId, + publick_key: &PublicKey, + ) -> BuckyResult> { + let signs = self + .body() + .as_ref() + .unwrap() + .content() + .decide_signatures + .as_slice(); + for sign in signs { + if &sign.proponent_id == member_id { + let verifier = RsaCPUObjectVerifier::new(publick_key.clone()); + let hash = GroupProposalBodyContent::hash_decide_signature( + &self.desc().object_id(), + &sign.proponent_id, + sign.decide.as_str(), + ); + + if verifier.verify(hash.as_slice(), &sign.signature).await { + return Ok(Some(sign.decide.as_str())); + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid signature", + )); + } + } + } + + Ok(None) + } + + fn decided_members_no_verify(&self) -> &Vec { + &self.body().as_ref().unwrap().content().decide_signatures + } + + async fn decide( + &mut self, + member_id: ObjectId, + decide: String, + private_key: &PrivateKey, + ) -> BuckyResult<()> { + let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "duplicated decide", + )); + } + + let hash = GroupProposalBodyContent::hash_decide_signature( + &self.desc().object_id(), + &member_id, + decide.as_str(), + ); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + let sign = signer + .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + .await?; + + let signs = &mut self + .body_mut() + .as_mut() + .unwrap() + .content_mut() + .decide_signatures; + + signs.push(GroupProposalSignature { + signature: sign, + proponent_id: member_id, + decide, + }); + Ok(()) + } + + fn merge_decide(&mut self, signatures: &[GroupProposalSignature]) { + let signs = &mut self + .body_mut() + .as_mut() + .unwrap() + .content_mut() + .decide_signatures; + + signatures.iter().for_each(|add| { + if signs + .iter() + .find(|exist| exist.proponent_id == add.proponent_id) + .is_some() + { + return; + } + signs.push(add.clone()); + }); + } +} +#[cfg(test)] +mod test { + use super::{GroupProposal, GroupProposalObject}; + use cyfs_base::*; + + #[async_std::test] + async fn create_group_proposal() { + // let secret1 = PrivateKey::generate_rsa(1024).unwrap(); + // let secret2 = PrivateKey::generate_rsa(1024).unwrap(); + // let people1 = People::new(None, vec![], secret1.public(), None, None, None).build(); + // let people1_id = people1.desc().people_id(); + // let people2 = People::new(None, vec![], secret2.public(), None, None, None).build(); + // let _people2_id = people2.desc().people_id(); + + // let g1 = GroupRPath::create( + // people1_id.object_id().to_owned(), + // people1_id.object_id().to_owned(), + // people1_id.to_string(), + // ); + + // let buf = g1.to_vec().unwrap(); + // let add2 = GroupRPath::clone_from_slice(&buf).unwrap(); + // let any = AnyNamedObject::clone_from_slice(&buf).unwrap(); + // assert_eq!(g1.desc().calculate_id(), add2.desc().calculate_id()); + // assert_eq!(g1.desc().calculate_id(), any.calculate_id()); + } +} diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs new file mode 100644 index 000000000..6f7dea088 --- /dev/null +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -0,0 +1,104 @@ +use crate::CoreObjectType; +use cyfs_base::*; +use serde::Serialize; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[cyfs_protobuf_type(crate::codec::protos::GroupRPathDescContent)] +pub struct GroupRPathDescContent { + group_id: ObjectId, + dec_id: ObjectId, + r_path: String, +} + +impl DescContent for GroupRPathDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupRPath as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupRPathDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +type GroupRPathType = NamedObjType; +type GroupRPathBuilder = NamedObjectBuilder; + +pub type GroupRPathId = NamedObjectId; +pub type GroupRPath = NamedObjectBase; + +impl GroupRPathDescContent { + pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + Self { + group_id, + dec_id, + r_path, + } + } +} + +pub trait GroupRPathObject { + fn create(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self; + fn group_id(&self) -> &ObjectId; + fn dec_id(&self) -> &ObjectId; + fn r_path(&self) -> &str; +} + +impl GroupRPathObject for GroupRPath { + fn create(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + let desc = GroupRPathDescContent { + group_id, + dec_id, + r_path, + }; + + GroupRPathBuilder::new(desc, EmptyProtobufBodyContent::default()).build() + } + + fn group_id(&self) -> &ObjectId { + &self.desc().content().group_id + } + + fn dec_id(&self) -> &ObjectId { + &self.desc().content().dec_id + } + + fn r_path(&self) -> &str { + self.desc().content().r_path.as_str() + } +} +#[cfg(test)] +mod test { + use super::{GroupRPath, GroupRPathObject}; + use cyfs_base::*; + + #[async_std::test] + async fn create_group_rpath() { + let secret1 = PrivateKey::generate_rsa(1024).unwrap(); + let secret2 = PrivateKey::generate_rsa(1024).unwrap(); + let people1 = People::new(None, vec![], secret1.public(), None, None, None).build(); + let people1_id = people1.desc().people_id(); + let people2 = People::new(None, vec![], secret2.public(), None, None, None).build(); + let _people2_id = people2.desc().people_id(); + + let g1 = GroupRPath::create( + people1_id.object_id().to_owned(), + people1_id.object_id().to_owned(), + people1_id.to_string(), + ); + + let buf = g1.to_vec().unwrap(); + let add2 = GroupRPath::clone_from_slice(&buf).unwrap(); + let any = AnyNamedObject::clone_from_slice(&buf).unwrap(); + assert_eq!(g1.desc().calculate_id(), add2.desc().calculate_id()); + assert_eq!(g1.desc().calculate_id(), any.calculate_id()); + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs new file mode 100644 index 000000000..b9a68eefe --- /dev/null +++ b/src/component/cyfs-core/src/group/mod.rs @@ -0,0 +1,5 @@ +mod group_rpath; +mod group_proposal; + +pub use group_rpath::*; +pub use group_proposal::*; \ No newline at end of file diff --git a/src/component/cyfs-core/src/lib.rs b/src/component/cyfs-core/src/lib.rs index e77fa3731..fa0143477 100644 --- a/src/component/cyfs-core/src/lib.rs +++ b/src/component/cyfs-core/src/lib.rs @@ -2,20 +2,22 @@ extern crate log; pub use app::*; +pub use codec::*; pub use common::*; pub use coreobj::*; +pub use group::*; +pub use nft::*; pub use storage::*; -pub use zone::*; pub use trans::*; -pub use nft::*; -pub use codec::*; +pub use zone::*; +mod app; pub mod codec; +mod common; mod coreobj; -mod zone; +mod group; +pub mod im; +mod nft; mod storage; -mod app; -mod common; mod trans; -mod nft; -pub mod im; \ No newline at end of file +mod zone; diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml new file mode 100644 index 000000000..43794e6f1 --- /dev/null +++ b/src/component/cyfs-group/Cargo.toml @@ -0,0 +1,20 @@ + +[package] +name = 'cyfs-group' +version = '0.0.1' +authors = ['zhangzhen '] +edition = '2022' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group/build.rs new file mode 100644 index 000000000..9d3a5a616 --- /dev/null +++ b/src/component/cyfs-group/build.rs @@ -0,0 +1,55 @@ +extern crate protoc_rust; +extern crate chrono; + +use std::io::Write; + +static MOD_PROTOS_RS:&str = r#" +pub(crate) mod group_bft_protocol; + +pub(crate) use group_bft_protocol::*; +"#; + +#[allow(dead_code)] +fn gen_protos() { + let out_dir = std::env::var("OUT_DIR").unwrap(); + let mut gen = protoc_rust::Codegen::new(); + gen.input("protos/group_bft_protocol.proto") + .protoc_path(protoc_bin_vendored::protoc_bin_path().unwrap()) + .out_dir(&out_dir) + .customize(protoc_rust::Customize { + expose_fields: Some(true), + ..Default::default() + }); + + gen.run().expect("protoc error!"); + + std::fs::File::create(out_dir + "/mod.rs").expect("write protos mod error") + .write_all(MOD_PROTOS_RS.as_ref()).expect("write protos mod error"); +} + +fn main() { + println!("cargo:rerun-if-env-changed=VERSION"); + println!("cargo:rerun-if-env-changed=CHANNEL"); + println!("cargo:rerun-if-env-changed=TARGET"); + println!( + "cargo:rustc-env=VERSION={}", + std::env::var("VERSION").unwrap_or("0".to_owned()) + ); + println!( + "cargo:rustc-env=CHANNEL={}", + std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) + ); + println!( + "cargo:rustc-env=TARGET={}", + std::env::var("TARGET").unwrap() + ); + + println!( + "cargo:rustc-env=BUILDDATE={}", + chrono::Local::today().format("%y-%m-%d") + ); + + println!("cargo:rerun-if-changed=protos"); + + gen_protos(); +} diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto new file mode 100644 index 000000000..df26a09af --- /dev/null +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -0,0 +1,14 @@ + +syntax = "proto3"; + +message GroupConsensusBlockAckDescContent { + bytes block_id = 1; + + enum AckStep { + Verify = 0; + Ack = 1; + AckAck = 2; + } + + AckStep step = 2; +} From b52f49336588179e4b0fb29a5e2f54c93db98849 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 9 Dec 2022 21:55:38 +0800 Subject: [PATCH 004/553] GroupConsensusBlock impl --- .../src/group/group_consensus_block.rs | 245 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 6 +- 2 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_consensus_block.rs diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs new file mode 100644 index 000000000..55915f963 --- /dev/null +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -0,0 +1,245 @@ +use std::sync::atomic::{AtomicU8, Ordering}; + +use crate::CoreObjectType; +use cyfs_base::*; +use serde::Serialize; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] +pub struct GroupConsensusBlockDescContent { + r_path_id: ObjectId, + proposals_hash: HashValue, + result_state_id: ObjectId, + proposal_result_states_hash: HashValue, + proposal_receiptes_hash: HashValue, + version_seq: u64, + meta_block_id: ObjectId, + timestamp: u64, + prev_block_id: Option, +} + +impl DescContent for GroupConsensusBlockDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupConsensusBlock as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupConsensusBlockDescContent") + } + + type OwnerType = Option; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockBodyContent)] +pub struct GroupConsensusBlockBodyContent { + proposals: Vec, + proposal_result_states: Vec, + proposal_receiptes: Vec, +} + +impl BodyContent for GroupConsensusBlockBodyContent { + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } +} + +type GroupConsensusBlockType = + NamedObjType; +type GroupConsensusBlockBuilder = + NamedObjectBuilder; + +pub type GroupConsensusBlockId = NamedObjectId; +pub struct GroupConsensusBlock(NamedObjectBase, AtomicU8); + +const BLOCK_CHECK_STATE_NONE: u8 = 0; +const BLOCK_CHECK_STATE_SUCC: u8 = 1; +const BLOCK_CHECK_STATE_FAIL: u8 = 2; + +impl GroupConsensusBlockDescContent { + fn hash_object_vec(object_ids: &[ObjectId]) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + for id in object_ids { + sha256.input(id.as_slice()); + } + + sha256.result().into() + } +} + +pub trait GroupConsensusBlockObject { + fn create( + r_path_id: ObjectId, + proposals: Vec, + result_state_id: ObjectId, + proposal_result_states: Vec, + proposal_receiptes: Vec, + version_seq: u64, + meta_block_id: ObjectId, + prev_block_id: Option, + owner: ObjectId, + ) -> Self; + fn check(&self) -> bool; + fn r_path_id(&self) -> &ObjectId; + fn proposals(&self) -> &Vec; + fn result_state_id(&self) -> &ObjectId; + fn proposal_result_states(&self) -> &Vec; + fn proposal_receiptes(&self) -> &Vec; + fn version_seq(&self) -> u64; + fn meta_block_id(&self) -> &ObjectId; + fn prev_block_id(&self) -> &Option; + fn owner(&self) -> &ObjectId; + fn named_object(&self) -> &NamedObjectBase; +} + +impl GroupConsensusBlockObject for GroupConsensusBlock { + fn create( + r_path_id: ObjectId, + proposals: Vec, + result_state_id: ObjectId, + proposal_result_states: Vec, + proposal_receiptes: Vec, + version_seq: u64, + meta_block_id: ObjectId, + prev_block_id: Option, + owner: ObjectId, + ) -> Self { + let desc = GroupConsensusBlockDescContent { + r_path_id, + proposals_hash: GroupConsensusBlockDescContent::hash_object_vec(proposals.as_slice()), + result_state_id, + proposal_result_states_hash: GroupConsensusBlockDescContent::hash_object_vec( + proposal_result_states.as_slice(), + ), + proposal_receiptes_hash: GroupConsensusBlockDescContent::hash_object_vec( + proposal_receiptes.as_slice(), + ), + version_seq, + meta_block_id, + timestamp: bucky_time_now(), + prev_block_id, + }; + + let body = GroupConsensusBlockBodyContent { + proposals, + proposal_result_states, + proposal_receiptes, + }; + + let block = GroupConsensusBlockBuilder::new(desc, body) + .owner(owner) + .build(); + + Self(block, AtomicU8::new(BLOCK_CHECK_STATE_SUCC)) + } + + fn check(&self) -> bool { + let state = self.1.load(Ordering::SeqCst); + if state == BLOCK_CHECK_STATE_NONE { + let desc = self.0.desc().content(); + let body = self.0.body().as_ref().unwrap().content(); + if GroupConsensusBlockDescContent::hash_object_vec(body.proposals.as_slice()) + != desc.proposals_hash + || GroupConsensusBlockDescContent::hash_object_vec( + body.proposal_result_states.as_slice(), + ) != desc.proposal_result_states_hash + || GroupConsensusBlockDescContent::hash_object_vec( + body.proposal_receiptes.as_slice(), + ) != desc.proposal_receiptes_hash + { + self.1.store(BLOCK_CHECK_STATE_FAIL, Ordering::SeqCst); + false + } else { + self.1.store(BLOCK_CHECK_STATE_SUCC, Ordering::SeqCst); + true + } + } else { + state == BLOCK_CHECK_STATE_SUCC + } + } + + fn r_path_id(&self) -> &ObjectId { + let desc = self.0.desc().content(); + &desc.r_path_id + } + + fn proposals(&self) -> &Vec { + let body = self.0.body().as_ref().unwrap().content(); + &body.proposals + } + + fn result_state_id(&self) -> &ObjectId { + let desc = self.0.desc().content(); + &desc.result_state_id + } + + fn proposal_result_states(&self) -> &Vec { + let body = self.0.body().as_ref().unwrap().content(); + &body.proposal_result_states + } + + fn proposal_receiptes(&self) -> &Vec { + let body = self.0.body().as_ref().unwrap().content(); + &body.proposal_receiptes + } + + fn version_seq(&self) -> u64 { + let desc = self.0.desc().content(); + desc.version_seq + } + + fn meta_block_id(&self) -> &ObjectId { + let desc = self.0.desc().content(); + &desc.meta_block_id + } + + fn prev_block_id(&self) -> &Option { + let desc = self.0.desc().content(); + &desc.prev_block_id + } + + fn owner(&self) -> &ObjectId { + let desc = self.0.desc(); + desc.owner().as_ref().unwrap() + } + + fn named_object(&self) -> &NamedObjectBase { + &self.0 + } +} + +#[cfg(test)] +mod test { + use super::{GroupConsensusBlock, GroupConsensusBlockObject}; + use cyfs_base::*; + + #[async_std::test] + async fn create_group_rpath() { + let secret1 = PrivateKey::generate_rsa(1024).unwrap(); + let secret2 = PrivateKey::generate_rsa(1024).unwrap(); + let people1 = People::new(None, vec![], secret1.public(), None, None, None).build(); + let people1_id = people1.desc().people_id(); + let people2 = People::new(None, vec![], secret2.public(), None, None, None).build(); + let _people2_id = people2.desc().people_id(); + + let g1 = GroupConsensusBlock::create( + people1_id.object_id().to_owned(), + people1_id.object_id().to_owned(), + people1_id.to_string(), + ); + + let buf = g1.to_vec().unwrap(); + let add2 = GroupConsensusBlock::clone_from_slice(&buf).unwrap(); + let any = AnyNamedObject::clone_from_slice(&buf).unwrap(); + assert_eq!(g1.desc().calculate_id(), add2.desc().calculate_id()); + assert_eq!(g1.desc().calculate_id(), any.calculate_id()); + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b9a68eefe..0712ad5da 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,5 +1,7 @@ -mod group_rpath; +mod group_consensus_block; mod group_proposal; +mod group_rpath; +pub use group_consensus_block::*; +pub use group_proposal::*; pub use group_rpath::*; -pub use group_proposal::*; \ No newline at end of file From db86d6dd5026269a84ec71ad24069fa955c9ebcb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 28 Dec 2022 21:21:47 +0800 Subject: [PATCH 005/553] interface define, and handle_block --- src/Cargo.lock | 568 +++++++++--------- src/Cargo.toml | 1 + .../cyfs-base/protos/standard_objects.proto | 8 +- src/component/cyfs-base/src/base/error.rs | 2 +- src/component/cyfs-base/src/objects/group.rs | 60 +- src/component/cyfs-base/src/objects/mock.rs | 19 + src/component/cyfs-base/src/objects/mod.rs | 6 +- src/component/cyfs-chunk-lib/src/chunk.rs | 36 +- .../cyfs-core/protos/core_objects.proto | 79 ++- src/component/cyfs-core/src/coreobj.rs | 11 +- .../src/group/group_consensus_block.rs | 338 ++++++++--- .../cyfs-core/src/group/group_proposal.rs | 173 ++++-- .../src/group/group_proposal_decide_param.rs | 51 ++ .../cyfs-core/src/group/group_rpath.rs | 90 +-- .../cyfs-core/src/group/group_rpath_status.rs | 12 + .../group_update_group_proposal_param.rs | 36 ++ src/component/cyfs-core/src/group/mod.rs | 6 + src/component/cyfs-group/Cargo.toml | 13 +- src/component/cyfs-group/build.rs | 19 +- .../cyfs-group/examples/app_example.rs | 162 +++++ .../protos/group_bft_protocol.proto | 19 +- src/component/cyfs-group/readme.md | 14 + .../cyfs-group/src/consensus/block.rs | 19 + .../cyfs-group/src/consensus/consensus.rs | 25 + .../src/consensus/hotstuff/hotstuff.rs | 283 +++++++++ .../cyfs-group/src/consensus/hotstuff/mod.rs | 3 + src/component/cyfs-group/src/consensus/mod.rs | 13 + .../src/consensus/order_block/mod.rs | 3 + .../consensus/order_block/order_block_mgr.rs | 18 + .../cyfs-group/src/consensus/proposal/mod.rs | 5 + .../proposal/pending_proposal_mgr.rs | 110 ++++ .../src/consensus/proposal/proposal.rs | 19 + .../cyfs-group/src/consensus/timer.rs | 39 ++ .../src/consensus/vote/committee.rs | 39 ++ .../cyfs-group/src/consensus/vote/mod.rs | 7 + .../cyfs-group/src/consensus/vote/vote.rs | 17 + .../cyfs-group/src/consensus/vote/vote_mgr.rs | 147 +++++ src/component/cyfs-group/src/constant.rs | 15 + src/component/cyfs-group/src/crypto/crypto.rs | 14 + src/component/cyfs-group/src/crypto/mod.rs | 3 + src/component/cyfs-group/src/dataflow.vsdx | Bin 0 -> 26647 bytes .../cyfs-group/src/dec/delegate_factory.rs | 45 ++ src/component/cyfs-group/src/dec/mod.rs | 11 + .../cyfs-group/src/dec/rpath_client.rs | 32 + .../cyfs-group/src/dec/rpath_control.rs | 33 + src/component/cyfs-group/src/dec/rpath_mgr.rs | 62 ++ src/component/cyfs-group/src/lib.rs | 21 + .../cyfs-group/src/manager/group_manager.rs | 52 ++ src/component/cyfs-group/src/manager/mod.rs | 5 + .../cyfs-group/src/network/listener.rs | 9 + src/component/cyfs-group/src/network/mod.rs | 7 + .../cyfs-group/src/network/non_driver.rs | 22 + .../cyfs-group/src/network/sender.rs | 15 + .../src/objects/group_decide_proposal.rs | 104 ++++ .../src/objects/group_update_proposal.rs | 244 ++++++++ src/component/cyfs-group/src/objects/mod.rs | 7 + .../cyfs-group/src/objects/protocol.rs | 101 ++++ .../cyfs-group/src/statepath/design.md | 63 ++ src/component/cyfs-group/src/statepath/mod.rs | 3 + .../cyfs-group/src/statepath/statepath.rs | 202 +++++++ src/component/cyfs-group/src/storage/mod.rs | 3 + .../cyfs-group/src/storage/storage.rs | 142 +++++ src/component/cyfs-group/src/utils.rs | 8 + 63 files changed, 3123 insertions(+), 570 deletions(-) create mode 100644 src/component/cyfs-base/src/objects/mock.rs create mode 100644 src/component/cyfs-core/src/group/group_proposal_decide_param.rs create mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs create mode 100644 src/component/cyfs-core/src/group/group_update_group_proposal_param.rs create mode 100644 src/component/cyfs-group/examples/app_example.rs create mode 100644 src/component/cyfs-group/readme.md create mode 100644 src/component/cyfs-group/src/consensus/block.rs create mode 100644 src/component/cyfs-group/src/consensus/consensus.rs create mode 100644 src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs create mode 100644 src/component/cyfs-group/src/consensus/hotstuff/mod.rs create mode 100644 src/component/cyfs-group/src/consensus/mod.rs create mode 100644 src/component/cyfs-group/src/consensus/order_block/mod.rs create mode 100644 src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs create mode 100644 src/component/cyfs-group/src/consensus/proposal/mod.rs create mode 100644 src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs create mode 100644 src/component/cyfs-group/src/consensus/proposal/proposal.rs create mode 100644 src/component/cyfs-group/src/consensus/timer.rs create mode 100644 src/component/cyfs-group/src/consensus/vote/committee.rs create mode 100644 src/component/cyfs-group/src/consensus/vote/mod.rs create mode 100644 src/component/cyfs-group/src/consensus/vote/vote.rs create mode 100644 src/component/cyfs-group/src/consensus/vote/vote_mgr.rs create mode 100644 src/component/cyfs-group/src/constant.rs create mode 100644 src/component/cyfs-group/src/crypto/crypto.rs create mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/dataflow.vsdx create mode 100644 src/component/cyfs-group/src/dec/delegate_factory.rs create mode 100644 src/component/cyfs-group/src/dec/mod.rs create mode 100644 src/component/cyfs-group/src/dec/rpath_client.rs create mode 100644 src/component/cyfs-group/src/dec/rpath_control.rs create mode 100644 src/component/cyfs-group/src/dec/rpath_mgr.rs create mode 100644 src/component/cyfs-group/src/lib.rs create mode 100644 src/component/cyfs-group/src/manager/group_manager.rs create mode 100644 src/component/cyfs-group/src/manager/mod.rs create mode 100644 src/component/cyfs-group/src/network/listener.rs create mode 100644 src/component/cyfs-group/src/network/mod.rs create mode 100644 src/component/cyfs-group/src/network/non_driver.rs create mode 100644 src/component/cyfs-group/src/network/sender.rs create mode 100644 src/component/cyfs-group/src/objects/group_decide_proposal.rs create mode 100644 src/component/cyfs-group/src/objects/group_update_proposal.rs create mode 100644 src/component/cyfs-group/src/objects/mod.rs create mode 100644 src/component/cyfs-group/src/objects/protocol.rs create mode 100644 src/component/cyfs-group/src/statepath/design.md create mode 100644 src/component/cyfs-group/src/statepath/mod.rs create mode 100644 src/component/cyfs-group/src/statepath/statepath.rs create mode 100644 src/component/cyfs-group/src/storage/mod.rs create mode 100644 src/component/cyfs-group/src/storage/storage.rs create mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 9f9d31104..df9c3b37c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -111,9 +111,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" [[package]] name = "android_logger" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" +checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" dependencies = [ "android_log-sys", "env_logger", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" [[package]] name = "app-manager" @@ -266,11 +266,11 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ - "concurrent-queue 1.2.4", + "concurrent-queue", "event-listener", "futures-core", ] @@ -293,7 +293,7 @@ checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ "async-lock", "async-task", - "concurrent-queue 2.0.0", + "concurrent-queue", "fastrand", "futures-lite", "slab", @@ -333,13 +333,13 @@ dependencies = [ [[package]] name = "async-io" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ "async-lock", "autocfg 1.1.0", - "concurrent-queue 1.2.4", + "concurrent-queue", "futures-lite", "libc", "log 0.4.17", @@ -348,7 +348,7 @@ dependencies = [ "slab", "socket2", "waker-fn", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -375,20 +375,20 @@ dependencies = [ [[package]] name = "async-process" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" +checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" dependencies = [ "async-io", + "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", - "once_cell", "signal-hook", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -497,9 +497,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" dependencies = [ "proc-macro2", "quote", @@ -549,7 +549,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -571,15 +571,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.5.4", + "miniz_oxide", "object", "rustc-demangle", ] @@ -806,16 +806,16 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", + "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", - "once_cell", ] [[package]] @@ -826,7 +826,7 @@ checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" dependencies = [ "base64 0.13.1", "bollard-stubs", - "bytes 1.2.1", + "bytes 1.3.0", "chrono", "dirs-next", "futures-core", @@ -945,9 +945,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "bzip2" @@ -990,9 +990,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" dependencies = [ "jobserver", ] @@ -1023,16 +1023,16 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.44", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -1156,15 +1156,15 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "memchr", ] [[package]] name = "comfy-table" -version = "6.1.2" +version = "6.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1090f39f45786ec6dc6286f8ea9c75d0a7ef0a0d3cda674cef0c3af7b307fbc2" +checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" dependencies = [ "crossterm", "strum", @@ -1178,15 +1178,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" -[[package]] -name = "concurrent-queue" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" -dependencies = [ - "cache-padded", -] - [[package]] name = "concurrent-queue" version = "2.0.0" @@ -1428,22 +1419,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1451,9 +1442,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -1582,9 +1573,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888" +checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" dependencies = [ "cc", "cxxbridge-flags", @@ -1594,9 +1585,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3" +checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" dependencies = [ "cc", "codespan-reporting", @@ -1609,15 +1600,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f" +checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" [[package]] name = "cxxbridge-macro" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" +checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" dependencies = [ "proc-macro2", "quote", @@ -1714,7 +1705,7 @@ dependencies = [ "log 0.4.17", "lru_time_cache", "md5", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.7.3", "ringbuf", @@ -1762,7 +1753,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1802,7 +1793,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1826,7 +1817,7 @@ version = "0.6.3" dependencies = [ "bip39", "cyfs-base", - "digest 0.10.5", + "digest 0.10.6", "hex", "hmac 0.12.1", "log 0.4.17", @@ -1890,6 +1881,7 @@ dependencies = [ "chrono", "cyfs-base", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1902,6 +1894,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1951,6 +1944,31 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.0.1" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.5", + "prost-build 0.11.5", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "serde", + "serde_json", +] + [[package]] name = "cyfs-lib" version = "0.7.0" @@ -1959,7 +1977,7 @@ dependencies = [ "async-std", "async-trait", "async-tungstenite", - "bytes 1.2.1", + "bytes 1.3.0", "chrono", "cyfs-base", "cyfs-bdt", @@ -2248,7 +2266,7 @@ dependencies = [ "async-std", "async-trait", "base", - "bytes 1.2.1", + "bytes 1.3.0", "clap", "cyfs-base", "cyfs-bdt", @@ -2319,11 +2337,11 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.2", - "prost-build 0.11.2", + "prost 0.11.5", + "prost-build 0.11.5", "protoc-bin-vendored", "rand 0.8.5", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", "sha2 0.8.2", @@ -2459,7 +2477,7 @@ dependencies = [ "log 0.4.17", "log-panics", "named-lock", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.8.5", "rusqlite", @@ -2519,7 +2537,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.5", ] [[package]] @@ -2595,9 +2613,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -2712,7 +2730,7 @@ dependencies = [ "encoding", "lazy_static", "rand 0.4.6", - "time 0.1.44", + "time 0.1.45", "version_check 0.1.5", ] @@ -2782,9 +2800,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "env_logger" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "log 0.4.17", "regex", @@ -2792,9 +2810,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" +checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" dependencies = [ "serde", ] @@ -2810,7 +2828,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itertools", - "paste 1.0.9", + "paste 1.0.11", "rustc-hex", "serde", "serde_json", @@ -2994,9 +3012,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" dependencies = [ "cfg-if 1.0.0", "libc", @@ -3024,12 +3042,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide 0.5.4", + "miniz_oxide", ] [[package]] @@ -3321,7 +3339,7 @@ dependencies = [ "async-std", "async-trait", "base", - "bytes 1.2.1", + "bytes 1.3.0", "clap", "cyfs-base", "cyfs-bdt", @@ -3400,9 +3418,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" +checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" dependencies = [ "proc-macro2", "quote", @@ -3421,9 +3439,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" [[package]] name = "glob" @@ -3446,9 +3464,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +checksum = "98c4a8d6391675c6b2ee1a6c8d06e8e2d03605c44cec1270675985a4c2a5500b" dependencies = [ "futures-channel", "futures-core", @@ -3462,7 +3480,7 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "fnv", "futures-core", "futures-sink", @@ -3565,6 +3583,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -3652,7 +3679,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -3682,9 +3709,9 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "fnv", - "itoa 1.0.4", + "itoa 1.0.5", ] [[package]] @@ -3693,7 +3720,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "http", "pin-project-lite 0.2.9", ] @@ -3769,7 +3796,7 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time 0.1.44", + "time 0.1.45", "traitobject", "typeable", "unicase 1.4.2", @@ -3782,7 +3809,7 @@ version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "futures-channel", "futures-core", "futures-util", @@ -3791,7 +3818,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.4", + "itoa 1.0.5", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -3881,9 +3908,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.4" +version = "0.24.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8e4fb07cf672b1642304e731ef8a6a4c7891d67bb4fd4f5ce58cd6ed86803c" +checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" dependencies = [ "bytemuck", "byteorder", @@ -3934,9 +3961,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -3949,7 +3976,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" dependencies = [ "indoc-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -3958,7 +3985,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "syn", @@ -4057,9 +4084,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jni" @@ -4092,9 +4119,9 @@ dependencies = [ [[package]] name = "jpeg-decoder" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" [[package]] name = "js-sys" @@ -4107,9 +4134,12 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] [[package]] name = "kv-log-macro" @@ -4163,7 +4193,7 @@ dependencies = [ "email", "lettre", "mime 0.3.16", - "time 0.1.44", + "time 0.1.45", "uuid", ] @@ -4182,9 +4212,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" @@ -4231,9 +4261,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -4290,7 +4320,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" dependencies = [ - "nix 0.23.1", + "nix 0.23.2", "winapi", ] @@ -4336,6 +4366,15 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "memzero" version = "0.1.0" @@ -4424,15 +4463,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -4494,27 +4524,27 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -4600,9 +4630,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" dependencies = [ "byteorder", "lazy_static", @@ -4670,11 +4700,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -4689,9 +4719,9 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" dependencies = [ "memchr", ] @@ -4805,9 +4835,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.42" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -4837,9 +4867,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.77" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg 1.1.0", "cc", @@ -4910,7 +4940,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -4920,14 +4950,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.5", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -4939,9 +4969,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if 1.0.0", "libc", @@ -4968,14 +4998,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "paste-impl" @@ -4983,7 +5013,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -5011,7 +5041,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -5051,9 +5081,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8" +checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" dependencies = [ "thiserror", "ucd-trie", @@ -5143,7 +5173,7 @@ checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "chrono", "font-kit", - "image 0.24.4", + "image 0.24.5", "lazy_static", "num-traits", "pathfinder_geometry", @@ -5168,7 +5198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4a1f21490a6cf4a84c272ad20bd7844ed99a3178187a4c5ab7f2051295beef" dependencies = [ "gif", - "image 0.24.4", + "image 0.24.5", "plotters-backend", ] @@ -5209,21 +5239,21 @@ dependencies = [ "bitflags", "crc32fast", "flate2", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] name = "polling" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -5245,9 +5275,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" +checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773" dependencies = [ "proc-macro2", "syn", @@ -5343,9 +5373,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-hack-impl" @@ -5355,9 +5385,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] @@ -5368,18 +5398,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a" +checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592" dependencies = [ - "bytes 1.2.1", - "prost-derive 0.11.2", + "bytes 1.3.0", + "prost-derive 0.11.5", ] [[package]] @@ -5388,7 +5418,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "heck 0.3.3", "itertools", "lazy_static", @@ -5404,11 +5434,11 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d8b442418ea0822409d9e7d047cbf1e7e9e1760b172bf9982cf29d517c93511" +checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "heck 0.4.0", "itertools", "lazy_static", @@ -5416,8 +5446,8 @@ dependencies = [ "multimap", "petgraph", "prettyplease", - "prost 0.11.2", - "prost-types 0.11.2", + "prost 0.11.5", + "prost-types 0.11.5", "regex", "syn", "tempfile", @@ -5439,9 +5469,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" +checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720" dependencies = [ "anyhow", "itertools", @@ -5456,18 +5486,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" +checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091" dependencies = [ - "bytes 1.2.1", - "prost 0.11.2", + "bytes 1.3.0", + "prost 0.11.5", ] [[package]] @@ -5476,7 +5506,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", ] [[package]] @@ -5616,9 +5646,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -5821,21 +5851,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg 1.1.0", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -5951,7 +5979,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "rustc-hex", ] @@ -6001,8 +6029,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", - "digest 0.10.5", - "num-bigint-dig 0.8.1", + "digest 0.10.6", + "num-bigint-dig 0.8.2", "num-integer", "num-iter", "num-traits", @@ -6168,15 +6196,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "safemem" @@ -6244,9 +6272,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "sct" @@ -6311,9 +6339,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -6332,9 +6360,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -6351,9 +6379,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -6371,11 +6399,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ - "itoa 1.0.4", + "itoa 1.0.5", "ryu", "serde", ] @@ -6398,7 +6426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa 1.0.5", "ryu", "serde", ] @@ -6427,13 +6455,13 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6453,7 +6481,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6495,7 +6523,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6541,7 +6569,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.17", - "nix 0.23.1", + "nix 0.23.2", "rand 0.8.5", "win-sys", ] @@ -6776,10 +6804,10 @@ dependencies = [ "atoi 0.4.0", "bitflags", "byteorder", - "bytes 1.2.1", + "bytes 1.3.0", "crc 2.1.0", "crossbeam-queue", - "digest 0.10.5", + "digest 0.10.6", "either", "event-listener", "flume", @@ -6792,14 +6820,14 @@ dependencies = [ "hashlink 0.7.0", "hex", "indexmap", - "itoa 1.0.4", + "itoa 1.0.5", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "num-bigint 0.3.3", "once_cell", - "paste 1.0.9", + "paste 1.0.11", "percent-encoding 2.2.0", "rand 0.8.5", "rsa 0.6.1", @@ -6826,7 +6854,7 @@ dependencies = [ "atoi 1.0.0", "bitflags", "byteorder", - "bytes 1.2.1", + "bytes 1.3.0", "crc 3.0.0", "crossbeam-queue", "dotenvy", @@ -6841,13 +6869,13 @@ dependencies = [ "hashlink 0.8.1", "hex", "indexmap", - "itoa 1.0.4", + "itoa 1.0.5", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "once_cell", - "paste 1.0.9", + "paste 1.0.11", "percent-encoding 2.2.0", "rustls 0.20.7", "rustls-pemfile", @@ -6858,7 +6886,7 @@ dependencies = [ "stringprep", "thiserror", "url 2.3.0", - "webpki-roots 0.22.5", + "webpki-roots 0.22.6", ] [[package]] @@ -7071,9 +7099,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -7094,9 +7122,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.7" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c375d5fd899e32847b8566e10598d6e9f1d9b55ec6de3cdf9e7da4bdc51371bc" +checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -7189,18 +7217,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -7250,9 +7278,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -7280,7 +7308,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.4", + "itoa 1.0.5", "libc", "num_threads", "serde", @@ -7300,7 +7328,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "time-macros-impl", ] @@ -7319,7 +7347,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "standback", @@ -7356,19 +7384,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.21.2" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" dependencies = [ "autocfg 1.1.0", - "bytes 1.2.1", + "bytes 1.3.0", "libc", "memchr", "mio", "num_cpus", "pin-project-lite 0.2.9", "socket2", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -7377,7 +7405,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "futures-core", "futures-sink", "log 0.4.17", @@ -7391,7 +7419,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ - "bytes 1.2.1", + "bytes 1.3.0", "futures-core", "futures-sink", "pin-project-lite 0.2.9", @@ -7401,9 +7429,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "indexmap", "serde", @@ -7471,7 +7499,7 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.2.1", + "bytes 1.3.0", "http", "httparse", "log 0.4.17", @@ -7490,9 +7518,9 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" @@ -7502,9 +7530,9 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "uint" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", @@ -7538,9 +7566,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -7577,9 +7605,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unindent" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "universal-hash" @@ -7663,9 +7691,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version-compare" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" @@ -7851,9 +7879,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.5" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" dependencies = [ "webpki 0.22.0", ] @@ -8135,9 +8163,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", @@ -8236,9 +8264,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.4+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" dependencies = [ "cc", "libc", diff --git a/src/Cargo.toml b/src/Cargo.toml index e262e2bb0..c77bfc6e3 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -25,6 +25,7 @@ members = [ "./component/cyfs-chunk-cache", "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", + "./component/cyfs-group", "./service/base", "./service/ood-control", diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index 0098c88fc..cfb722c62 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -92,9 +92,8 @@ message GroupRoleACL { } message GroupJoinSignature { - bytes signature = 1; // Sign(member_id, group_id, timestamp, hash, is_admin) + bytes signature = 1; // Sign(member_id, group_id, hash, is_admin) bytes member_id = 2; - uint64 timestamp = 3; bool is_admin = 4; bytes hash = 5; // Hash(Encode(Group)) } @@ -122,6 +121,7 @@ message CommonGroupBodyContent { uint64 version = 13; + // TODO: 这个Group的签名准备放到Group信息变更的提案里 repeated GroupJoinSignature join_signatures = 14; // signature for every member/admin } @@ -149,10 +149,6 @@ message OrgBodyContent { CommonGroupBodyContent common = 3; } -message GroupPackedBodyContent { - bytes packed_body_id = 1; -} - // tx message TxBodyContent { bytes data = 1; diff --git a/src/component/cyfs-base/src/base/error.rs b/src/component/cyfs-base/src/base/error.rs index 5deddc3ee..bfa27d314 100644 --- a/src/component/cyfs-base/src/base/error.rs +++ b/src/component/cyfs-base/src/base/error.rs @@ -385,7 +385,7 @@ impl Into for BuckySystemErrorCode { Self::OutofSessionLimit => BuckyErrorCode::OutofSessionLimit, Self::Redirect => BuckyErrorCode::Redirect, - + Self::MongoDBError => BuckyErrorCode::MongoDBError, Self::SqliteError => BuckyErrorCode::SqliteError, Self::UrlError => BuckyErrorCode::UrlError, diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index e180f4a66..59ad2a685 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -29,7 +29,7 @@ impl DescContent for GroupDescContent { impl BodyContent for GroupBodyContent { fn format(&self) -> u8 { - OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + OBJECT_CONTENT_CODEC_FORMAT_RAW } } @@ -62,6 +62,10 @@ impl GroupBodyContent { &mut self.common_mut().ood_list } + pub fn version(&self) -> u64 { + self.common().version + } + fn common(&self) -> &CommonGroupBodyContent { match self { GroupBodyContent::Org(body) => &body.common, @@ -176,6 +180,22 @@ impl Group { self.common_mut().ood_list = oods; } + pub fn version(&self) -> u64 { + self.common().version + } + + pub fn set_version(&mut self, version: u64) { + self.common_mut().version = version; + } + + pub fn consensus_interval(&self) -> u64 { + self.common().consensus_interval + } + + pub fn set_consensus_interval(&mut self, interval: u64) { + self.common_mut().consensus_interval = interval; + } + pub fn join_member( &self, member_id: &ObjectId, @@ -184,11 +204,29 @@ impl Group { unimplemented!() } - pub fn verify(&self, signature: &GroupJoinSignature, member_id: &ObjectId, public_key: &PublicKey) -> BuckyResult { + pub fn verify( + &self, + signature: &GroupJoinSignature, + member_id: &ObjectId, + public_key: &PublicKey, + ) -> BuckyResult { + unimplemented!() + } + + pub fn verify_member( + &self, + member_id: &ObjectId, + is_admin: bool, + public_key: &PublicKey, + ) -> BuckyResult { unimplemented!() } - pub fn verify_member(&self, member_id: &ObjectId, is_admin: bool, publick_key: &PublicKey) -> BuckyResult { + pub fn verify_members( + &self, + members: &[(ObjectId, PublicKey)], + is_admin: bool, + ) -> BuckyResult { unimplemented!() } @@ -248,6 +286,19 @@ impl Group { } } + pub fn group_hash(&self) -> ObjectId { + let mut without_sign = self.clone(); + without_sign.common_mut().join_signatures = vec![]; + + let mut hash = HashValue::default(); + let remain = without_sign + .raw_encode(hash.as_mut_slice(), &Some(RawEncodePurpose::Hash)) + .unwrap(); + assert_eq!(remain.len(), 0); + + ObjectId::from_slice_value(&hash.as_slice()[..31]) + } + fn common(&self) -> &CommonGroupBodyContent { self.body().as_ref().unwrap().content().common() } @@ -423,7 +474,6 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { pub struct GroupJoinSignature { signature: Signature, member_id: ObjectId, - timestamp: u64, is_admin: bool, hash: HashValue, } @@ -435,7 +485,6 @@ impl TryFrom for GroupJoinSignature { let ret = Self { signature: ProtobufCodecHelper::decode_buf(value.signature)?, member_id: ProtobufCodecHelper::decode_buf(value.member_id)?, - timestamp: value.timestamp, is_admin: value.is_admin, hash: ProtobufCodecHelper::decode_buf(value.hash)?, }; @@ -452,7 +501,6 @@ impl TryFrom<&GroupJoinSignature> for protos::GroupJoinSignature { ret.signature = value.signature.to_vec()?; ret.member_id = value.member_id.to_vec()?; - ret.timestamp = value.timestamp; ret.is_admin = value.is_admin; ret.hash = value.hash.to_vec()?; diff --git a/src/component/cyfs-base/src/objects/mock.rs b/src/component/cyfs-base/src/objects/mock.rs new file mode 100644 index 000000000..edda480db --- /dev/null +++ b/src/component/cyfs-base/src/objects/mock.rs @@ -0,0 +1,19 @@ +use crate::ObjectId; + +pub trait CustomObjectId { + fn from_slice_value(buf: &[u8]) -> Self; + fn get_slice_value(&self) -> &[u8]; +} + +impl CustomObjectId for ObjectId { + fn from_slice_value(buf: &[u8]) -> Self { + assert!(buf.len() <= 31); + let mut value = [0u8; 32]; + value[1..buf.len() + 1].copy_from_slice(buf); + ObjectId::clone_from_slice(&value) + } + + fn get_slice_value(&self) -> &[u8] { + &self.as_slice()[1..] + } +} diff --git a/src/component/cyfs-base/src/objects/mod.rs b/src/component/cyfs-base/src/objects/mod.rs index a3ea14b12..5c23701dd 100644 --- a/src/component/cyfs-base/src/objects/mod.rs +++ b/src/component/cyfs-base/src/objects/mod.rs @@ -9,6 +9,8 @@ mod diff; mod dir; mod empty; mod file; +mod group; +mod mock; mod named_object_id; mod ndn; mod object; @@ -22,7 +24,6 @@ mod object_typeless; mod people; mod proof_of_service; mod raw_diff; -mod group; mod standard; mod tx; mod union_account; @@ -39,6 +40,8 @@ pub use device::*; pub use dir::*; pub use empty::*; pub use file::*; +pub use group::*; +pub use mock::*; pub use named_object_id::*; pub use ndn::*; pub use object::*; @@ -53,7 +56,6 @@ pub use object_typeless::*; pub use people::*; pub use proof_of_service::*; pub use raw_diff::*; -pub use group::*; pub use standard::*; pub use tx::*; pub use union_account::*; diff --git a/src/component/cyfs-chunk-lib/src/chunk.rs b/src/component/cyfs-chunk-lib/src/chunk.rs index 3c1e25a39..b6c180828 100644 --- a/src/component/cyfs-chunk-lib/src/chunk.rs +++ b/src/component/cyfs-chunk-lib/src/chunk.rs @@ -2,8 +2,8 @@ use crate::SharedMemChunk; use crate::{MMapChunk, MemChunk}; use cyfs_base::*; -use cyfs_util::AsyncReadWithSeek; use cyfs_debug::Mutex; +use cyfs_util::AsyncReadWithSeek; use std::future::Future; use std::io::SeekFrom; @@ -140,7 +140,7 @@ impl async_std::io::Seek for ChunkRead { } } -use async_std::io::{Seek, Read}; +use async_std::io::{Read, Seek}; use std::ops::Range; impl AsyncReadWithSeek for ChunkRead {} @@ -320,3 +320,35 @@ impl async_std::io::Write for ChunkWrite { Poll::Ready(Ok(())) } } + +impl From<&Group> for ChunkMeta { + fn from(group: &Group) -> Self { + let len = group.raw_measure(&None).unwrap(); + let mut buf = vec![0u8; len]; + let remain = group.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + ChunkMeta::MemChunk(buf) + } +} + +impl TryFrom<&ChunkMeta> for Group { + type Error = BuckyError; + + fn try_from(value: &ChunkMeta) -> Result { + match value { + ChunkMeta::MemChunk(buf) => { + let (group, remain) = Group::raw_decode(buf.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(group) + } + ChunkMeta::MMapChunk(_, _) => Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("expected ChunkMeta::MemChunk, got ChunkMeta::MMapChunk"), + )), + ChunkMeta::SharedMemChunk(_, _, _) => Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("expected ChunkMeta::MemChunk, got ChunkMeta::SharedMemChunk"), + )), + } + } +} diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index d29f53f82..3043faa2e 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -316,7 +316,7 @@ message SyncResponseObjectMetaInfo { optional uint32 access_string = 5; } -message GroupRPathDescContent { +message GroupRPath { bytes group_id = 1; bytes dec_id = 2; string r_path = 3; @@ -324,7 +324,7 @@ message GroupRPathDescContent { message GroupProposalDescContent { // target - bytes r_path_id = 1; + GroupRPath r_path = 1; // for app string method = 2; @@ -343,46 +343,80 @@ message GroupProposalBodyContent { message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; - string decide = 3; + bytes decide = 3; } repeated Signature decide_signatures = 2; } -message GroupUpdateGroupDescContent { - repeated bytes dec_id = 1; // the proccesor decs - optional bytes payload = 2; +message GroupUpdateGroupPropsalParam { + repeated bytes target_dec_id = 1; // the proccesor decs + optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) + bytes to_chunk_id = 3; // Chunk(Encode(Group)) } -message GroupUpdateGroupBodyContent { - optional bytes payload = 1; +message GroupPropsalDecideParam { + bytes signature = 1; // sign(hash(ProposalId, owner, decide)) + bytes proposal_id = 2; + bytes decide = 3; +} + +message HotstuffBlockQc { + bytes block_id = 1; + uint64 round = 2; + uint64 dummy_round = 3; + + message VoteSignature { + bytes voter = 1; + bytes signature = 2; + } + + repeated VoteSignature votes = 4; +} + +message HotstuffTimeout { + uint64 round = 1; + + message VoteSignature { + bytes voter = 1; + uint64 high_qc_round = 2; + bytes signature = 3; + } + + repeated VoteSignature votes = 2; } message GroupConsensusBlockDescContent { // target - bytes r_path_id = 1; + GroupRPath r_path = 1; // input - bytes proposals_hash = 2; + bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) // result bytes result_state_id = 3; - bytes proposal_result_states_hash = 4; - bytes proposal_receiptes_hash = 5; - uint64 version_seq = 6; + uint64 height = 4; // time - bytes meta_block_id = 7; - uint64 timestamp = 8; + bytes meta_block_id = 5; + uint64 timestamp = 6; - // prev - optional bytes prev_block_id = 9; // the first block is none + uint64 round = 7; + bytes group_chunk_id = 8; } message GroupConsensusBlockBodyContent { - repeated bytes proposals = 1; - repeated bytes proposal_result_states = 2; - repeated bytes proposal_receiptes = 3; + message Proposal { + bytes proposal_id = 1; + bytes proposal_result_state = 2; + bytes proposal_receipt = 3; + bytes context = 4; + } + + repeated Proposal proposals = 1; + + optional HotstuffBlockQc qc = 2; + optional HotstuffTimeout tc = 3; } message GroupRPathSubStatus { @@ -392,8 +426,7 @@ message GroupRPathSubStatus { message GroupRPathStatusDescContent { bytes block_id = 1; - optional GroupRPathSubStatus sub_status = 2; - optional bytes sub_status_hash = 3; + optional bytes sub_status_hash = 2; } message GroupRPathStatusBodyContent { @@ -402,7 +435,7 @@ message GroupRPathStatusBodyContent { message GroupActionDescContent { // target - bytes r_path_id = 1; + GroupRPath r_path = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 7f0572430..724f0debb 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -61,12 +61,11 @@ pub enum CoreObjectType { PerfOperation = 600, // Group - GroupRPath = 700, - GroupProposal = 701, - GroupUpdateGroup = 702, - GroupConsensusBlock = 703, - GroupRPathStatus = 704, - GroupAction = 705, + GroupProposal = 700, + GroupUpdateGroup = 701, + GroupConsensusBlock = 702, + GroupRPathStatus = 703, + GroupAction = 704, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 55915f963..2b5e45872 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -1,6 +1,9 @@ -use std::sync::atomic::{AtomicU8, Ordering}; +use std::sync::{ + atomic::{AtomicU8, Ordering}, + Arc, +}; -use crate::CoreObjectType; +use crate::{CoreObjectType, GroupRPath}; use cyfs_base::*; use serde::Serialize; use sha2::Digest; @@ -8,15 +11,14 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path_id: ObjectId, - proposals_hash: HashValue, + r_path: GroupRPath, + body_hash: HashValue, result_state_id: ObjectId, - proposal_result_states_hash: HashValue, - proposal_receiptes_hash: HashValue, - version_seq: u64, + height: u64, meta_block_id: ObjectId, timestamp: u64, - prev_block_id: Option, + round: u64, + group_chunk_id: ObjectId, } impl DescContent for GroupConsensusBlockDescContent { @@ -38,12 +40,130 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[derive(Clone, ProtobufTransformType)] +#[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] +pub struct HotstuffBlockQCSign { + pub voter: ObjectId, + pub signature: Signature, +} + +impl ProtobufTransform + for HotstuffBlockQCSign +{ + fn transform( + value: crate::codec::protos::hotstuff_block_qc::VoteSignature, + ) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCSign> + for crate::codec::protos::hotstuff_block_qc::VoteSignature +{ + fn transform(value: &HotstuffBlockQCSign) -> BuckyResult { + Ok(Self { + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }) + } +} + +#[derive(Default, Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(crate::codec::protos::HotstuffBlockQc)] +pub struct HotstuffBlockQC { + pub block_id: ObjectId, + pub round: u64, + pub dummy_round: u64, + pub votes: Vec, +} + +#[derive(Clone, ProtobufTransformType)] +#[cyfs_protobuf_type(crate::codec::protos::hotstuff_timeout::VoteSignature)] +pub struct HotstuffTimeoutSign { + pub voter: ObjectId, + pub high_qc_round: u64, + pub signature: Signature, +} + +impl ProtobufTransform + for HotstuffTimeoutSign +{ + fn transform( + value: crate::codec::protos::hotstuff_timeout::VoteSignature, + ) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + high_qc_round: value.high_qc_round, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutSign> + for crate::codec::protos::hotstuff_timeout::VoteSignature +{ + fn transform(value: &HotstuffTimeoutSign) -> BuckyResult { + Ok(Self { + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + high_qc_round: value.high_qc_round, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(crate::codec::protos::HotstuffTimeout)] +pub struct HotstuffTimeout { + pub round: u64, + pub votes: Vec, +} + +#[derive(Clone, ProtobufTransformType)] +#[cyfs_protobuf_type(crate::codec::protos::group_consensus_block_body_content::Proposal)] +pub struct GroupConsensusBlockProposal { + pub proposal: ObjectId, + pub result_state: ObjectId, + pub receipt: Vec, + pub context: Vec, +} + +impl ProtobufTransform + for GroupConsensusBlockProposal +{ + fn transform( + value: crate::codec::protos::group_consensus_block_body_content::Proposal, + ) -> BuckyResult { + Ok(Self { + proposal: ObjectId::raw_decode(value.proposal_id.as_slice())?.0, + result_state: ObjectId::raw_decode(&value.proposal_result_state.as_slice())?.0, + receipt: value.proposal_receipt.clone(), + context: value.context.clone(), + }) + } +} + +impl ProtobufTransform<&GroupConsensusBlockProposal> + for crate::codec::protos::group_consensus_block_body_content::Proposal +{ + fn transform(value: &GroupConsensusBlockProposal) -> BuckyResult { + Ok(Self { + proposal_id: value.proposal.to_vec()?, + proposal_result_state: value.result_state.to_vec()?, + proposal_receipt: value.receipt.clone(), + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockBodyContent)] pub struct GroupConsensusBlockBodyContent { - proposals: Vec, - proposal_result_states: Vec, - proposal_receiptes: Vec, + proposals: Vec, + qc: Option, + tc: Option, } impl BodyContent for GroupConsensusBlockBodyContent { @@ -58,7 +178,8 @@ type GroupConsensusBlockBuilder = NamedObjectBuilder; pub type GroupConsensusBlockId = NamedObjectId; -pub struct GroupConsensusBlock(NamedObjectBase, AtomicU8); +#[derive(Clone)] +pub struct GroupConsensusBlock(NamedObjectBase, Arc); const BLOCK_CHECK_STATE_NONE: u8 = 0; const BLOCK_CHECK_STATE_SUCC: u8 = 1; @@ -75,70 +196,75 @@ impl GroupConsensusBlockDescContent { } } +impl GroupConsensusBlockBodyContent { + fn hash(&self) -> HashValue { + let buf = self.to_vec().unwrap(); + let mut sha256 = sha2::Sha256::new(); + sha256.input(buf.as_slice()); + sha256.result().into() + } +} + pub trait GroupConsensusBlockObject { fn create( - r_path_id: ObjectId, - proposals: Vec, + r_path: GroupRPath, + proposals: Vec, result_state_id: ObjectId, - proposal_result_states: Vec, - proposal_receiptes: Vec, - version_seq: u64, + height: u64, meta_block_id: ObjectId, - prev_block_id: Option, + round: u64, + group_chunk_id: ObjectId, + qc: Option, + tc: Option, owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path_id(&self) -> &ObjectId; - fn proposals(&self) -> &Vec; + fn r_path(&self) -> &GroupRPath; + fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &ObjectId; - fn proposal_result_states(&self) -> &Vec; - fn proposal_receiptes(&self) -> &Vec; - fn version_seq(&self) -> u64; + fn height(&self) -> u64; fn meta_block_id(&self) -> &ObjectId; - fn prev_block_id(&self) -> &Option; + fn prev_block_id(&self) -> Option<&ObjectId>; fn owner(&self) -> &ObjectId; fn named_object(&self) -> &NamedObjectBase; + fn round(&self) -> u64; + fn group_chunk_id(&self) -> &ObjectId; + fn qc(&self) -> &Option; + fn tc(&self) -> &Option; } impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path_id: ObjectId, - proposals: Vec, + r_path: GroupRPath, + proposals: Vec, result_state_id: ObjectId, - proposal_result_states: Vec, - proposal_receiptes: Vec, - version_seq: u64, + height: u64, meta_block_id: ObjectId, - prev_block_id: Option, + round: u64, + group_chunk_id: ObjectId, + qc: Option, + tc: Option, owner: ObjectId, ) -> Self { + let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; + let desc = GroupConsensusBlockDescContent { - r_path_id, - proposals_hash: GroupConsensusBlockDescContent::hash_object_vec(proposals.as_slice()), + r_path, result_state_id, - proposal_result_states_hash: GroupConsensusBlockDescContent::hash_object_vec( - proposal_result_states.as_slice(), - ), - proposal_receiptes_hash: GroupConsensusBlockDescContent::hash_object_vec( - proposal_receiptes.as_slice(), - ), - version_seq, + + height, meta_block_id, timestamp: bucky_time_now(), - prev_block_id, - }; - - let body = GroupConsensusBlockBodyContent { - proposals, - proposal_result_states, - proposal_receiptes, + body_hash: body.hash(), + round, + group_chunk_id, }; let block = GroupConsensusBlockBuilder::new(desc, body) .owner(owner) .build(); - Self(block, AtomicU8::new(BLOCK_CHECK_STATE_SUCC)) + Self(block, Arc::new(AtomicU8::new(BLOCK_CHECK_STATE_SUCC))) } fn check(&self) -> bool { @@ -146,15 +272,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { if state == BLOCK_CHECK_STATE_NONE { let desc = self.0.desc().content(); let body = self.0.body().as_ref().unwrap().content(); - if GroupConsensusBlockDescContent::hash_object_vec(body.proposals.as_slice()) - != desc.proposals_hash - || GroupConsensusBlockDescContent::hash_object_vec( - body.proposal_result_states.as_slice(), - ) != desc.proposal_result_states_hash - || GroupConsensusBlockDescContent::hash_object_vec( - body.proposal_receiptes.as_slice(), - ) != desc.proposal_receiptes_hash - { + if body.hash() != desc.body_hash { self.1.store(BLOCK_CHECK_STATE_FAIL, Ordering::SeqCst); false } else { @@ -166,12 +284,12 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path_id(&self) -> &ObjectId { + fn r_path(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path_id + &desc.r_path } - fn proposals(&self) -> &Vec { + fn proposals(&self) -> &Vec { let body = self.0.body().as_ref().unwrap().content(); &body.proposals } @@ -181,19 +299,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &desc.result_state_id } - fn proposal_result_states(&self) -> &Vec { - let body = self.0.body().as_ref().unwrap().content(); - &body.proposal_result_states - } - - fn proposal_receiptes(&self) -> &Vec { - let body = self.0.body().as_ref().unwrap().content(); - &body.proposal_receiptes - } - - fn version_seq(&self) -> u64 { + fn height(&self) -> u64 { let desc = self.0.desc().content(); - desc.version_seq + desc.height } fn meta_block_id(&self) -> &ObjectId { @@ -201,9 +309,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &desc.meta_block_id } - fn prev_block_id(&self) -> &Option { - let desc = self.0.desc().content(); - &desc.prev_block_id + fn prev_block_id(&self) -> Option<&ObjectId> { + let body = self.0.body().as_ref().unwrap().content(); + body.qc.as_ref().map(|qc| &qc.block_id) } fn owner(&self) -> &ObjectId { @@ -214,6 +322,50 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { fn named_object(&self) -> &NamedObjectBase { &self.0 } + + fn round(&self) -> u64 { + let desc = self.0.desc().content(); + desc.round + } + + fn group_chunk_id(&self) -> &ObjectId { + let desc = self.0.desc().content(); + &desc.group_chunk_id + } + + fn qc(&self) -> &Option { + let body = self.0.body().as_ref().unwrap().content(); + &body.qc + } + + fn tc(&self) -> &Option { + let body = self.0.body().as_ref().unwrap().content(); + &body.tc + } +} + +impl RawEncode for GroupConsensusBlock { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + self.0.raw_measure(purpose) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + self.0.raw_encode(buf, purpose) + } +} + +impl<'de> RawDecode<'de> for GroupConsensusBlock { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let (obj, remain) = NamedObjectBase::::raw_decode(buf)?; + Ok(( + Self(obj, Arc::new(AtomicU8::new(BLOCK_CHECK_STATE_NONE))), + remain, + )) + } } #[cfg(test)] @@ -223,23 +375,23 @@ mod test { #[async_std::test] async fn create_group_rpath() { - let secret1 = PrivateKey::generate_rsa(1024).unwrap(); - let secret2 = PrivateKey::generate_rsa(1024).unwrap(); - let people1 = People::new(None, vec![], secret1.public(), None, None, None).build(); - let people1_id = people1.desc().people_id(); - let people2 = People::new(None, vec![], secret2.public(), None, None, None).build(); - let _people2_id = people2.desc().people_id(); - - let g1 = GroupConsensusBlock::create( - people1_id.object_id().to_owned(), - people1_id.object_id().to_owned(), - people1_id.to_string(), - ); - - let buf = g1.to_vec().unwrap(); - let add2 = GroupConsensusBlock::clone_from_slice(&buf).unwrap(); - let any = AnyNamedObject::clone_from_slice(&buf).unwrap(); - assert_eq!(g1.desc().calculate_id(), add2.desc().calculate_id()); - assert_eq!(g1.desc().calculate_id(), any.calculate_id()); + // let secret1 = PrivateKey::generate_rsa(1024).unwrap(); + // let secret2 = PrivateKey::generate_rsa(1024).unwrap(); + // let people1 = People::new(None, vec![], secret1.public(), None, None, None).build(); + // let people1_id = people1.desc().people_id(); + // let people2 = People::new(None, vec![], secret2.public(), None, None, None).build(); + // let _people2_id = people2.desc().people_id(); + + // let g1 = GroupConsensusBlock::create( + // people1_id.object_id().to_owned(), + // people1_id.object_id().to_owned(), + // people1_id.to_string(), + // ); + + // let buf = g1.to_vec().unwrap(); + // let add2 = GroupConsensusBlock::clone_from_slice(&buf).unwrap(); + // let any = AnyNamedObject::clone_from_slice(&buf).unwrap(); + // assert_eq!(g1.desc().calculate_id(), add2.desc().calculate_id()); + // assert_eq!(g1.desc().calculate_id(), any.calculate_id()); } } diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 62244f0d6..adba33d44 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,6 +1,4 @@ -use std::hash::Hash; - -use crate::CoreObjectType; +use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use serde::Serialize; @@ -9,7 +7,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path_id: ObjectId, + r_path: GroupRPath, method: String, params: Option>, @@ -42,7 +40,7 @@ impl DescContent for GroupProposalDescContent { pub struct GroupProposalSignature { signature: Signature, proponent_id: ObjectId, - decide: String, + decide: Vec, } impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> @@ -119,15 +117,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> } } -type GroupProposalType = NamedObjType; -type GroupProposalBuilder = NamedObjectBuilder; +pub type GroupProposalType = NamedObjType; +pub type GroupProposalBuilder = + NamedObjectBuilder; pub type GroupProposalId = NamedObjectId; pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path_id: ObjectId, + r_path: GroupRPath, method: String, params: Option>, timestamp: Option, @@ -136,7 +135,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path_id, + r_path, method, params, meta_block_id, @@ -151,12 +150,12 @@ impl GroupProposalBodyContent { fn hash_decide_signature( proposal_id: &ObjectId, proponent_id: &ObjectId, - decide: &str, + decide: &[u8], ) -> HashValue { let mut sha256 = sha2::Sha256::new(); sha256.input(proposal_id.as_slice()); sha256.input(proponent_id.as_slice()); - sha256.input(decide.as_bytes()); + sha256.input(decide); sha256.result().into() } } @@ -164,16 +163,17 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path_id: ObjectId, + r_path: GroupRPath, method: String, params: Option>, + payload: Option>, timestamp: Option, meta_block_id: Option, effective_begining: Option, effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path_id(&self) -> &ObjectId; + fn r_path(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -189,34 +189,40 @@ pub trait GroupProposalObject { async fn verify_member_decide( &self, member_id: &ObjectId, - publick_key: &PublicKey, - ) -> BuckyResult>; + public_key: &PublicKey, + ) -> BuckyResult>; fn decided_members_no_verify(&self) -> &Vec; async fn decide( - &mut self, + &self, member_id: ObjectId, - decide: String, + decide: Vec, private_key: &PrivateKey, - ) -> BuckyResult<()>; + ) -> BuckyResult; - fn merge_decide(&mut self, signatures: &[GroupProposalSignature]); + async fn verify_and_merge_decide( + &mut self, + decide: &GroupPropsalDecideParam, + member_id: ObjectId, + public_key: &PublicKey, + ) -> BuckyResult<()>; } #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path_id: ObjectId, + r_path: GroupRPath, method: String, params: Option>, + payload: Option>, timestamp: Option, meta_block_id: Option, effective_begining: Option, effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path_id, + r_path, method, params, meta_block_id, @@ -225,11 +231,17 @@ impl GroupProposalObject for GroupProposal { effective_ending, }; - GroupProposalBuilder::new(desc, GroupProposalBodyContent::default()) + GroupProposalBuilder::new( + desc, + GroupProposalBodyContent { + payload, + decide_signatures: vec![], + }, + ) } - fn r_path_id(&self) -> &ObjectId { - &self.desc().content().r_path_id + fn r_path(&self) -> &GroupRPath { + &self.desc().content().r_path } fn method(&self) -> &str { @@ -305,8 +317,8 @@ impl GroupProposalObject for GroupProposal { async fn verify_member_decide( &self, member_id: &ObjectId, - publick_key: &PublicKey, - ) -> BuckyResult> { + public_key: &PublicKey, + ) -> BuckyResult> { let signs = self .body() .as_ref() @@ -314,17 +326,22 @@ impl GroupProposalObject for GroupProposal { .content() .decide_signatures .as_slice(); + + let proposal_id = self.desc().object_id(); + let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + let mut decides = vec![]; + for sign in signs { if &sign.proponent_id == member_id { - let verifier = RsaCPUObjectVerifier::new(publick_key.clone()); let hash = GroupProposalBodyContent::hash_decide_signature( - &self.desc().object_id(), + &proposal_id, &sign.proponent_id, - sign.decide.as_str(), + sign.decide.as_slice(), ); if verifier.verify(hash.as_slice(), &sign.signature).await { - return Ok(Some(sign.decide.as_str())); + decides.push(sign.decide.as_slice()); } else { return Err(BuckyError::new( BuckyErrorCode::InvalidSignature, @@ -334,7 +351,7 @@ impl GroupProposalObject for GroupProposal { } } - Ok(None) + Ok(decides) } fn decided_members_no_verify(&self) -> &Vec { @@ -342,11 +359,11 @@ impl GroupProposalObject for GroupProposal { } async fn decide( - &mut self, + &self, member_id: ObjectId, - decide: String, + decide: Vec, private_key: &PrivateKey, - ) -> BuckyResult<()> { + ) -> BuckyResult { let signs = &self.body().as_ref().unwrap().content().decide_signatures; if signs.iter().find(|s| s.proponent_id == member_id).is_some() { @@ -356,10 +373,12 @@ impl GroupProposalObject for GroupProposal { )); } + let proposal_id = self.desc().object_id(); + let hash = GroupProposalBodyContent::hash_decide_signature( - &self.desc().object_id(), + &proposal_id, &member_id, - decide.as_str(), + decide.as_slice(), ); let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); @@ -367,39 +386,61 @@ impl GroupProposalObject for GroupProposal { .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) .await?; - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - - signs.push(GroupProposalSignature { - signature: sign, - proponent_id: member_id, - decide, - }); - Ok(()) + Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) } - fn merge_decide(&mut self, signatures: &[GroupProposalSignature]) { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - - signatures.iter().for_each(|add| { - if signs - .iter() - .find(|exist| exist.proponent_id == add.proponent_id) - .is_some() - { - return; + async fn verify_and_merge_decide( + &mut self, + decide: &GroupPropsalDecideParam, + member_id: ObjectId, + public_key: &PublicKey, + ) -> BuckyResult<()> { + let proposal_id = self.desc().object_id(); + + if decide.proposal_id() != &proposal_id { + return Err(BuckyError::new( + BuckyErrorCode::NotMatch, + format!( + "proposal id not match for decide signature: {}/{}", + proposal_id, + decide.proposal_id() + ), + )); + } + + let hash = GroupProposalBodyContent::hash_decide_signature( + &proposal_id, + &member_id, + decide.decide(), + ); + + let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + if verifier.verify(hash.as_slice(), decide.signature()).await { + let signs = &mut self + .body_mut() + .as_mut() + .unwrap() + .content_mut() + .decide_signatures; + for exist in signs.iter() { + if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + return Ok(()); + } } - signs.push(add.clone()); - }); + + signs.push(GroupProposalSignature { + signature: decide.signature().clone(), + proponent_id: member_id, + decide: Vec::from(decide.decide()), + }); + + Ok(()) + } else { + Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid signature", + )) + } } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/group_proposal_decide_param.rs b/src/component/cyfs-core/src/group/group_proposal_decide_param.rs new file mode 100644 index 000000000..918e804ff --- /dev/null +++ b/src/component/cyfs-core/src/group/group_proposal_decide_param.rs @@ -0,0 +1,51 @@ +use cyfs_base::*; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(crate::codec::protos::GroupPropsalDecideParam)] +pub struct GroupPropsalDecideParam { + signature: Signature, + proposal_id: ObjectId, + decide: Vec, +} + +impl GroupPropsalDecideParam { + pub fn new(signature: Signature, proposal_id: ObjectId, decide: Vec) -> Self { + Self { + signature, + proposal_id, + decide, + } + } + + pub fn signature(&self) -> &Signature { + &self.signature + } + + pub fn proposal_id(&self) -> &ObjectId { + &self.proposal_id + } + + pub fn decide(&self) -> &[u8] { + &self.decide + } +} + +impl ProtobufTransform for GroupPropsalDecideParam { + fn transform(value: crate::codec::protos::GroupPropsalDecideParam) -> BuckyResult { + Ok(Self { + signature: Signature::raw_decode(value.signature.as_slice())?.0, + proposal_id: ObjectId::transform(value.proposal_id)?, + decide: value.decide, + }) + } +} + +impl ProtobufTransform<&GroupPropsalDecideParam> for crate::codec::protos::GroupPropsalDecideParam { + fn transform(value: &GroupPropsalDecideParam) -> BuckyResult { + Ok(Self { + signature: value.signature.to_vec()?, + proposal_id: value.proposal_id.to_vec()?, + decide: value.decide.clone(), + }) + } +} diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 6f7dea088..a59aff5e3 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,41 +1,15 @@ -use crate::CoreObjectType; use cyfs_base::*; use serde::Serialize; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] -#[cyfs_protobuf_type(crate::codec::protos::GroupRPathDescContent)] -pub struct GroupRPathDescContent { +#[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] +pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, r_path: String, } -impl DescContent for GroupRPathDescContent { - fn obj_type() -> u16 { - CoreObjectType::GroupRPath as u16 - } - - fn format(&self) -> u8 { - OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF - } - - fn debug_info() -> String { - String::from("GroupRPathDescContent") - } - - type OwnerType = SubDescNone; - type AreaType = SubDescNone; - type AuthorType = SubDescNone; - type PublicKeyType = SubDescNone; -} - -type GroupRPathType = NamedObjType; -type GroupRPathBuilder = NamedObjectBuilder; - -pub type GroupRPathId = NamedObjectId; -pub type GroupRPath = NamedObjectBase; - -impl GroupRPathDescContent { +impl GroupRPath { pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { Self { group_id, @@ -43,62 +17,16 @@ impl GroupRPathDescContent { r_path, } } -} - -pub trait GroupRPathObject { - fn create(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self; - fn group_id(&self) -> &ObjectId; - fn dec_id(&self) -> &ObjectId; - fn r_path(&self) -> &str; -} - -impl GroupRPathObject for GroupRPath { - fn create(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { - let desc = GroupRPathDescContent { - group_id, - dec_id, - r_path, - }; - - GroupRPathBuilder::new(desc, EmptyProtobufBodyContent::default()).build() - } - - fn group_id(&self) -> &ObjectId { - &self.desc().content().group_id - } - fn dec_id(&self) -> &ObjectId { - &self.desc().content().dec_id + pub fn group_id(&self) -> &ObjectId { + &self.group_id } - fn r_path(&self) -> &str { - self.desc().content().r_path.as_str() + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id } -} -#[cfg(test)] -mod test { - use super::{GroupRPath, GroupRPathObject}; - use cyfs_base::*; - - #[async_std::test] - async fn create_group_rpath() { - let secret1 = PrivateKey::generate_rsa(1024).unwrap(); - let secret2 = PrivateKey::generate_rsa(1024).unwrap(); - let people1 = People::new(None, vec![], secret1.public(), None, None, None).build(); - let people1_id = people1.desc().people_id(); - let people2 = People::new(None, vec![], secret2.public(), None, None, None).build(); - let _people2_id = people2.desc().people_id(); - - let g1 = GroupRPath::create( - people1_id.object_id().to_owned(), - people1_id.object_id().to_owned(), - people1_id.to_string(), - ); - let buf = g1.to_vec().unwrap(); - let add2 = GroupRPath::clone_from_slice(&buf).unwrap(); - let any = AnyNamedObject::clone_from_slice(&buf).unwrap(); - assert_eq!(g1.desc().calculate_id(), add2.desc().calculate_id()); - assert_eq!(g1.desc().calculate_id(), any.calculate_id()); + pub fn r_path(&self) -> &str { + self.r_path.as_str() } } diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs new file mode 100644 index 000000000..9159adcb5 --- /dev/null +++ b/src/component/cyfs-core/src/group/group_rpath_status.rs @@ -0,0 +1,12 @@ +use std::sync::atomic::{AtomicU8, Ordering}; + +use crate::CoreObjectType; +use cyfs_base::*; +use serde::Serialize; +use sha2::Digest; + +// TODO: 后面再封装这个对象 +pub struct GroupRPathStatus {} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-core/src/group/group_update_group_proposal_param.rs b/src/component/cyfs-core/src/group/group_update_group_proposal_param.rs new file mode 100644 index 000000000..986b00e14 --- /dev/null +++ b/src/component/cyfs-core/src/group/group_update_group_proposal_param.rs @@ -0,0 +1,36 @@ +use cyfs_base::*; +use serde::Serialize; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[cyfs_protobuf_type(crate::codec::protos::GroupUpdateGroupPropsalParam)] +pub struct GroupUpdateGroupPropsalParam { + target_dec_id: Vec, + from_chunk_id: Option, + to_chunk_id: ObjectId, +} + +impl GroupUpdateGroupPropsalParam { + pub fn new( + target_dec_id: Vec, + from_chunk_id: Option, + to_chunk_id: ObjectId, + ) -> Self { + Self { + target_dec_id, + from_chunk_id, + to_chunk_id, + } + } + + pub fn target_dec_id(&self) -> &[ObjectId] { + self.target_dec_id.as_slice() + } + + pub fn from_chunk_id(&self) -> &Option { + &self.from_chunk_id + } + + pub fn to_chunk_id(&self) -> &ObjectId { + &self.to_chunk_id + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 0712ad5da..4c315c090 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,7 +1,13 @@ mod group_consensus_block; mod group_proposal; +mod group_proposal_decide_param; mod group_rpath; +mod group_rpath_status; +mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; +pub use group_proposal_decide_param::*; pub use group_rpath::*; +pub use group_rpath_status::*; +pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 43794e6f1..e35ad158b 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -3,18 +3,29 @@ name = 'cyfs-group' version = '0.0.1' authors = ['zhangzhen '] -edition = '2022' +edition = '2021' license = 'BSD-2-Clause' description = 'Rust cyfs-group package' [build-dependencies] +prost-build = { version = '0.11.5' } protoc-rust = '2' chrono = '0.4' protoc-bin-vendored = '3' [dependencies] +async-trait = "0.1.53" async-std = '1.11' log = '0.4' serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group/build.rs index 9d3a5a616..8d4efe9c9 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group/build.rs @@ -1,12 +1,13 @@ -extern crate protoc_rust; extern crate chrono; +extern crate protoc_rust; use std::io::Write; -static MOD_PROTOS_RS:&str = r#" +static MOD_PROTOS_RS: &str = r#" pub(crate) mod group_bft_protocol; +mod group_bft_protocol_with_macro; -pub(crate) use group_bft_protocol::*; +pub use group_bft_protocol_with_macro::*; "#; #[allow(dead_code)] @@ -23,8 +24,16 @@ fn gen_protos() { gen.run().expect("protoc error!"); - std::fs::File::create(out_dir + "/mod.rs").expect("write protos mod error") - .write_all(MOD_PROTOS_RS.as_ref()).expect("write protos mod error"); + let mut config = prost_build::Config::new(); + config.default_package_filename("group_bft_protocol_with_macro"); + config + .compile_protos(&["protos/group_bft_protocol.proto"], &["protos"]) + .unwrap(); + + std::fs::File::create(out_dir + "/mod.rs") + .expect("write protos mod error") + .write_all(MOD_PROTOS_RS.as_ref()) + .expect("write protos mod error"); } fn main() { diff --git a/src/component/cyfs-group/examples/app_example.rs b/src/component/cyfs-group/examples/app_example.rs new file mode 100644 index 000000000..5dcbfeef4 --- /dev/null +++ b/src/component/cyfs-group/examples/app_example.rs @@ -0,0 +1,162 @@ +mod Client { + use cyfs_core::GroupProposal; + + pub struct DecClient { + + } + + impl DecClient { + async fn do_something(&self) { + let rpath_client = RPathClient::new(); + + let field_path = "/xxx/yyy"; + let old_value = rpath_client.get_field(field_path).await; + let param = ObjectId::default(); // param = old_value.value + let proposal = self.make_proposal(param); + rpath_client.post_proposal(proposal).await; + } + + fn make_proposal(&self, param: ObjectId) -> GroupProposal { + unimplemented!() + } + } +} + +mod GroupDecService { + use cyfs_base::*; + use cyfs_core::GroupProposal; + use cyfs_group::{DelegateFactory, ExecuteResult, RPathControlMgr}; + + pub struct DecService {} + + impl DecService { + pub async fn run() { + let rpath_mgr = RPathControlMgr::new(DecAppId::default()); + + rpath_mgr.register(delegate_factory) + } + } + + pub struct GroupRPathDelegateFactory {} + + impl GroupRPathDelegateFactory { + pub fn is_accept( + &self, + group: &Group, + dec_id: &ObjectId, + rpath: &str, + with_proposal: Option<&GroupProposal>, + ) -> bool { + // 由应用定义是否接收该rpath,并启动共识过程,参与该rpath的信息维护 + true + } + } + + #[async_trait::async_trait] + impl DelegateFactory for GroupRPathDelegateFactory { + async fn create_rpath_delegate( + &self, + group: &Group, + dec_id: &ObjectId, + rpath: &str, + with_proposal: Option<&GroupProposal>, + ) -> BuckyResult> { + if self.is_accept(group, dec_id, rpath, with_proposal) { + // 如果接受,就提供该rpath的处理响应对象 + Ok(MyRPathDelegate::new()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "")) + } + } + } + + pub struct MyRPathDelegate {} + + impl MyRPathDelegate { + pub fn new() -> Self { + MyRPathDelegate {} + } + } + + impl MyRPathDelegate { + pub fn execute( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + ) -> BuckyResult { + let result_state_id = { + /** + * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + */ + ObjectId::default() + }; + + let return_object = { + /** + * 返回给Client的对象,相当于这个请求的结果或者叫回执? + */ + None + }; + + let context = { + /** + * 执行请求的上下文,运算过程中可能有验证节点无法得到的上下文信息(比如时间戳,随机数) + */ + Some(vec![]) + }; + + /** + * (result_state_id, return_object) = pre_state_id + proposal + context + */ + Ok(ExecuteResult { + result_state_id, + return_object, + context, + }) + } + + pub fn verify( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + execute_result: &ExecuteResult, + ) -> BuckyResult { + /** + * let is_same = (execute_result.result_state_id, execute_result.return_object) + * == pre_state_id + proposal + execute_result.context + */ + Ok(true) + } + } + + #[async_trait::async_trait] + impl RPathDelegate for MyRPathDelegate { + async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + ) -> BuckyResult { + self.execute(proposal, pre_state_id) + } + + async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + execute_result: &ExecuteResult, + ) -> BuckyResult { + self.verify(proposal, pre_state_id, execute_result) + } + + async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + execute_result: &ExecuteResult, + ) { + /** + * 提交到共识链上了,可能有些善后事宜 + */ + } + } +} diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index df26a09af..4e8275009 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -1,14 +1,17 @@ syntax = "proto3"; -message GroupConsensusBlockAckDescContent { +message HotstuffBlockQCVote { bytes block_id = 1; + uint64 round = 2; + uint64 dummy_round = 3; + bytes voter = 4; + bytes signature = 5; +} - enum AckStep { - Verify = 0; - Ack = 1; - AckAck = 2; - } - - AckStep step = 2; +message HotstuffTimeoutVote { + bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; } diff --git a/src/component/cyfs-group/readme.md b/src/component/cyfs-group/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-group/src/consensus/block.rs b/src/component/cyfs-group/src/consensus/block.rs new file mode 100644 index 000000000..0f4ef8371 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/block.rs @@ -0,0 +1,19 @@ +use cyfs_base::BuckyResult; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; + +pub trait AsBlock {} + +#[async_trait::async_trait] +pub trait BlockBuilder { + async fn build( + &self, + proposals: Vec, + ) -> BuckyResult>; +} + +impl AsBlock for GroupConsensusBlock {} + +pub struct GroupBlockBuilder {} + +#[async_trait::async_trait] +impl BlockBuilder for GroupBlockBuilder {} diff --git a/src/component/cyfs-group/src/consensus/consensus.rs b/src/component/cyfs-group/src/consensus/consensus.rs new file mode 100644 index 000000000..7aaf5d126 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/consensus.rs @@ -0,0 +1,25 @@ +// as miner in blockchain + +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupProposal; + +use crate::AsProposal; + +#[async_trait::async_trait] +pub trait AsConsensus { + async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()>; + async fn get_nonce(&self, account: &ObjectId) -> BuckyResult; +} + +pub(crate) trait AsConsensusInner { + fn get_pending_proposal(&self) -> Vec; + fn remove_proposal(&self, proposal_id: &ObjectId); +} + +pub struct Consensus {} + +impl Consensus { + pub fn create() -> Self { + Self {} + } +} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs new file mode 100644 index 000000000..c6d5a3518 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -0,0 +1,283 @@ +use std::sync::Arc; + +use async_std::channel::{Receiver, Sender}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; + +use crate::{ + consensus::{order_block::OrderBlockMgr, proposal, timer::Timer}, + Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + RPathDelegate, Storage, VoteMgr, +}; + +pub struct Hotstuff { + local_id: ObjectId, + committee: Committee, + store: Storage, + signer: RsaCPUObjectSigner, + round: u64, // 当前轮次 + last_committed_round: u64, // 最后提交的轮次 + high_qc: HotstuffBlockQC, // 最后一次通过投票的确认信息 + timer: Timer, // 定时器 + vote_mgr: VoteMgr, + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, + rx_message: Receiver, + delegate: Arc>, + order_block_mgr: OrderBlockMgr, +} + +impl Hotstuff { + pub fn spawn( + local_id: ObjectId, + committee: Committee, + store: Storage, + signer: RsaCPUObjectSigner, + vote_mgr: VoteMgr, + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, + rx_message: Receiver, + delegate: Arc>, + ) { + let last_committed_round = store.header_block().map_or(0, |block| block.round()); + let mut round = 0; + let mut high_qc = HotstuffBlockQC::default(); + + for block in store.prepares().values() { + if block.round() > round { + round = block.round(); + } + + if let Some(qc) = block.qc().as_ref() { + if qc.round > high_qc.round { + high_qc = qc.clone(); + } + } + } + + for block in store.pre_commits().values() { + if block.round() > round { + round = block.round(); + } + + if let Some(qc) = block.qc().as_ref() { + if qc.round > high_qc.round { + high_qc = qc.clone(); + } + } + } + + let obj = Self { + local_id, + committee, + store, + signer, + round, + last_committed_round, + high_qc, + timer: Timer::new(store.group().consensus_interval()), + vote_mgr, + network_sender, + rx_message, + delegate, + order_block_mgr: OrderBlockMgr::new(), + non_driver, + }; + } + + // TODO: 网络层应该防御,只从当前group节点获取信息 + async fn handle_block(&mut self, block: &GroupConsensusBlock) -> BuckyResult<()> { + /** + * 1. 验证block投票签名 + * 2. 验证出块节点 + * 3. 同步块 + * 4. 验证各个proposal执行结果 + */ + { + if let Some(last_proposal) = block.proposals().last() { + if &last_proposal.result_state != block.result_state_id() { + log::warn!("the result-state({}) in last-proposal is missmatch with block.result_state_id({})" + , last_proposal.result_state, block.result_state_id()); + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "result-state unmatch", + )); + } + } + } + + { + // check leader + let leader = self.committee.get_leader(block.group_chunk_id()).await?; + if &leader != block.owner() { + log::warn!( + "receive block from invalid leader({}), expected {}", + block.owner(), + leader + ); + return Err(BuckyError::new(BuckyErrorCode::Ignored, "invalid leader")); + } + } + + let (prev_block, proposals) = { + match self.store.block_linked(block).await? { + crate::storage::BlockLinkState::Expired => { + log::warn!("receive block expired."); + return Err(BuckyError::new(BuckyErrorCode::Ignored, "expired")); + } + crate::storage::BlockLinkState::DuplicateProposal => { + log::warn!("receive block with duplicate proposal."); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "duplicate proposal", + )); + } + crate::storage::BlockLinkState::Duplicate => { + log::warn!("receive duplicate block."); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "duplicate block", + )); + } + crate::storage::BlockLinkState::Link(prev_block, proposals) => { + // 顺序连接状态 + if block.proposals().is_empty() { + match prev_block.as_ref() { + Some(prev_block) => { + if block.result_state_id() != prev_block.result_state_id() { + log::warn!("block.result_state_id({}) is missmatch with prev_block.result_state_id({}) with no proposal." + , block.result_state_id(), prev_block.result_state_id()); + + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "result-state unmatch", + )); + } + } + None => { + log::warn!("the first block is empty, ignore."); + return Err(BuckyError::new( + BuckyErrorCode::Ignored, + "empty first block", + )); + } + } + } + (prev_block, proposals) + } + crate::storage::BlockLinkState::Pending => { + // 乱序,同步 + return self.order_block_mgr.push_block(block).await; + } + } + }; + + { + self.committee.verify_block(block).await?; + } + + { + let mut prev_state_id = prev_block + .as_ref() + .map_or(ObjectId::default(), |block| block.result_state_id().clone()); + + for proposal_exe_info in block.proposals() { + let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); + let receipt = if proposal_exe_info.receipt.len() > 0 { + Some(NONObjectInfo::new_from_object_raw( + proposal_exe_info.receipt.clone(), + )?) + } else { + None + }; + + let exe_result = ExecuteResult { + result_state_id: proposal_exe_info.result_state, + receipt, + context: proposal_exe_info.context.clone(), + }; + + if self + .delegate + .on_verify(proposal, prev_state_id, &exe_result) + .await? + { + prev_state_id = proposal_exe_info.result_state; + } else { + log::warn!("block verify failed by app, proposal: {}, prev_state: {}, expect-result: {}", + proposal_exe_info.proposal, prev_state_id, proposal_exe_info.result_state); + } + } + + assert_eq!( + &prev_state_id, + block.result_state_id(), + "the result state is missmatched" + ); + } + + unimplemented!() + } + + async fn process_block(&mut self, block: &GroupConsensusBlock) -> BuckyResult<()> { + /** + * 验证过的块执行这个函数 + */ + unimplemented!() + } + + async fn handle_vote(&mut self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { + unimplemented!() + } + + async fn handle_timeout(&mut self, timeout: &HotstuffTimeoutVote) -> BuckyResult<()> { + unimplemented!() + } + + async fn handle_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + unimplemented!() + } + + async fn local_timeout_round(&mut self) -> BuckyResult<()> { + unimplemented!() + } + + async fn run(&mut self) { + // Upon booting, generate the very first block (if we are the leader). + // Also, schedule a timer in case we don't hear from the leader. + self.timer.reset( + self.committee + .get_group(self.header_block()) + .await + .map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| g.consensus_interval()), + ); + if let Ok(leader) = self + .committee + .get_next_leader(self.store.header_block()) + .await + { + if leader == self.local_id { + self.generate_proposal(None).await; + } + } + + // This is the main loop: it processes incoming blocks and votes, + // and receive timeout notifications from our Timeout Manager. + loop { + let result = futures::select! { + Some(message) = self.rx_message.recv() => match message { + HotstuffMessage::Block(block) => self.handle_block(&block).await, + HotstuffMessage::BlockVote(vote) => self.handle_vote(&vote).await, + HotstuffMessage::TimeoutVote(timeout) => self.handle_timeout(&timeout).await, + HotstuffMessage::Timeout(tc) => self.handle_tc(&tc).await, + _ => panic!("Unexpected protocol message") + }, + Some(block) = self.rx_loopback.recv() => self.process_block(&block).await, + () = &mut self.timer => self.local_timeout_round().await, + }; + } + } +} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/mod.rs b/src/component/cyfs-group/src/consensus/hotstuff/mod.rs new file mode 100644 index 000000000..aacfc1367 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/hotstuff/mod.rs @@ -0,0 +1,3 @@ +mod hotstuff; + +pub use hotstuff::*; diff --git a/src/component/cyfs-group/src/consensus/mod.rs b/src/component/cyfs-group/src/consensus/mod.rs new file mode 100644 index 000000000..0f41c0ff3 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/mod.rs @@ -0,0 +1,13 @@ +mod block; +mod consensus; +mod hotstuff; +mod order_block; +mod proposal; +mod timer; +mod vote; + +pub use block::*; +pub use consensus::*; +pub use hotstuff::*; +pub use proposal::*; +pub use vote::*; diff --git a/src/component/cyfs-group/src/consensus/order_block/mod.rs b/src/component/cyfs-group/src/consensus/order_block/mod.rs new file mode 100644 index 000000000..12d837386 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/order_block/mod.rs @@ -0,0 +1,3 @@ +mod order_block_mgr; + +pub use order_block_mgr::*; \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs b/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs new file mode 100644 index 000000000..2a9a8bf33 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs @@ -0,0 +1,18 @@ +use cyfs_base::BuckyResult; +use cyfs_core::GroupConsensusBlock; + +pub struct OrderBlockMgr {} + +impl OrderBlockMgr { + pub fn new() -> Self { + Self {} + } + + pub async fn push_block(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn pop_link(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/consensus/proposal/mod.rs b/src/component/cyfs-group/src/consensus/proposal/mod.rs new file mode 100644 index 000000000..6aefbfd3d --- /dev/null +++ b/src/component/cyfs-group/src/consensus/proposal/mod.rs @@ -0,0 +1,5 @@ +mod proposal; +mod pending_proposal_mgr; + +pub use proposal::*; +pub use pending_proposal_mgr::*; diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs new file mode 100644 index 000000000..e03285f58 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -0,0 +1,110 @@ +use std::collections::HashMap; + +use async_std::channel::{Receiver, Sender}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::GroupProposal; +use futures::FutureExt; + +use crate::{AsProposal, BlockBuilder, GroupBlockBuilder, ASYNC_TIMEOUT}; + +pub enum ProposalConsumeMessage { + BuildBlock(GroupBlockBuilder), + Remove(Vec), +} + +pub struct PendingProposalMgr { + rx_product: Receiver, + rx_consume: Receiver, + network_sender: crate::network::Sender, + + // TODO: 需要设计一个结构便于按时间或数量拆分 + // TODO: 要把修改group的提案单独排序处理 + buffer: HashMap, +} + +impl PendingProposalMgr { + pub fn spawn( + rx_product: Receiver, + rx_consume: Receiver, + network_sender: crate::network::Sender, + ) { + async_std::task::spawn(async move { + Self { + rx_product, + rx_consume, + buffer: HashMap::new(), + network_sender, + } + .run() + .await + }); + } + + pub async fn build_block( + tx_consume: &Sender, + builder: GroupBlockBuilder, + ) -> BuckyResult<()> { + tx_consume + .send(ProposalConsumeMessage::BuildBlock(builder)) + .await + .map_err(|e| { + log::error!("[pending_proposal_mgr] send message(query) faield: {}", e); + BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") + }) + } + + pub async fn remove_proposals( + tx_consume: &Sender, + proposal_ids: Vec, + ) -> BuckyResult<()> { + tx_consume + .send(ProposalConsumeMessage::Remove(proposal_ids)) + .await + .map_err(|e| { + log::error!("[pending_proposal_mgr] send message(remove) faield: {}", e); + BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") + }) + } + + async fn build_block_impl(&mut self, builder: GroupBlockBuilder) -> BuckyResult<()> { + let proposals = self.buffer.drain().map(|(_, p)| p).collect(); + + let block = builder.build(proposals).await?; + if block.is_none() { + return Ok(()); + } + + /** + * TODO: + * 1. broadcast + */ + Ok(()) + } + + async fn run(&mut self) { + loop { + futures::select! { + proposal = self.rx_product.recv().fuse() => { + if let Ok(proposal) = proposal { + self.buffer.insert(proposal.id(), proposal); + } + }, + message = self.rx_consume.recv().fuse() => { + if let Ok(message) = message { + match message { + ProposalConsumeMessage::BuildBlock(builder) => { + let r = self.build_block_impl(builder).await; + notifier.send(r).await; + }, + ProposalConsumeMessage::Remove(proposal_ids) => { + for id in &proposal_ids { + self.buffer.remove(id); + } + } + } + } + } + } + } + } +} diff --git a/src/component/cyfs-group/src/consensus/proposal/proposal.rs b/src/component/cyfs-group/src/consensus/proposal/proposal.rs new file mode 100644 index 000000000..ad926b40a --- /dev/null +++ b/src/component/cyfs-group/src/consensus/proposal/proposal.rs @@ -0,0 +1,19 @@ +// as Tx in blockchain + +use cyfs_base::ObjectId; +use cyfs_core::GroupProposal; + +pub trait AsProposal { + fn id(&self) -> ObjectId; + fn caller(&self) -> &ObjectId; +} + +impl AsProposal for GroupProposal { + fn id(&self) -> ObjectId { + todo!() + } + + fn caller(&self) -> &ObjectId { + todo!() + } +} diff --git a/src/component/cyfs-group/src/consensus/timer.rs b/src/component/cyfs-group/src/consensus/timer.rs new file mode 100644 index 000000000..226578d13 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/timer.rs @@ -0,0 +1,39 @@ +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::time::Duration; + +pub struct Timer { + sleep: Pin>>, +} + +impl Timer { + pub fn new(duration: u64) -> Self { + let sleep = Box::pin(async { + async_std::future::timeout( + Duration::from_millis(duration), + std::future::pending::<()>(), + ) + .await; + }); + Self { sleep } + } + + pub fn reset(&mut self, duration: u64) { + self.sleep = Box::pin(async { + async_std::future::timeout( + Duration::from_millis(duration), + std::future::pending::<()>(), + ) + .await; + }); + } +} + +impl Future for Timer { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + self.sleep.as_mut().poll(cx) + } +} diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs new file mode 100644 index 000000000..80692ddd0 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -0,0 +1,39 @@ +use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct Committee {} + +impl Committee { + pub fn spawn() {} + + pub async fn get_group(&self, group_chunk_id: &ObjectId) -> BuckyResult { + unimplemented!() + } + + pub async fn quorum_threshold( + &self, + voters: &[ObjectId], + block_id: &ObjectId, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn timeout_threshold( + &self, + voters: &[ObjectId], + high_qc_block_id: &ObjectId, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn get_leader(&self, group_chunk_id: &ObjectId) -> BuckyResult { + unimplemented!() + } + + pub async fn verify_block(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + unimplemented!() + /* * + * 验证block下的签名是否符合对上一个block归属group的确认 + */ + } +} diff --git a/src/component/cyfs-group/src/consensus/vote/mod.rs b/src/component/cyfs-group/src/consensus/vote/mod.rs new file mode 100644 index 000000000..f2cf86596 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/vote/mod.rs @@ -0,0 +1,7 @@ +mod committee; +mod vote; +mod vote_mgr; + +pub use committee::*; +pub use vote::*; +pub use vote_mgr::*; diff --git a/src/component/cyfs-group/src/consensus/vote/vote.rs b/src/component/cyfs-group/src/consensus/vote/vote.rs new file mode 100644 index 000000000..3c947db26 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/vote/vote.rs @@ -0,0 +1,17 @@ +use cyfs_base::{BuckyResult, ObjectId, Signature}; +use cyfs_core::GroupConsensusBlock; + +use super::committee::Committee; + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + voter: ObjectId, /*stack*/ + ) -> BuckyResult { + unimplemented!() + } + + pub async fn verify(&self, committee: &Committee /*stack*/) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs new file mode 100644 index 000000000..0ec48f102 --- /dev/null +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -0,0 +1,147 @@ +use std::collections::{HashMap, HashSet}; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout, HotstuffTimeoutSign}; + +use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; + +pub struct VoteMgr { + committee: Committee, + votes: HashMap>>, + timeouts: HashMap>, +} + +impl VoteMgr { + pub fn new(committee: Committee) -> Self { + Self { + committee, + votes: HashMap::new(), + timeouts: HashMap::new(), + } + } + + pub fn add_vote(&mut self, vote: HotstuffBlockQCVote) -> BuckyResult> { + // TODO [issue #7]: A bad node may make us run out of memory by sending many votes + // with different round numbers or different digests. + + // Add the new vote to our aggregator and see if we have a QC. + self.votes + .entry(vote.round) + .or_insert_with(HashMap::new) + .entry(vote.block_id) + .or_insert_with(|| Box::new(QCMaker::new())) + .append(vote, &self.committee) + } + + pub fn add_timeout(&mut self, timeout: HotstuffTimeoutVote) -> BuckyResult> { + // TODO: A bad node may make us run out of memory by sending many timeouts + // with different round numbers. + + // Add the new timeout to our aggregator and see if we have a TC. + self.timeouts + .entry(timeout.round) + .or_insert_with(|| Box::new(TCMaker::new())) + .append(timeout, &self.committee) + } + + pub fn cleanup(&mut self, round: &Round) { + self.votes.retain(|k, _| k >= round); + self.timeouts.retain(|k, _| k >= round); + } +} + +struct QCMaker { + votes: Vec<(ObjectId, Signature)>, + used: HashSet, + thresholded: bool, +} + +impl QCMaker { + pub fn new() -> Self { + Self { + votes: Vec::new(), + used: HashSet::new(), + thresholded: false, + } + } + + /// Try to append a signature to a (partial) quorum. + pub fn append( + &mut self, + vote: HotstuffBlockQCVote, + committee: &Committee, + ) -> BuckyResult> { + let author = vote.voter; + + if !self.used.insert(author) { + return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, "has voted")); + } + + self.votes.push((author, vote.signature)); + if !self.thresholded + && committee + .quorum_threshold(self.votes.iter().map(|v| v.0).collect(), &vote.block_id)? + { + self.thresholded = true; + return Ok(Some(HotstuffBlockQC { + block_id: vote.block_id, + round: vote.round, + votes: self.votes.clone(), + dummy_round: todo!(), + })); + } + Ok(None) + } +} + +struct TCMaker { + votes: Vec<(ObjectId, Signature, u64)>, + used: HashSet, + thresholded: bool, +} + +impl TCMaker { + pub fn new() -> Self { + Self { + votes: Vec::new(), + used: HashSet::new(), + thresholded: false, + } + } + + /// Try to append a signature to a (partial) quorum. + pub fn append( + &mut self, + timeout: HotstuffTimeoutVote, + committee: &Committee, + ) -> BuckyResult> { + let author = timeout.voter; + + // Ensure it is the first time this authority votes. + if !self.used.insert(author) { + return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, "has voted")); + } + + // Add the timeout to the accumulator. + self.votes + .push((author, timeout.signature, timeout.high_qc.round)); + + if !self.thresholded + && committee.timeout_threshold( + self.votes.iter().map(|v| v.0).collect(), + &timeout.high_qc.block_id, + )? + { + self.thresholded = true; + return Ok(Some(HotstuffTimeout { + round: timeout.round, + votes: self.votes.iter().map(|v| HotstuffTimeoutSign { + voter: v.0, + high_qc_round: v.2, + signature: v.1, + }), + })); + } + Ok(None) + } +} diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs new file mode 100644 index 000000000..2a64bf053 --- /dev/null +++ b/src/component/cyfs-group/src/constant.rs @@ -0,0 +1,15 @@ +use std::time::Duration; + +pub const GROUP_METHOD_UPDATE: &str = ".update"; +pub const GROUP_METHOD_DECIDE: &str = ".decide"; +pub enum GroupUpdateDecide { + Accept = 1, + Reject = 2, + JoinAdmin = 3, + JoinMember = 4, +} + +// Some config +pub const ASYNC_TIMEOUT: Duration = Duration::from_millis(500); +pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); +pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs new file mode 100644 index 000000000..9949f7a67 --- /dev/null +++ b/src/component/cyfs-group/src/crypto/crypto.rs @@ -0,0 +1,14 @@ +use cyfs_base::{HashValue, ObjectId, Signature}; + +#[derive(Clone)] +pub struct Crypto {} + +impl Crypto { + pub fn sign(&self, hash: &HashValue) -> Signature { + unimplemented!() + } + + pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs new file mode 100644 index 000000000..066e79b6b --- /dev/null +++ b/src/component/cyfs-group/src/crypto/mod.rs @@ -0,0 +1,3 @@ +mod crypto; + +pub use crypto::*; diff --git a/src/component/cyfs-group/src/dataflow.vsdx b/src/component/cyfs-group/src/dataflow.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..665a8e4fb73a882cc5c6b38cf015e1a74d84d0c9 GIT binary patch literal 26647 zcmeFZW0x+^w&q>7ZLP9x+qP}nwr$(CZPzN>SY^9<{m*%NkMoSZ`xA8EFYb|bvChe)>HPdH*wOT zb+@r5Cs=bMln!AU%S}OUgTZLYs2$~PI7TO~)wHJ`; zVVL#9`$udNzmzbc!U(Ct!IoF8*#V|pTcz~MUNgwoPsPLhM;gSY*5qu^EnFR| z1<6#_3Pxqs-Pe-lZ@8i#fpDs^3SVHXZSd433BZZyj@wxj(=w}w&BDRkl))IYQy)Y5 z<0Z)?$T8NnXlaIumkC+Kd9Rb`Cv|ObT!1kiPGzD>r6|$8z+fSoS)>NAuYgi=;xHi* zf>vGsv#Ap*{OEVK-qv%7x~vF3&weMNEUz$#uw2$erz`FejAye)k?7jE_CBz|1M6FM zg*dM|G~sm;6#Nz=LF<7t5sAqHEf3zVmuYRc=8g1RD@LJf>yb#R zQ>ZFuiH+8M+q=hIzXowVl&4w4kyo_0j*ec9ZUeYvoMD-dvBbz|qMPuyLO3}WGXm4; zLTT10C~$IY0V>`Rcr$sbhcDfr9;|K*^SWpXxAkvWv!@-hQ>W$-0U%Hi!A^f@d?XEm z98&|9V6=*($%!=O*sxe?1t$jB=5A^PmmrU}{13?Fye=3SrZJ`ITMU|@sM-Q)&R?yZ zB-yRHM~5|0%rE-$i*;XWe;Rx(QQeqUkUP3c7m)ILXGjmw9m9{N`POkfWeK-+ks#fI zRSP&_L3i*YhR@WL^Zp9;@2)CATyNDw`Rk}a005-Fceq+OS=iAT+Znmo{LPX7B*#k~ zEvHTPM&I4a2Yh8N_>CH+2A2kEugTd|lJ!_OZ>_10>D~n-V+WxG%}B?Cx2G~}f^e{f z{PGNr3HMcrW$EGXd2;~R{Dm{pxbJ5dM3!9PPN<~U_VpbL7Hpzi;w5@tZrj?X^{gP% zLp!^lQ#mnwLI3E)2~WaRH?^b=b&#qY5q60r6~-x7(g{PhjG4iR zHJ`!2t{l~_rY?xV_KL~xbk35blJI~VY6*0K)(wfpvFwmq)b!?OHzh<+O!2PFu&I=z z=R-?O>0t+_jK~!6JmH6{1X@Nk4KNuEmg}Trn_CD1^F8tDK$qn0sJeA_uh>0_;tMpR>G7-SuBSc|%`9_tX#_|2tJ2p^o?U|(uLDDOJ@y|BFu43KKfu49b<3jS?1I=e z2Ds0dH+n?t783kkuykJeqQ^B*xCJ9@#ay3jQ-OsOlMK1h`xCy+wWE)Or$BpTv5?lR zwW~w_sH9Rm0x{$KxNIFE*5eIyV?~l%YU8t|WFCHkfR1MT0G^iK z5y9B~Wu$GB;LVg(Bm6vJ;{|!=gnB>-_0xmq*i`NxLnc71&uS(?sjxzhvJ6|;LZqdm z8b9`M6s0v*l5V0V07ZGecx?~$7G5v+As$2=R5B#?MX*R643;Cj|BI={e#I+UG7ETM zh+XQwqJD|X`pNU^S)gnC!uf@3MOjFPUjVvOpqQmf+mD1w`X*LzD;!lS!x{TO0V*upaF$xQiIt`!lrO_MwE=SWm93 zKuq{jjt|w8J3Wef^MP5z%QASz>HZE^&l<+(;1AtapZ&|8RBp+HpsFUxG7rX-;MEN` zIwX6}3_paa$wttFV@)SfheC{iuxR6C?*U_J&lYPCL zKzFEAO0gKbC3?}S>|bzA<%Q+hTS38yuV0Q(o~LDpE3uJBE0C-Y83;>Z`uFQ3g@|)> zYxqHD4>pvhL?I7IOA_=R*Gso|3TGot4y0E&zoT7H<}+ZEDriwWQ_;bnwYbwK(ByZ} zs}RlquxpfM$FEM9yb|9l0W+!RTj?8r6V(d8k2l|O22{jPuN4GCk{(#(Ysp_YNu7)@+c(&o zSyzsMgqfC*xxqR^&fhv`i*`jvQlOZzJ{k9$75%W0Qq{T%fP5|R(^VPsoek| zdv*Lx07Gf#W`jTgJHDf=*&+qHqv5=#Fve`zj+@Om<#&t+)xttk^6*=D(n&-Xx+7Zf`9i)b^~0guIeY#$M;`Ns|Q=PE!$-(6Pw(~ zXStzlwj};mi_$5QL#WNL3qFj@kNxQcJDdvixSTtdo?*g6jgq~Iy&7I~JM!J=Gi7k~y% zo#M53RXL7LKFJ49Kte4_8q^Q8yi$;m(kg)zGy|*|y%+;YUK>^2NojGQcd8%KK;4}X zRhoYav^}RVaz*!G64tC23!&(ryz)5E@L>V`bqf3FXPf_kG-x2|X*ED|Xo;NOpaHN$ zdS!Z)UC#&EFdT%cy}=NAnv-5&hn#upAd3ya2NxPU*iMAS=_kmOHkNO=T;i!5&s|8E zgKh~!2wtYNhRt&{N0c=^ws+)oj4PGtMj?Nc1gdRPF{)|iCNdH-){EY33pyYgNVRcz za>Zj)O~IKBZf{pbylJ7;S`IXUI|HO3>L?n+03hV<-C;>p5!`>NTze#mV#}NYaGv@s zu5d}KxF|YfHQTymk64k`+NawJdJs@hr4WHO#4Q1Nq)SUhUA?S}dxkqta}f45p`#`>kTK z$1S2N)+gT_s|iYb;PHxJdX_qw2E^xN&2SOt1FPty-LPj4yAv7F0b8Z;_yroO!4tf9 z?7l;;f6lnRi&TMponr3-$YFovh!MI~HSxwy&L?@yAH94Mbca)aU1I+N!+Y8$<~D(j z`LjfHhu6L_&g-8Af_W-rNgDc#6~`^QcV{y^I8|hTdrU2gK+(6&LGKftP&9 zX27dmN$S@c>OCRxryarX*s|#TO8~D0Zk?_Y(Fv?AO;92YzFD1llHksQyMEpE3Al&L zDzYm2@Ti?uYr^P*@Zr@vV%RhdSn&lhyXx9QTW?o`X~J0wHHdIL#!Lt3$h&l~sSYtF z{TV)JrP+4?sNC!AS-?QVq!+ulPZ_VVd)v4)V1^)a)Y|z87#8#*w`w@AwBo*T zDRGHLPJ{Z`y~=Hx!rY-fNu=!!)Q}rjp@&BfTl4$_MOnRN#`-C7Wd`DxfuTt(*m(=r z%X+4$Lj=AC7R(}=Y2nuQ$pCldw1fPH0^E3o1w2o<<_(j<3Gy2|%9C2{QDfyCWaTum z=>Ug-!_D>x2KgCumD2$IHErNAiIrbLdJSCDbku5}jJSo-#?)t!c}f6BDv@d1wE~oI1ec7UXnH-PDMM^x}aABDBOG6*tO4{Y1Ur)v~d8iHT z1ArwfQ+VUsv>-K8rii>#Cg7TB3kwzXW-3MHS%}A#2m(_Vl9F|i{jh=mV*CEIEtu4d zogi&ijmk5@<*`U2Xs)4m>7I*XX|HC$`yl!%Navf@#gpahLd_Mt$*abpur*o7PzO~R z-nE+694~c>^w5vK)(zjhZNmuwOK5q8VZgUu4KmM|v^*ef?Fo6T0-AA|)Baj8&0c<& zEQ%P5pFO4B0DcKwh^lfE_+8sTmjYg;-|TMQR?PR}JC%-?OkQC{qYMp6ocBaFn|Bly zXGfrUMe`miKg*mYw~$n-tM zSbkq197pF5!u|BZEvWs%G(_%=NYH-f`FOD~{k1cguP>Pf1KsJ_@eEwjX&UHa^bIr( z+(W~pF)1w;usc1e+G9YHa~V zzMj%ZP9xF=I4PtINUxEM7Cu$@D4`^4_P8&}VZ)1oQSRzm0)KY2&A<{gm$}H7{B-F%$Ns!bc zA%8?_trzt_&M&xli-)*&-LTQUtUpi^I5P8k~U~Po1;z8$bA&<&qp!y9&I%-lR zyvQW#Er$)Qyajp>q@oRZ4=SG2cBV;v{Ni)VlF(|ckhBqcK6PU0jP(H2X(Ppv7S=0z z-br~d!irLJn`liwArfap-bff;yWE~~d7*n%EB7LoTMMNA?rHgqSLt$(b<4zF=gq6Tb7(wh? zp7b=e=Fs@;_*@4MPKLn+-L6Y_G!i*et4l$q)vn7x7UbS#s5MQOMAbF2XbZJ`1E*9f zzOlVVu2lN%sbPGZDkuHXAOdl!QCmrv5~%LijvN)Dn$mBFk+YmbbuwD z7~M_*3T}k6uHBSEyS0tNga{l;NC~d{M+ZxN;6%;V|LH*3B_4-Ui3Tsv>Q?An@(zjn zpWp0>L<*PPfQfoxKt6*9S)y*hp9e{@GPo>NaYk%61MuRuhZr@DNZEZf_w`ISh z=r$yUOm$NB;k0)!DsM*|e>Uq@s*Ql&0Q353d7WePhF8GBe`y*~JQQ?Pn9-cX=Ul6uIND7u@jnO+8d!^`)J1(m9FlVqhc z*Nc%1biUH7+_72%O?aTv&5o+spSB``&t=`mu^5}7-b|5RI=;In+VAF%P7(-~ev(Kw zq6qL8_;Rou1=Fg^9X<^)%8=gH^isWM<`G*uy$J#6L8UbA40t{J)0M{X=YG9@$IhCL z-|A7P92^)ql~ho+%gU}`J|@9*62#gLZBLdLZrR%f&Xpg|pXQ;vG$QAZSV?D1>CtpW z-C)T*4z>M|{ex})9Y@Yc*Rjt0ZF%?$`icLABW(8k||9@xyu*v_T|IG<9 zQG@(2p*MryVT3O>8&FZBdPC>kf;hkR_Id_Tf?o% z?nA56$;XdSn%G1P@fa|@SbrI4t?H%YW6sm0U(lP6hZ(?LxXT#&8hV*I9l2Ac#Ng4% z!XcO|(G`%hK$#e%b1N>`&;60K1pKzM-Zik+!_0ES$m07&tGm4YALWP}%D8O*+XDSp z4uXHlVQ*k&^1sFSuj7A7p*=STHAoKwcH6bbmAs|H22a%J%4VRp08XxR8Tki4lj!|< zH0uFF&{wb5*F8jpyCGgqL149+fPRDd?F?nB_H-K&LJN1Xobs?oqm^g;-pXG$!!R2q+2Mj;dp9HL z=W@?RBKf+dfnvPu6e!yD3hS6Vj5__Gp7K>zXNWG~caOHpJpO;|b#+|44A9>m2mf7= z#r;>W|9kNNCz<}Q(JxLMu>8yXg>OQ>gVwxgxM)g}$2*ewYe~KU2Uk_qOqEvs)(yscN^=?D~8dKZ8_ls@}hC z-(rJiKNT))!~=D_73WWJbW5a5#mbZf0C{$sQF3OvM`gimcwNFA6;kIIbv^lc?ohHs z1-6*u2wKPbkN9?GGsPn|v@skV?Kl9kRF8iv<5k<8#jgpE!8HXckh{~xKa7vqjQ79M z`j;g*HMzrTZi5}~=5&lW%__tndcb}?!h4qTT54I{#!Sx^%rVhSPA?yN#4Nr3Qtjg! zpV+ME`zz7EI|wr#!4UlK5?M4j008R0#QX0@=3fs>wu+3>COtxrTj|dLTV6el->?K& zSb+S-G=PD9zCFq;=gRL?Z4JoczFsO4z%B`jr6@Dvp6#}e=bu#sMqJ5WD}`XOzD|Txl~`iqBP$~vhDLa+&4FFRD*^ZkGj~_cb9)>!<`E~arE*5bKyUGD2}^O{ zJO?2L2w=q4eY~WuXYRz&keI_g?t5Wcv&{hVD;=2wu8daYAvz4&mF) zY4aV$b8EIgR-?WH);dF>^)$+xHwMGO=$8={$xEKQ+GUOujreWyX=|oh{%}9moITda zSMjG)oyM3dHwHJPFYM@Y)y9@Ra}^?dIF%G*N)x`c`^j{ZxFS__%!B6c0!$>u4ze2t zwomOLr8FAghLdXZSc=oeOL{pk4dfxxPrrwP=k`b9K?JgnrE-NzcgCVYPa)pZs-Opc z_RXJliA$;DtEec^J%9GRJ!0{3&-i1ymyw?s&ZK|i1Ls1P2tNT<8*85vlqT+@F&Dvjc zbt`+YZ59UG?cf!$u)n)`TL|j%``|po#n*GQbg`Y;4QficyMH+{O}tmd^Q%0wC57^X zQ)eNk;V^y}PEG3AXRIUd1Y;@M{f}V>L6Byi;je2-u>k-u|K*(joqPUA*11&Qb;@E# z@ST(X2H$Zvw>Ic!H9l|#Su>j(iNGf7X|)4^o<ig#NF&umAK~R#RWXhf)nkk{Dj=tO>^l@+5?2-mPG-b5B_IRz#r|jF zfm;s`Inl$Z)xPP3=y8!)>a+Wt1Um86_l&_28;DXNB~=p57GtXL#-VeSOQR9P{)6R%gY%014*Gy{Fh{q$NF}kEpnwRD?SyWa|)#Q9j zr~Xf__eA$rOi=j5B6*XVMlN+^YU;d)GN>VuR1&iW^+WDuu`L0KL$3H+wuBU$z6`)) zqC3`30D8Ve5q&sfrWSrz2U{C!AzXsU@}J}BnUH%IobM*Xv-7@4gR@sV^2oviAqxy2 zod88KhRcA`W|}8Hjm9nMv#Olu{!7bk(Oq*2SRJL!{9RmTWhIskPcf!P)(g2U98wxQ zVOszvFg%!{_2>a%AqDBPWzz{C9-fST`%>~+c>vEK`bgIns^?$3E3$Id ze-}7B50C;7$z?>md|~SGR&EQWch_Li zU_EsmQb}A`R?%IttSd3Xx z{*F*1-@0i|G1D4$|8PuJ$c{qjeUU#2bZS{vkqMGbATh7x6zo3v2#NbJTi7o?jglDZ z>;_CtGH;1JYzNOkJKD>@WW}gOUflIZZSkMe0Held}XM2B{r z?NFj`K%is}m^m9=xPD?>F6S61WTDRrq45nua-u&&z~nLzzxgHk4^J0)ZgPR4#a{d# zSUi6RhY1dyH2QCQWzzz||u4qU4_sIl?|DK>XLA>O5YC$t`(*BT&+i zPFu4ink;1Zqe!TN|l8*lz#HLFg69)@~G+j2qIBlNDp?6+(2FUrCSXH6fiPbq(N_sP7xDC)>Y% z!4UEgZ5dUrJuzq*&mlwgNkWuBBD#lK&!;Ioc+ut-M4e?l~@B(cD+)*-N z?Z>Q~7FDQNSA-F;%r#>Ts1%eEn+p-!?z~|Q69%>u6TnoEdn6fx<2d+ zT<;EDRCac|JbF1~WWjo#HQDRRXS{=V!ki5&tq1Hsg}py#avM@q?@XJ}#PSj7Z8n;H z?b&9ce04=aMUk{=s|qda$f^TjscfK|y@1-#dT>q*Z6G*hVE`rDmx^jSqU2?q z^*K*1SfT$8R|P5{9SInib@-Uxt5syHjSk|E_OC`A@G7%$XBIRZ>X;RFcmWZV81ZOJ z;y86X>lHQOe^!w_yvkFl&1t3xpRlK;XLYQ1pDnaulowH$jCv`QL6z4Ht=VV zaqtd_;I{h&m>|5fUPm1)xCY!DnmTTC5BLazY?S7HgzX~yeHI*%WPgY?P&{PSsmB@D zsovY&-vNxSvf{CX^04R>v0QSYv7Wa0441T7^ZggGou^~F&juQd0ksY?UgzPVT7>90 zxF?)T^8uCo>fenKqz1im-ZtS+trBqX{6P2|y=d}cOc568AR7g;&0RLzP5HHpbn|#H zAVdM27>o`INd6$2aHIjPm}tp=&KWjJ@9X-&&9%IwHZSR)ayw-_%X>uU_b^^l)Ffon z^hjKE?Ng5AN3hgmm(P}B*XN&F7w9>^1csEeTbFDwag`eM1loV=$+Yj(B~q68Ow?As z5Vb7zDECuUhTWL`y?8rPJ^UD=CV^)SST!yax93Fp{Y4i|Z3AYeLj(JB@^KDMNDYs& zbth7J1}#HK%WzR9@^|Y7W{Td1pzc*1xpwC=YI|^Ax`;;f-2v;^YygvdQyT(42)w&KdTthIbwkiqLI2~u6Y4Yf3L_Q z$U8u>V_X^c3)YTxJZu9_!G7j9tWp#=3h=&{kZiXDkWpmU0P%gJ@`!Pk5KO}l)*5@^kNX!9SG;d?Vk4pq(2%D_uH8!U+)enRyiwF(U!hFhw1QHgs1m+q1Y@p5 z=@odAD+_g8IaV43)s8q+MCtX?UnlKIDF`jg31qJ$xCwPefmRdV|}P#@zu zsjbRFk?%yfi}5{cJN?jKWexLr-E5%-2L~W;-haR)e_X7W;S2lt79uMDG@b*Hd2y0H zblAHql@}CDN50j<&`Z$oJE^OnM8OGPCsV#b=vFbF;b;+VjPBlUQnc;!;t90-K7XPU zx~$*vdWTp`=UsDi|5Wd$A5v@xL|!axhVQ^z^G?Nk?{G_?d;N z1C>`}98TQ0jem?SCL}8w9V*;!haSsZhc&b2*{HUQjJ0Ux^|fvtHP>M_ma2Q4t>mx5 z@!1=xPB#&aV&*}@Avr+P>?g+Og_@!$Dqp}^+U5Rws6iUj9y*A_1^DeE8B;r^tJwDah5AM(bYL?jLkiXgZ|V-NL(PtfROYta-$Wdn zAw-`D8vI6vz>>mOTnpCZ6X?OYKq8QfeC6Q5yrWaC|Mrrm`eobw0so%@L^svp_rl)- z9Odu)pWt7G_d~Aq^A`cY_}>Ke1TFZeCJtg0$=ZeJO1%J#Dj+Yt zf=?wsUsVZ#%V2gr5fc~OB+Yv|K{jzJ8RQiPsIujgcQU`SW4&@%^Y!vOv^dl|MH=r( z!eo7a+4PjHt70BZn5hazSnF4^`2A|kB3ECbP)eRek5eCX!=^q0VG z1BDB1d#P2isjY87)w^t~-Pz3~j5H5=6XSlF3+U5LU8@%u_rRUd?-X$S95-dg$vj{TKO5V_rS9;e` zNt!Ds#HJv40-1X&Q|ZpF{AN1DU3rbkuI5sBZh6)Sf$lXYV#XF{0piQ19c-IPu5B%a zu5^7R2mviS&X3A$uO!ZPr;&ZMGn=&bR32j_fK2&}qNiK!%~mS$7IR(7+Dh-3Yg9j} zXW%?X)G3(G&+QL2>zV>UedzCEH*qpediDJc-KDmp4wQGmwK`xz7%c?X18%U8sI95P3DCvA3MAp1J~3b6~O=)eZNeC$i~( zG6B>9PgtDE-_D=@#G%FB zBzC%Q>+r1U>M9kqw$Je3c*r94t?A>6ItTCfvE3Y+O1mlR{z+}Q_J_>*q(>C9ZK3;s zH`5-`DZxou;0&rg$xd2cVvbD2HG9bc6}-Az{!M3eA?&0vLNMInc7jlcvtJ*ZtF7tH z+Q-H3xpMvWf=0pF>AV^4`xFjg5;8YM*!TUjp6bFRCB*@kl7})kKa=;C?(BMD6vS6; zM1E&|?xCV{xzX78VB9Q^aX|=Lo#xr9(Z&Z#A7ih6?+i=W7`?r5VVU-r4du}+2luFb zTk)2jmbPe25|kQ?zZs4oQ!!1o%eTp2#HU4(ucy}1f2Rd!1)^p0d<0>U3nGU=;5daU z=CZk2ws4*hWw%HkyA54v{EUb=%CcgDG3f_*7Uw{@Gr6c6gTNF$K1t;y*jHs$rON-J z(US0`&!{*R2{uWlXc^z&0&to!1?)J~!%7Fn87bC^Z4Fhht|jv$E?mcMI^qUuH7KDT z#(NDF`T`;K7vx_4>Ko2CN4dnP68b3?0)=ONimSKY6V=5N)Iqi+d3xYZf@6F-bL{ z6UoaEInksn^O#YD9jk*%r%YtUS9v|obg>BY-Xb>gtS`=5LPgaD`y7l4%WBd{io=t( zi{UFd3lA+UGcM8|_l@ndLt)czlJ@66!abx>w(esX002KYyp)%WH#GI5YKhR0 zGi@)`ocrclJRPmq<)uXp*d*4Ro?H5nQ+u(Ct1dk{_IB>z`%c#73J(p`&G~(wuTLCt za)_&WG)}Gpr#EZfz?*saJ~%UL%9%|#HnyfdSfti2Rc&RKPAPc0u;h^zZE}R;akSct zPEB~TBs=Aq#;l*qGy-*~S+r&!Sy9c@QXz(&KQ1Bt4n*L>Fqtq+95P&OdYkD?es=a@ z${_t1%A(dFTeo5K{=VF{c1)_S`hnlU2{aiR*qmVW=;Py-DSb0`=@CCdzSsXe1_McH z3JW@%;FQzPfrH={M~fQR{Mw)Jc45W&RB)e!?-_RuK?ir;8@{s_7R^a35{!y=xXs^9 zdV8X#3tLyk2+5^M9uJ4%mMqIxg=(f@a~0ZLIUJ}}`xs)Y!bJ07)+52Mci(jFnIHIp z1>cKIVqp8o!~aov70A>G_W{QPjzfPQf>WRH3s90>`hnTWM(wSUxoMh4l&&^2dZ}FB z=w2M!gEJ=1xw0+U>{`84I7Yb0SSQYsHW>03KgPh0;0xq=IjMKP@H3Nx+d+#>DXl-y zB|B%FXrdch916)7JahL`@7{Ev#CIBfampbKe;C>hyafIwTQzWdJ7oz}&yzmcoofn(l7U~pAITI3CboLdO&2MQ zGGee7%1;Pj9UJF>Cgx9> zD{5(|C#`C#iL8%g6<|G1Q*i)!vob02svY2{M3ZJu8;YF_h?sy1PhU(HA=Hw^f9#1< zT3wVME;A>cm?e)%owlzLBlUF6|1j5VEEk-rh9#$)eVfaJYsZUCDsc;`?>Bo->umPe z)}hlWVnd~J$xeuX7S!u@K;%J8ax3$_M->Ge%SerMLEM~tKi;{VzdnfnRpoBml-(1YcTBD2toy~aQiJz zoeA7=4bWN{`mg}TW&39kJj9k4p^j+S0^a5^c8oKhv>dJbUMs;9SM~gS$)KIewj;?{8%q zj2+UAQ5qhMm-poSh<_B&E@9&u!43O+{EKo|S z$xPd)E|>6+ZKh&>&D}j&9>hy|vL6n_!b7}*Y{3NIRO8d}cC){a{V95(d$E-F&;}kp zgijjDBhzq9F_v$U2>*hZ1C~lY5^V}|q|h3_2Dk^hcr09yTzKa~gGDxmyQdy;qQtYH z_Ar{@;=fcKuR&J=5`^CKvI&RfzqkD6=-?KoGg&6-KLH|lE6w)@bbO!D=QeW!Ze*ugAc*kx$wZ0YMzPH0y}bo*Prb*AT)B`IdVZ|55H~(rHFZAD7{rFy z$O}v1YL)#lhuqO9^(+VtrzC+UkUaJmpkA9bVk1dyO?sFhAp*XD0#RtR^^l&1D_o>K z$l%>Rp(GMZ=?V%g1LA~jfGTr$1elGG8kS>*@MBPIxl#!+H*BY2;UMkVq(G_bmt z3-<-kb~&iC#>V0e*W-^8&mrqfQWvj1z~}QRO)cmt(dQ_azxqRJso3U1*K9Zpvgi`? ze*2%M5QR7Yoq$B!N6M&i6!M2s-t99=%F7;AB*COI1%!P}_yd~S5H1|Uy_1$gS=#-( z<`JtBnw&aQ@JePIhIJ4JJQWm$jl$mX`LPppOnKscL*S@#;ji;BURG2epADp^0vgY* z9gWF(gUJF0;BYV-$Pn0Ny)oB7a_9Uw|2&5u&xmN=v*Q5Q&^1WweNWrH2v$#F;2QyT z=u=H$@gvrw>pjc@VBx8*dv zYLR|1Ml>gl4J3{GCLfP#XPk}O(xSGEmwDHZ*-D!EZS`mK1r01VN2>P`xuyPD4B zCTAAbY(t)!I&+B9I2j00leCjsG2Wd3${9UD=>8dKZaxS@GBjF`4CRD+iU5V;X?I`S z`o<4>451?pITgLUq5eUyX5%v+Y_xVdqO>nsh+ttcOF4I998vXL*c-Io7j|D1a9J$@ zV=p-54S7sw|8e#P^axce^G6{m|sx_#C#Yqo2k)=dWzem*3R7- zzRVSL0Tg#DnJGN*eqFOaJ6({1{$Q!|^%$4x0T(-Tv>^RkSm>|>ivd?!fbY+H9@Zi) zqdTUjaElArUNdy+j9+Kx@GH0GLR5H`<#*aEn#%O%s;!X_)n3s0=F6mQ9zw%9+o0G} zE9sW09Q~7?zvQJ^u;5W=7shJBH!fZ2wwi!pxd0Ydmblw3vQ|b#i-N=W`Xr~7&8)U7 zm5@}(XPEoO4C0T62E(<18UPUcv-7(agHpG~BZ^oFcJYj$L2YqD=kqTILVk(URx|iP zj%NDW5Z{-QEg*o@mlBMU#?;AVOrP1c^7_|Z>RTr#7h7PzR<(d0>TajuQgXgiMGAiG zKyBF3p_v@&pNd5lx~u5abETUty}RbTqeGYQUYvodCpTEFfQ|Fu!RF3B!cpq40pt6nEUIhYlWqN$8^dsN)>W_G#) zEdQ34*zO9LwIwZAgnz=-sigob_)0nsm${$NzCz_|Lz8$B@(4}bPJHLskiL8L zaBh4@lvPR9$=?3kb!{0;E!LN?t{`1)h%jVm;qW$mbEQv3DO1Wqy5dDJD~28P@os}> zg$7;WCP|d(tg$<4d0CaPADfTKJmIDVttfqFiBxO;n^1yTt`GKB3dGp>HQ`_Lag z_bcwjrJ;dx=obH(;y0GCf3^p#UIB3L#6x)7nZQalWK}EQVaIx`8f6k!BF9}@&J=7x z=hK|KE#(pkz!I&8HWSRf*2Vdw$JlwEa_nU}%ze(;+Q1t=_p&17jT!)g@22;pLP0*^@g z^OBM)ZSjkW@TJ0;sus$xAbklVSviYxM)4K0OfW>AmwRmS@-I@qA$cVkht?I_Kdfcm z@X?!+Oeq}qhM%~eoHG>W*rzSJC;lI8EM=>%zy4kUEH<4vZ-I>LjkmcvFDozqIrEvf zkXLv!qPaM34@_B&>}1on%75N~Vt#P85~P#Jg;3sWF3Bo8o%~NB`3mM zDB@&@yR~!j`sVwOh@_sTNGb#b0AT#@n~eXbrCX+dc+ru%hSOg};(H_g1Dwg*f8N|p z=OJyTEWv9^trCN=?r}lSY-}Kigp;Uv`T0&O7Z8SmpHV9FM1(j6a_7V`+ zN-RqbZ9@%>Buf0aMgx0e-7TTkr-9MK@pTuLRFPFojMqRjnx5UheHZrW0 z)Grh4@5vywMv2Oe7H-{Ah==^kDNune_u}!zF2%YdomLB#+kC_F5Q9^nS?I&*E>t#mX{J|q*fR_&WwBIlqt* z^FZ&L0FtvSZlHU4Tt0+%X5Y+D8~nf6!A`y`t2wCm(^ar0%;@3RAM1kB#}j_BD!_z6Q>O>{LCZ+wUs`W z3wb|G*JQ8>F1ioG(mi8E{kQ% z?AUp#A{I~Fct1jz#w8%c=0Z<8H|FT(^lV}B{@X&nv1Rf5IuD!tKD&rfb;_;In1Log zGXRIF6Q~g`ii}{m?Gm}OyP@Ilpz~5~UY{q+|8AlFO}$u5SzB(5SH=)iB|BF-jll_A zyZdTurMUd^LALA#Cb|B{qFrL0BLLVe!^Z2U+haPgTwG_48ZmxzfXt8QHFu~4Cr}%? z-#h~mZ`>|4VR0n<=Kel@U&x17&e8u;&OTI zjEy7L%b3#m)|oybbY&?;r}oqb-T@M|4ofc^`E(uRhyco;Li3?lItr+&pkXPjBRf>Ajsx;qB<-#oTLIr!C=0(`OCT|G`rXSnUA`dSC|LIV2uv_UsZlW9?O!TifRi}6B3z8n}+E{RoDDO*p|&2krW?C2}wz_DFURx0-;`k z#8|PZnYEU1rTF^7HH&UypoYUvomTo_I-2|Pd3p5OKp6v0M0`xml5m_3W&o zQQu6d2|@d&sR3GN-K)D4xCW2%+^PfK;Tl5m$5ZS;g{=-U$YoVqSzRJ3N~Uc%8NCZC zG*BeFAFX&8YHggR#-wROe5IYBLIav8!kxf$rGa6#v;q=D(^gH61w{sQ2lx$d8dcSw zi0n}iU!-=IY<2=`+|r}dR#)h(fEN$tJ`nE$H8KZ5_)r>9hiJp*)Llqg=!X?qN2zfR zTKl3#Mo0{qKz!K75>G<`1AP3>XYK`I`XT!(BeVCIfKQklE{HzVqKSC-{>xBp5Yddh z0ltuw3E4S?gJ$Q`PM&8hg5Y&^-pRk&hpUrF$aO_j1}vOG@eDcLY4W%H1C*TUaqN*W zMZA`&gJIwQYVRz&;##@{42?SkcS+-od$0s2xVyVIE(s8VLvVKuZoz^D4^D6o5ZpDm z4)q3 z9L+KpD>AFW>S>6FTp*dw`c^MGZgK^My}te2T}KhdW2k4Q<0i6>R6kV z^qZPCnNsX$w5v_7U$s@%+lxWMLd!8kt+@Bc*n4r-H&&GWyiuK#XLr?Jbh8m>R_HgO zx+wb=dDc&UNKr~TCdNxMJe(3z&tK?G8$fhkP<|~qPQZkdz;)T(yVk74Se~%t*z3&N zoRaR9+1TXT$I&#AAzLjYjJgX4=mI}7*+1W870m`i-(9! zc?UbNBa@T4vyGvxfrT}riH+%QYQG(!C|)a2h-OfI=r=#rtDVUKL>Yrxmt*azJ2?=!x@qt-mZ#F`u@;`1#)q3NMU@?jK=ah zg?BN#fYVYRSCk*+igQ}mZ%=Ako*UXkcMi58pJrPnR^yp0-#w^irH6AHs^HRddcn7e ztH7=xqR_68e|&0u!^&jQ|G-Axo2AF*5}tLz$A)(egyVA{T)qMwkL2H8bft9h9g@&; z#g$jIUR{pxw9gVhHvw+iTe!m)4vkgC-^s&bYbhW(SCeNsJ6S>evsx3|^`01Jo&QvrW{Y!-)G>oRPxP zUUk?SRBOSH0YWK;M!kgbqZm4cW-yEi+5vJe;gQ;fYy=v5ul-Z@i})G_JX7Za%ALca z30PVrJ}Ne8UYP9~_gJX*FC8qlEYbijxWn{)B2*c_g1mFh7}gq0^Wc%BGb+eH%#a|C zDm{=`D%!^L>3CDAFjM<-d5M7`4U3ext<@wK+s>~KUW74sJFl`C8dcn|6cgzBaQ$OH z7y};!{os?(Nz8wvm5RBNdTmrLDYfGU;-a`JTrXGD+mFfEhi{yV$NQnVh~4sw zPy0r$zH1t5mf=JRmhztoF9&w^qMqI!unl1QB)LyCfv;{%WLaEs=)w9yEG0{n) ziuWL2liTwLE^CjIbEn9n%xL;T`bN*RYDu9tl>z*VNi%QDg=mQkg=@- zcY0FowE50#5-f7_xxSHve>i9JH6rO);*IH+(rEQpsw{j4dF4O!R;Yw;la(dl4qPqB z=M;c{aE^Bt5Qy3}^9iHFAd+pw3$33;+~w=c-B&BCi{%A_y6~6u&^SJ@`B-+j{_Mo; znPP1gKbF|Zys>*wTRss=j~Xik*B4DGm%fpi;c%XK&0MUdZ}fxRcVUU?99X+-Cju8j z7aC0~nnYtnUX1giXk6`UNol`O0Bp3M==_bT+=~Oyw;JsgvymD3;OmK4xXiaIj^K&c z)v>$vdRFebNa}TEdJ_fOIXvslV10r?-X&Ah*_D$|s3s>FHzI}5D6xTG`ov)NL=N-x zYMw22YAlW?TB?5VK6V~{DvhpAKiHI1TCUo~f-1DDd<`9^juaio4~FU;MZ1t47{JjpTripBEI zD~G4G$U2BKz|>}PL3XmD->TMc^IL9}n)~{&n1+F_Vn}fC20>xw&K9*%1XfbaTTt&MjfW-iMeD=pP06|ei#~#T3i&z?XJLL z;dqXj&dyacK8VSU2-)K@V&AZPsKF*a7F})G935#*C_NmOp<_G(24q&D6w~bEIf{{g zE#N4JoadK_+`Vqbva`YGeNX0t4zpOuFMGYZ61S#Ev{L~=ElQOz;O2Qr)CueqpJ_Z_ zW>e{$uC^v7dJ9m{QY-9$Vb6Xpu8m%9*8-j{t$0Cg1SzQwH}ElLr|O-1am^H7?i}Vf z@^BWhB$vdlb|_c!JhmM!F~(bEcjPp|9*qIMCW+4X2_=LJG=PjAox`|KI>qHULz?~ zs)!8dFloHAYu=SPa`t*&a!LXU*)8Y7tXN0fJ47cJ^VZh zEb7Gx^4Wk}o@#tQtSrqWJdWm&)eLp_?&Qv}RV+EUgPPZZgKBJxy$+yHvzC_}ZFz}qg*B)C8v#CgRdz<~5{y9%h7 zb^@;+D*Ekim^rYOKn3XA>ebKoLGp#EI@JrAaKKB0CWmBIcSkE5m zVYz(yYuWr&h{ws?#Kz=d<$U=5<=Z2gahU5l;#awZ!&)#{5>Sr+41Qhd97n^m){TJ> zt?mN>^{%p}@HR+UfI65?R*w}gBLPLagw|)iNb~rY*n(NbMUPbxxRsduSe$d{` zzB8R_y~lF{D6dSx9V)E)j{kMtK?vnGU#+ZX_5(p4#SZlc!wia3s1NnapX|N+aKn`b zmR|ifaIAx4n2dEsn^7M*dn^hrq?}b%@%Z@=iYa)W-REgmu3M&4!B`eZG~jSYGZ4lb z2gvGgWf5&PTsL0q?+H6gfOrH@2r#`1U^$y5xK#^@vtG1JFpG9a2_+Mfu4{ z0C&PATm!11&lSdI&yMyiAfPAK>H42}ZQka4p1{Jm;DnFbby(EO_q*&8WjGU~cc)=hIAXY7k}SE=rN2Xhp1l!#5a8omSg5(XLRM zwWAq;c`2Ykh9q7SfLcNyzloEMI)PP1Mf?ax#{RgY(`UF; zFgcu4(E0T*J;jgw;lSesS>m24+3f}NC^Wm7!(ZrLuOJ-oh>B{PdCMwf4H<1}L};q< z#p0#^q)F?aatvY3DND{;_xP5>7lx~sE{~<>lbh|+7jHa$^?7d_(S*n)-(A&)E(LdU zswoHp0xB=kiY?1SyGw~ZK=He{g@YQ9o4XAZX z{mpgD{b_`UHR)jhET3I5?b0pZH&beRVJNoE+qgGv$OH&#-R>N6T{rmQ7C%;0l0n?y z{hFN-Fe4TjE!;lvr0la#BagkD1-Bp*6~Z&d=ae&XRk9MI zhVK|2+J>!?=bpyRy>I0OykKP{d~Oe0b;{ufj1?A574tS>_m%XF5rClZM5_4e=2(qf zhrfwR>#lt=(h`tSY9XmDj=0h+(fU zahh)Ga7F%_XL`OwT^~Kk#U{2z=sCAXi;rLF6^?OFn!#r&Tl*h zBCBhQ=8QS@uv5vqmne-|a=M*D4Br#Ab76+yN}drU6e=GRBuI*Rh4q))CzVy`t~hA@ za1q_OTVW**$(kgw26`kjY1N_-u7)2-HITYRTdDg1J3=NS08^^i2OA3##<*y8ePvTf zB6Xo*p@A0Bc{$rGVT4h!kw(-QPRsTKvV1i>@OF62d9Mx@>`2(?(UZgy^LmdZ2K2{d zu|k@zq!b6m9jpC5A}zEF2Ub;PS*s%UH~C>gj_Mq=yL3bM^YBIER@@YB=Ri&OZn?Da zf-5t4=&c4ggjBl0etMNP*FZ%RsoXBATrj6kKcYNt-uoMNWFa1^ml$x3eN^et-)#F> z9!%Xd3A9)Q3@cx;pFp+)O2C`3x2|N9{Pdf3^M&8$N$#w9$uO;86@jhp!|K+OV%cva zVc=Xmm$*vpe2t=RW38F;NgziTCKTiOv}%h!(34AsZPsE;`r<9{MSx{cJDv}3oVS1A z*JslC1Ew5VLz?h7qnzJ5Ha#?ARo?Zv+mNlQ7|mM*VC?&|hVM1^G%cFm%|+$WPJX6E z>W&~WfMq!rdtFKzGktvAupJ|YeCwUS4wjk3UfIH;VBbqsM#GVv_lwj+^1qHp_9oZo zlW8tmHe}Cui?ctfVjo6kYtCu>LLm`IX$>d}C`+nSAPPoTSW2Trq)BTd_O(|z`FVyJ zg&`L(x<R z<%DJLo7S!8&Icgq=+r38$>{8HxO4zH^F{)MJkW6#Ui9-Y@XC*5Z}Vl0XNJ`1OmEYr z-Qtvm2NXl;my2T;5+>g{)2>#JkP3}hep-LEu&HewtZYOXV?$nXYW$&<`71*&mc@>4 ze0BV*3V+#}PIC28iBGrE+*y5GRibk-b7M%5nORy!PL$lVi*S?#uzN+e<|m~%4S9Qt zNJz1tN0r%$afrl#h2S^{)#PyU8839nGR%uCg3XYzrMhgwk?Tvg_h3 zdf`7*X4meoFcvVEon_?fBCO{C#T0Ek2hc@9+3yvza(UzYRc`S7ooX`#veE5o|`#H zNM3w#Q|wH)InNch-sO>TVcCr+FsP`(t^7EZ#O+mILw%PzYIT!S#%li4?8aOe+;tj4 zf>()k1xq9gN41MXQ$}?u25b!3<4K z(xSXGjr)7_9n0O1<=$JM<&f!E5(RW6EEbSpj8x$*R-J zf%D=T#?e#@d)K~9h@a7!_LtdZ`grczu@bz1A`tk{60QCRTdPQ^TET#_v)K&~;R2hb ziW$Bs=W8(E+pVdvKr>6e>V_jtrE|3I4huUjlJvr(;q9)Na=y0VfQRfEuM)MF^4_MR zy+v^YKScF{b|N-Bg#6kYi~zVZ#=H^msG7u>t2;7`n2m@>^nMjPH@rv+bH>5o=vf4e zbXszuVoZw5v&8<+G9kCNOIMs_G1rB-V4d!R?QeQZ2r2$`TPQQjU5yKFNELTBjXkya zxBOmS=k!F(Fo*TSbfvF@yo}X-^keEm7r5iN?gQVs-oyOcS*?288@_{w$UMOZUlTe6 zJmmkJZ5e>Ue;w666rzQs$%J@l@qhc1s;py|!i?paQGNf;O^!?oTP7;YGPp=qbKE>@ zgd{SL*O7d(Rjf8J`Swaj7|NiSv!)5$;>5jiLEv($tfm_}3s3pnn+44ijZ&>X(qvUI z&$TL|*$mV}L`TVTEN6bRb8*XCJ680{28JMlEI0Tjr)Ka4JhGr6im9xPWSY5r3*V#IiUA|5K6|E*kfmC6%g?v?OZL@Uzw!j0rP)gLg`mm$hl6XIpAG$OXH3 z7IbZG(V<5{ZeVy&opmLDAR;COF0MSjahtmSIsCT^Vt514X3PEc(VeJE>v}k)*)7Sx^h1Z5-O|J(+IFIywJ5Y=#vG&(7=SAyf809U5Z3 zw0?;m67+rY;*jj**0_!*%3O1#Ch%2R!OGmt;N^z+1zzX{nm?kjrJD|&7bM=Ebx6I zI@5r`NIHc1cb#JBVKyy0=QiB$&?AnFw}ekU{Ben4UG-1JM(kyIiR!% zk}jDvb;N8hc4`;b{rNeIifHn9c212Q_l>cuje6!NY27>q^X^3 z{SI#5$w^(wIh{*q6pCk4GRQ_v35|b>XW;4LSLH(5O^d=eS$$z4YLzX+)P-(DXh3+* z=I6_ZSaI*c?l4owxk4m+bfU1#^f220X`@~3t#&C7Hp=l}qZt3NQ9B2d|F_Ub3;m$j zW;@4>`~_`V5U+u^GR>LRuM?&rD<7L?7>m$l3^+MqDD}Q`;B+w}-iWJ>Q=cp9;3(?t z^4WTgRh1rkw!KStpGq5RMW2OH3h|rS#kDC=C{1a6X;p<0l!%K`i}z<0T^igUkf)d3kgn?OZ8g8h##dSKmDut?qEXlg`y#oN9!h3oF^lhxHlxQ>O+>$mPZP@icDDa3?P)=pM_T1WeVSkT{nG0{%F{gU z>eKQpkEjEZ->6@T{r&ydt>`J@X`PBk1TDpH#P8AiW1OC1o~GeGVxnmO9rJfm?o-Uu zWW7gBCBtvb(~O&0LKW*}tMt=vGJ=NrCbjKqmQ{*@1k64eV;!mCFkK$nQ|IM}jl=0NF@W{x2aMAzj z$x}bWQ^r3xK92+l2x-kf^!V>>&{OGuJ`w&YZLjl(^yBm4Q@}r$>pub5`hNocd-0Z+ Xf_Zq^&tFfUm=FXH8@Ua`zkdA}3pve- literal 0 HcmV?d00001 diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs new file mode 100644 index 000000000..5f5cd1a5b --- /dev/null +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -0,0 +1,45 @@ +use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_lib::NONObjectInfo; + +#[async_trait::async_trait] +pub trait DelegateFactory { + async fn create_rpath_delegate( + &self, + group: &Group, + dec_id: &ObjectId, + rpath: &str, + with_proposal: Option<&GroupProposal>, + ) -> BuckyResult>; +} + +pub struct ExecuteResult { + pub result_state_id: ObjectId, // pack block + pub receipt: Option, // to client + pub context: Vec, // timestamp etc. +} + +#[async_trait::async_trait] +pub trait RPathDelegate: Sync + Send { + async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; + + async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + ) -> BuckyResult; + + async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + execute_result: &ExecuteResult, + ) -> BuckyResult; + + async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: ObjectId, + execute_result: &ExecuteResult, + ); +} diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs new file mode 100644 index 000000000..a1f964e95 --- /dev/null +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -0,0 +1,11 @@ +// dec framework + +mod delegate_factory; +mod rpath_client; +mod rpath_control; +mod rpath_mgr; + +pub use delegate_factory::*; +pub use rpath_client::*; +pub use rpath_control::*; +pub use rpath_mgr::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs new file mode 100644 index 000000000..768909145 --- /dev/null +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -0,0 +1,32 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath, GroupRPathStatus}; +use cyfs_lib::NONObjectInfo; + +pub struct RPathClient {} + +impl RPathClient { + pub fn new() -> Self { + Self {} + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } + + pub async fn get_field(&self, sub_path: &str) -> BuckyResult { + unimplemented!() + } + + pub async fn get_block(&self, height: Option) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs new file mode 100644 index 000000000..a4a323cb4 --- /dev/null +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -0,0 +1,33 @@ +use std::sync::Arc; + +use async_std::sync::Mutex; +use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc, ObjectId}; +use cyfs_chunk_lib::ChunkMeta; +use cyfs_core::{GroupProposal, GroupRPath, GroupRPathStatus}; +use cyfs_lib::NONObjectInfo; + +struct RPathControlRaw { + network: crate::network::Sender, +} + +impl RPathControlRaw { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub fn select_branch(&self, block_id: ObjectId, source: ObjectId) -> BuckyResult<()> { + unimplemented!() + } + + async fn on_post_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + unimplemented!() + } + + async fn on_get_field(&self, sub_path: &str) -> BuckyResult { + unimplemented!() + } +} + +pub struct RPathControl { + raw: Arc, +} diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs new file mode 100644 index 000000000..d70d0843f --- /dev/null +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -0,0 +1,62 @@ +use std::collections::HashMap; + +use cyfs_base::{BuckyResult, GroupId, ObjectId}; +use cyfs_core::{DecAppId, GroupRPath}; + +use crate::{DelegateFactory, IsCreateRPath, RPathClient, RPathControl}; + +type ByRPath = HashMap; +type ByDec = HashMap; +type ByGroup = HashMap; + +pub struct RPathControlMgr { + dec_id: DecAppId, + by_group: ByGroup, +} + +impl RPathControlMgr { + pub fn new(dec_id: DecAppId) -> Self { + Self { + by_group: ByGroup::default(), + dec_id, + } + } + + pub async fn start(&self) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn close(&self) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn find_rpath_control( + &self, + group_id: &GroupId, + rpath: &str, + is_auto_create: IsCreateRPath, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &GroupId, rpath: &str) -> BuckyResult { + unimplemented!() + } + + // return Vec + pub async fn enum_group(&self) -> BuckyResult> { + unimplemented!() + } + + // return + pub async fn enum_rpath_control( + &self, + group_id: &ObjectId, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs new file mode 100644 index 000000000..0b4cfc980 --- /dev/null +++ b/src/component/cyfs-group/src/lib.rs @@ -0,0 +1,21 @@ +mod consensus; +mod constant; +mod crypto; +mod dec; +mod manager; +mod network; +mod objects; +mod statepath; +mod storage; +mod utils; + +pub use consensus::*; +pub use constant::*; +pub(crate) use crypto::*; +pub use dec::*; +pub use manager::*; +pub(crate) use network::*; +pub use objects::*; +pub use statepath::*; +pub(crate) use storage::*; +pub use utils::*; diff --git a/src/component/cyfs-group/src/manager/group_manager.rs b/src/component/cyfs-group/src/manager/group_manager.rs new file mode 100644 index 000000000..307a26d11 --- /dev/null +++ b/src/component/cyfs-group/src/manager/group_manager.rs @@ -0,0 +1,52 @@ +use cyfs_base::{BuckyResult, GroupId}; +use cyfs_core::DecAppId; + +use crate::GroupDecControl; + +pub struct GroupManager {} + +impl GroupManager { + pub fn get_group_dec_control( + &self, + group_id: GroupId, + dec_id: DecAppId, + r_path: &str, + ) -> BuckyResult { + unimplemented!() + } +} + +// pub struct GroupMemberState { +// None, +// Joined, +// Crave(CraveObject), +// Invite(InviteObject), +// Reject(RejectCraveObject | RejectInviteObject), +// Removed(RemoveMemberObject) +// } + +// pub struct GroupControl { +// pub fn member_state(member_id: ObjectId) -> BuckyResult { + +// } + +// pub fn invite(target: ObjectId) -> BuckyResult { + +// } + +// pub fn crave() -> BuckyResult { + +// } + +// pub fn remove_member(target: ObjectId) -> BuckyResult { + +// } + +// pub fn add_invite_handle(() -> GroupMemberState) { + +// } + +// pub fn add_crave_handle(() -> GroupMemberState) { + +// } +// } diff --git a/src/component/cyfs-group/src/manager/mod.rs b/src/component/cyfs-group/src/manager/mod.rs new file mode 100644 index 000000000..5d2af2270 --- /dev/null +++ b/src/component/cyfs-group/src/manager/mod.rs @@ -0,0 +1,5 @@ +// the manager for the groups + +mod group_manager; + +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs new file mode 100644 index 000000000..badd0969e --- /dev/null +++ b/src/component/cyfs-group/src/network/listener.rs @@ -0,0 +1,9 @@ +use cyfs_bdt::Stack; + +pub struct Listener {} + +impl Listener { + pub fn new(vport: u16, bdt_stack: Stack) {} + + pub fn listen(&self) {} +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs new file mode 100644 index 000000000..468f26086 --- /dev/null +++ b/src/component/cyfs-group/src/network/mod.rs @@ -0,0 +1,7 @@ +mod listener; +mod non_driver; +mod sender; + +pub use listener::*; +pub use non_driver::*; +pub use sender::*; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs new file mode 100644 index 000000000..029a8734a --- /dev/null +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -0,0 +1,22 @@ +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_lib::NONObjectInfo; + +pub struct NonDriver {} + +impl NonDriver { + pub fn get_object( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + unimplemented!() + } + + pub fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + unimplemented!() + } + + pub fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) -> BuckyResult<()> { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs new file mode 100644 index 000000000..4e47c0e43 --- /dev/null +++ b/src/component/cyfs-group/src/network/sender.rs @@ -0,0 +1,15 @@ +use cyfs_base::ObjectId; +use cyfs_bdt::Stack; +use cyfs_core::GroupRPath; + +use crate::HotstuffMessage; + +pub(crate) struct Sender {} + +impl Sender { + pub fn new(vport: u16, bdt_stack: Stack) {} + + pub async fn post_package(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &ObjectId) {} + + pub async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[&ObjectId]) {} +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group/src/objects/group_decide_proposal.rs new file mode 100644 index 000000000..4b6c7c62b --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_decide_proposal.rs @@ -0,0 +1,104 @@ +use std::mem; + +use cyfs_base::*; +use cyfs_core::{ + GroupProposal, GroupProposalBuilder, GroupProposalDescContent, GroupProposalObject, + GroupPropsalDecideParam, GroupRPath, +}; + +use crate::GROUP_METHOD_DECIDE; + +pub struct GroupDecideProposal { + proposal: GroupProposal, + decides: Vec, +} + +impl GroupDecideProposal { + pub fn create( + rpath: GroupRPath, + decides: Vec, + owner_id: ObjectId, + ) -> GroupDecideProposalBuilder { + GroupDecideProposalBuilder::create(rpath, decides, owner_id) + } + + pub fn base(&self) -> &GroupProposal { + &self.proposal + } + + pub fn decides(&self) -> &[GroupPropsalDecideParam] { + self.decides.as_slice() + } +} + +impl TryFrom for GroupDecideProposal { + type Error = BuckyError; + + fn try_from(value: GroupProposal) -> Result { + if value.params().is_none() { + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + "param for GroupDecideProposal shoud not None", + )); + } + + let (decides, remain) = Vec::::raw_decode( + value.params().as_ref().unwrap().as_slice(), + )?; + assert_eq!(remain.len(), 0); + + let ret = GroupDecideProposal { + proposal: value, + decides, + }; + Ok(ret) + } +} + +pub struct GroupDecideProposalBuilder { + proposal: GroupProposalBuilder, + decides: Vec, +} + +impl GroupDecideProposalBuilder { + pub fn create( + rpath: GroupRPath, + decides: Vec, + owner: ObjectId, + ) -> Self { + let param_vec = { + let len = decides.raw_measure(&None).unwrap(); + let mut buf = vec![0u8; len]; + let remain = decides.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + buf + }; + + let proposal = GroupProposal::create( + rpath, + GROUP_METHOD_DECIDE.to_string(), + Some(param_vec), + None, + None, + None, + None, + None, + ); + + Self { proposal, decides } + } + + pub fn desc_builder(&mut self) -> &mut NamedObjectDescBuilder { + self.proposal.mut_desc_builder() + } + + pub fn build(mut self) -> GroupDecideProposal { + let mut decides = vec![]; + mem::swap(&mut decides, &mut self.decides); + + GroupDecideProposal { + proposal: self.proposal.build(), + decides, + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group/src/objects/group_update_proposal.rs new file mode 100644 index 000000000..c7aaebabe --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_update_proposal.rs @@ -0,0 +1,244 @@ +use std::mem; + +use async_std::task; +use cyfs_base::*; +use cyfs_chunk_lib::ChunkMeta; +use cyfs_core::{ + GroupProposal, GroupProposalBuilder, GroupProposalDescContent, GroupProposalObject, + GroupPropsalDecideParam, GroupRPath, GroupUpdateGroupPropsalParam, +}; + +use crate::{GROUP_METHOD_UPDATE, STATEPATH_GROUP_DEC_ID, STATEPATH_GROUP_DEC_RPATH}; + +pub struct GroupUpdateProposal { + proposal: GroupProposal, + target_dec_id: Vec, + from_chunk_id: Option, + to_group: Group, +} + +impl GroupUpdateProposal { + pub fn create( + from_group_chunk_id: Option, + to_group: Group, + target_dec_id: Vec, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> GroupUpdateProposalBuilder { + GroupUpdateProposalBuilder::create( + from_group_chunk_id, + to_group, + target_dec_id, + meta_block_id, + effective_begining, + effective_ending, + ) + } + + pub fn create_new_group( + to_group: Group, + target_dec_id: Vec, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> GroupUpdateProposalBuilder { + GroupUpdateProposalBuilder::create( + None, + to_group, + target_dec_id, + meta_block_id, + effective_begining, + effective_ending, + ) + } + + pub fn base(&self) -> &GroupProposal { + &self.proposal + } + + pub fn target_dec_id(&self) -> &[ObjectId] { + self.target_dec_id.as_slice() + } + + pub fn from_chunk_id(&self) -> &Option { + &self.from_chunk_id + } + + pub fn to_group(&self) -> &Group { + &self.to_group + } + + pub async fn decide( + &mut self, + member_id: ObjectId, + decide: Vec, + private_key: &PrivateKey, + ) -> BuckyResult { + self.proposal.decide(member_id, decide, private_key).await + } + + async fn verify_and_merge_decide( + &mut self, + decide: &GroupPropsalDecideParam, + member_id: ObjectId, + public_key: &PublicKey, + ) -> BuckyResult<()> { + self.proposal + .verify_and_merge_decide(decide, member_id, public_key) + .await + } + + pub fn group_update_rpath(group_id: ObjectId) -> GroupRPath { + GroupRPath::new( + group_id, + *STATEPATH_GROUP_DEC_ID, + STATEPATH_GROUP_DEC_RPATH.to_string(), + ) + } +} + +impl TryFrom for GroupUpdateProposal { + type Error = BuckyError; + + fn try_from(value: GroupProposal) -> Result { + if value.params().is_none() { + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + "param for GroupUpdateProposal shoud not None", + )); + } + + let (param, remain) = + GroupUpdateGroupPropsalParam::raw_decode(value.params().as_ref().unwrap().as_slice())?; + assert_eq!(remain.len(), 0); + + if value.payload().is_none() { + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + "payload for GroupUpdateProposal shoud not None", + )); + } + + let payload = value.payload().as_ref().unwrap(); + let (group_chunk, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); + assert_eq!(remain.len(), 0); + + let to_group = Group::try_from(&group_chunk)?; + + let to_chunk_id = + task::block_on(async { group_chunk.to_chunk().await.unwrap().calculate_id() }); + if &to_chunk_id.object_id() != param.to_chunk_id() { + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + "the chunk in GroupUpdateProposal.body is not match with the to_chunk_id in desc.param", + )); + } + + let ret = Self { + proposal: value, + target_dec_id: Vec::from(param.target_dec_id()), + from_chunk_id: param.from_chunk_id().clone(), + to_group, + }; + + Ok(ret) + } +} + +pub struct GroupUpdateProposalBuilder { + proposal: GroupProposalBuilder, + target_dec_id: Vec, + from_chunk_id: Option, + to_group: Option, +} + +impl GroupUpdateProposalBuilder { + pub fn create( + from_group_chunk_id: Option, + to_group: Group, + target_dec_id: Vec, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> Self { + let group_chunk = ChunkMeta::from(&to_group); + let group_chunk_vec = { + let len = group_chunk.raw_measure(&None).unwrap(); + let mut buf = vec![0u8; len]; + let remain = group_chunk.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + buf + }; + + let to_chunk_id = + task::block_on(async { group_chunk.to_chunk().await.unwrap().calculate_id() }); + + let param = + GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_chunk_id.object_id()); + let param_vec = { + let len = param.raw_measure(&None).unwrap(); + let mut buf = vec![0u8; len]; + let remain = param.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + buf + }; + + let group_id = to_group.desc().group_id(); + let update_rpath = GroupUpdateProposal::group_update_rpath(group_id.object_id().clone()); + + let proposal = GroupProposal::create( + update_rpath, + GROUP_METHOD_UPDATE.to_string(), + Some(param_vec), + Some(group_chunk_vec), + None, + meta_block_id, + effective_begining, + effective_ending, + ); + + Self { + proposal, + target_dec_id, + from_chunk_id: from_group_chunk_id, + to_group: Some(to_group), + } + } + + pub fn create_new_group( + to_group: Group, + target_dec_id: Vec, + meta_block_id: Option, + effective_begining: Option, + effective_ending: Option, + ) -> Self { + Self::create( + None, + to_group, + target_dec_id, + meta_block_id, + effective_begining, + effective_ending, + ) + } + + pub fn desc_builder(&mut self) -> &mut NamedObjectDescBuilder { + self.proposal.mut_desc_builder() + } + + pub fn build(mut self) -> GroupUpdateProposal { + let mut target_dec_id: Vec = vec![]; + let mut from_chunk_id: Option = None; + let to_group = self.to_group.take().unwrap(); + mem::swap(&mut target_dec_id, &mut self.target_dec_id); + mem::swap(&mut from_chunk_id, &mut self.from_chunk_id); + + GroupUpdateProposal { + proposal: self.proposal.build(), + target_dec_id, + from_chunk_id, + to_group, + } + } +} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs new file mode 100644 index 000000000..d6de55d79 --- /dev/null +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -0,0 +1,7 @@ +mod group_decide_proposal; +mod group_update_proposal; +mod protocol; + +pub use group_decide_proposal::*; +pub use group_update_proposal::*; +pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs new file mode 100644 index 000000000..2e2049d61 --- /dev/null +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -0,0 +1,101 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} + +use cyfs_base::*; +use cyfs_core::{GroupRPath, HotstuffBlockQC}; +use serde::Serialize; + +#[derive(Clone, RawEncode, RawDecode)] +pub(crate) enum HotstuffMessage { + Block(cyfs_core::GroupConsensusBlock), + BlockVote(HotstuffBlockQCVote), + TimeoutVote(HotstuffTimeoutVote), + Timeout(cyfs_core::HotstuffTimeout), +} + +#[derive(Clone, RawEncode, RawDecode)] +pub(crate) enum HotstuffPackage { + Block(cyfs_core::GroupConsensusBlock), + BlockVote(ProtocolAddress, HotstuffBlockQCVote), + TimeoutVote(ProtocolAddress, HotstuffTimeoutVote), + Timeout(ProtocolAddress, cyfs_core::HotstuffTimeout), +} + +#[derive(Clone, RawEncode, RawDecode)] +pub(crate) enum ProtocolAddress { + Full(GroupRPath), + Channel(u64), +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] +pub(crate) struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub round: u64, + pub dummy_round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + dummy_round: value.dummy_round, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = crate::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + dummy_round: value.dummy_round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] +pub(crate) struct HotstuffTimeoutVote { + pub high_qc: HotstuffBlockQC, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc: HotstuffBlockQC::raw_decode(value.high_qc.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = crate::protos::HotstuffTimeoutVote { + high_qc: value.high_qc.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md new file mode 100644 index 000000000..c0fb7c6be --- /dev/null +++ b/src/component/cyfs-group/src/statepath/design.md @@ -0,0 +1,63 @@ +``` +/--groups // for manager;通过决议以后构造/更新的Group对象放在这里,更新步骤 +| | // 1.得到一个创建/更新一个Group的决议(旧成员一定量的投票+所有新成员签名) +| | // 形成决议的方式可以是合约,也可以是超送用`DEC框架`实现的DEC +| | // 2.跟friend管理一样,用决议设定到系统更新Group信息 +| | // 3.更新Group下所有r-path的本地Group版本,并达成共识;这里主要要同步ood-list +| |--list-->Set +| |--option-->GroupOption +| +|--.dec-state // for dec;各Group的dec状态放这里 +| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 +| |--${dec-id} | .group // 一个dec管理的${r-path}状态 +| | | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | +| +|--.link // 区块链结构,记录状态变更链条 +| |--${group-id} +| |--${dec-id} | .group // .group表示group本身的演变共识 +| |--${r-path} +| |--group-chunk-->Chunk(Group) +| |--users +| | |--${user-id} +| | |--xxx +| |--last-vote-round-->u64 // 最后一次投票的轮次 +| | +| |--range-->(${first_height}, ${header_seq}) // 保留的历史block序列号区间 +| |--str(${height}) +| | |--block-->GroupConsensusBlock +| | |--proposals-->Set +| | +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| | +| |--finish-proposals +| | |--flip-time-->Timestamp // 取block时间戳 +| | |--recycle-->Set +| | |--adding-->Set +``` + +``` +// .group结构 +/--${group-id} + |--ObjectId(.group) + |--.update + |--voting + | |--${proposal-id} + | |--proposal-->GroupUpdateProposal + | |--decides-->Set + |--latest-version-->GroupUpdateProposal // Chunk(Encode(group)) + |--str(version-seq)-->GroupUpdateProposal // Chunk(Encode(group)) + |--str(group-hash)-->GroupUpdateProposal +``` diff --git a/src/component/cyfs-group/src/statepath/mod.rs b/src/component/cyfs-group/src/statepath/mod.rs new file mode 100644 index 000000000..20219f092 --- /dev/null +++ b/src/component/cyfs-group/src/statepath/mod.rs @@ -0,0 +1,3 @@ +mod statepath; + +pub use statepath::*; diff --git a/src/component/cyfs-group/src/statepath/statepath.rs b/src/component/cyfs-group/src/statepath/statepath.rs new file mode 100644 index 000000000..eabc1fdde --- /dev/null +++ b/src/component/cyfs-group/src/statepath/statepath.rs @@ -0,0 +1,202 @@ +use cyfs_base::{CustomObjectId, ObjectId}; + +pub const STATEPATH_SEPARATOR: &str = "/"; + +pub const STATEPATH_GROUPS: &str = "groups"; + +pub const STATEPATH_DEC_STATE: &str = ".dec-state"; + +pub const STATEPATH_LINK: &str = ".link"; +pub const STATEPATH_GROUP_HASH: &str = "group-hash"; +pub const STATEPATH_USERS: &str = "users"; +pub const STATEPATH_USERS_NONCE: &str = "nonce"; +pub const STATEPATH_RANGE: &str = "range"; +pub const STATEPATH_BLOCK: &str = "block"; + +pub const STATEPATH_RPATHS: &str = ".r-paths"; + +pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; +pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; + +lazy_static::lazy_static! { + pub static ref STATEPATH_GROUP_DEC_ID: ObjectId = ObjectId::from_slice_value(".group".as_bytes()); + pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); +} + +pub struct StatePath { + group_id: ObjectId, + group_id_str: String, + dec_id: ObjectId, + dec_id_str: String, + rpath: String, +} + +impl StatePath { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { + Self { + group_id_str: group_id.to_string(), + group_id, + dec_id_str: dec_id.to_string(), + dec_id, + rpath, + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATEPATH_SEPARATOR) + } + + pub fn dec_state() -> String { + STATEPATH_DEC_STATE.to_string() + } + + pub fn dec_state_group(&self) -> String { + Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) + } + + pub fn dec_state_dec(&self) -> String { + Self::join(&[ + STATEPATH_DEC_STATE, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + ]) + } + + pub fn dec_state_rpath(&self) -> String { + Self::join(&[ + STATEPATH_DEC_STATE, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + ]) + } + + pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { + Self::join(&[ + STATEPATH_DEC_STATE, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + sub_path, + ]) + } + + pub fn link() -> String { + STATEPATH_LINK.to_string() + } + + pub fn link_group(&self) -> String { + Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + } + + pub fn link_dec(&self) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + ]) + } + + pub fn link_rpath(&self) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + ]) + } + + pub fn link_group_hash(&self) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + STATEPATH_GROUP_HASH, + ]) + } + + pub fn link_users(&self) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + STATEPATH_USERS, + ]) + } + + pub fn link_user(&self, user_id: &ObjectId) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + STATEPATH_USERS, + user_id.to_string().as_str(), + ]) + } + + pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + STATEPATH_USERS, + user_id.to_string().as_str(), + STATEPATH_USERS_NONCE, + ]) + } + + pub fn link_range(&self) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + STATEPATH_RANGE, + ]) + } + + pub fn link_height(&self, height_seq: u64) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + height_seq.to_string().as_str(), + ]) + } + + pub fn link_block(&self, height_seq: u64) -> String { + Self::join(&[ + STATEPATH_LINK, + self.group_id_str.as_str(), + self.dec_id_str.as_str(), + self.rpath.as_str(), + height_seq.to_string().as_str(), + STATEPATH_BLOCK, + ]) + } + + pub fn rpaths(&self) -> String { + STATEPATH_RPATHS.to_string() + } +} + +pub struct GroupUpdateStatePath; + +impl GroupUpdateStatePath { + pub fn latest_version() -> &'static str { + STATEPATH_GROUP_DEC_LATEST_VERSION + } + + pub fn version_seq(version_seq: u64) -> String { + version_seq.to_string() + } + + pub fn group_hash(group_hash: &ObjectId) -> String { + group_hash.to_string() + } +} diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs new file mode 100644 index 000000000..21ee2dffa --- /dev/null +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -0,0 +1,3 @@ +mod storage; + +pub use storage::*; diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs new file mode 100644 index 000000000..44dfd8055 --- /dev/null +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -0,0 +1,142 @@ +use std::collections::HashMap; + +use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; + +pub enum BlockLinkState { + Expired, + DuplicateProposal, + Duplicate, + Link( + Option, + HashMap, + ), // + Pending, +} + +pub struct Storage { + group: Group, + group_id: ObjectId, + dec_id: ObjectId, + rpath: String, + + dec_state_id: Option, + group_chunk_id: ObjectId, + height: u64, + last_vote_round: u64, // 参与投票的最后一个轮次 + header_block: Option, + first_block: Option, + prepares: HashMap, + pre_commits: HashMap, +} + +impl Storage { + pub async fn load(group_id: &ObjectId, dec_id: &ObjectId, rpath: &str) -> BuckyResult { + // 用hash加载chunk + // 从chunk解析group + unimplemented!() + } + + pub async fn insert( + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { + unimplemented!() + } + + pub fn header_block(&self) -> &Option { + unimplemented!() + } + + pub fn header_round(&self) -> u64 { + unimplemented!() + } + + pub fn header_height(&self) -> u64 { + unimplemented!() + } + + pub fn first_block(&self) -> &Option { + unimplemented!() + } + + pub fn prepares(&self) -> &HashMap { + unimplemented!() + } + + pub fn prepare_height(&self) -> u64 { + unimplemented!() + } + + pub fn pre_commits(&self) -> &HashMap { + unimplemented!() + } + + pub fn group(&self) -> &Group { + &self.group + } + + pub fn group_chunk_id(&self) -> &ObjectId { + unimplemented!() + } + + pub fn dec_state_id(&self) -> ObjectId { + unimplemented!() + } + + async fn user_nonce(&self, user_id: &ObjectId) -> BuckyResult> { + unimplemented!() + } + + pub fn insert_rpath(rpath_obj: &GroupRPath) -> BuckyResult<()> { + unimplemented!() + } + + pub fn get_rpath_by_id(rpath_id: &ObjectId) -> BuckyResult> { + unimplemented!() + } + + pub async fn push_block( + &mut self, + block: GroupConsensusBlock, + proposals: &[&GroupProposal], + ) -> BuckyResult<()> { + /** + * 1. 把block存入prepares + * 2. 把block.qc.block从prepares存入pre-commits + * 3. 把block.qc.block.qc.block从pre-commits存入链上 + * 4. 把淘汰block清理掉 + */ + unimplemented!() + } + + pub async fn last_vote_round(&self) -> u64 { + unimplemented!() + } + + pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { + if block.height() <= self.header_height() { + return Ok(BlockLinkState::Expired); + } + + let linked_state = match block.height().cmp(&(self.header_height() + 3)) { + std::cmp::Ordering::Less => { + // 重复block,BlockLinkState::Duplicate + BlockLinkState::Link(None, HashMap::default()) + } + std::cmp::Ordering::Equal => BlockLinkState::Link(None, HashMap::default()), + std::cmp::Ordering::Greater => BlockLinkState::Pending, + }; + + // BlockLinkState::Link状态也可能因为缺少前序成为BlockLinkState::Pending + // 去重proposal,BlockLinkState::DuplicateProposal,去重只检查相同分叉链上的proposal,不同分叉上允许有相同proposal + // 检查Proposal时间戳,早于去重proposal集合区间,或者晚于当前系统时间戳一定时间 + + Ok(linked_state) + } +} diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs new file mode 100644 index 000000000..635999f1e --- /dev/null +++ b/src/component/cyfs-group/src/utils.rs @@ -0,0 +1,8 @@ +use cyfs_base::ObjectId; + +pub type Round = u64; + +pub enum IsCreateRPath { + No, + Yes(Option), +} From 6452e9d942032c63df426c710918c0e4631030c1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 29 Dec 2022 21:24:56 +0800 Subject: [PATCH 006/553] vote --- src/Cargo.lock | 1 + .../cyfs-core/protos/core_objects.proto | 5 +- .../src/group/group_consensus_block.rs | 17 +- src/component/cyfs-group/Cargo.toml | 1 + .../protos/group_bft_protocol.proto | 1 - .../src/consensus/hotstuff/hotstuff.rs | 349 +++++++++++++----- .../src/consensus/vote/committee.rs | 24 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 187 +++++++--- .../cyfs-group/src/objects/protocol.rs | 41 +- .../cyfs-group/src/storage/storage.rs | 13 +- 10 files changed, 467 insertions(+), 172 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index df9c3b37c..3b61f69e1 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1967,6 +1967,7 @@ dependencies = [ "protoc-rust", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 3043faa2e..15d913836 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -364,14 +364,13 @@ message GroupPropsalDecideParam { message HotstuffBlockQc { bytes block_id = 1; uint64 round = 2; - uint64 dummy_round = 3; message VoteSignature { bytes voter = 1; bytes signature = 2; } - repeated VoteSignature votes = 4; + repeated VoteSignature votes = 3; } message HotstuffTimeout { @@ -415,7 +414,7 @@ message GroupConsensusBlockBodyContent { repeated Proposal proposals = 1; - optional HotstuffBlockQc qc = 2; + HotstuffBlockQc qc = 2; optional HotstuffTimeout tc = 3; } diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 2b5e45872..0a5b0646d 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -76,7 +76,6 @@ impl ProtobufTransform<&HotstuffBlockQCSign> pub struct HotstuffBlockQC { pub block_id: ObjectId, pub round: u64, - pub dummy_round: u64, pub votes: Vec, } @@ -162,7 +161,7 @@ impl ProtobufTransform<&GroupConsensusBlockProposal> #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockBodyContent)] pub struct GroupConsensusBlockBodyContent { proposals: Vec, - qc: Option, + qc: HotstuffBlockQC, tc: Option, } @@ -214,7 +213,7 @@ pub trait GroupConsensusBlockObject { meta_block_id: ObjectId, round: u64, group_chunk_id: ObjectId, - qc: Option, + qc: HotstuffBlockQC, tc: Option, owner: ObjectId, ) -> Self; @@ -224,12 +223,12 @@ pub trait GroupConsensusBlockObject { fn result_state_id(&self) -> &ObjectId; fn height(&self) -> u64; fn meta_block_id(&self) -> &ObjectId; - fn prev_block_id(&self) -> Option<&ObjectId>; + fn prev_block_id(&self) -> &ObjectId; fn owner(&self) -> &ObjectId; fn named_object(&self) -> &NamedObjectBase; fn round(&self) -> u64; fn group_chunk_id(&self) -> &ObjectId; - fn qc(&self) -> &Option; + fn qc(&self) -> &HotstuffBlockQC; fn tc(&self) -> &Option; } @@ -242,7 +241,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { meta_block_id: ObjectId, round: u64, group_chunk_id: ObjectId, - qc: Option, + qc: HotstuffBlockQC, tc: Option, owner: ObjectId, ) -> Self { @@ -309,9 +308,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &desc.meta_block_id } - fn prev_block_id(&self) -> Option<&ObjectId> { + fn prev_block_id(&self) -> &ObjectId { let body = self.0.body().as_ref().unwrap().content(); - body.qc.as_ref().map(|qc| &qc.block_id) + &body.qc.block_id } fn owner(&self) -> &ObjectId { @@ -333,7 +332,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &desc.group_chunk_id } - fn qc(&self) -> &Option { + fn qc(&self) -> &HotstuffBlockQC { let body = self.0.body().as_ref().unwrap().content(); &body.qc } diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index e35ad158b..f14fd1d10 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -23,6 +23,7 @@ serde = { version = '1.0', features = ['derive'] } prost = { version = '0.11.5' } protobuf = { version = '2', features = ['with-bytes'] } lazy_static = '1.4' +sha2 = { version = '0.8' } cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 4e8275009..a27a91dbe 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -4,7 +4,6 @@ syntax = "proto3"; message HotstuffBlockQCVote { bytes block_id = 1; uint64 round = 2; - uint64 dummy_round = 3; bytes voter = 4; bytes signature = 5; } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index c6d5a3518..62208ce67 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,16 +1,19 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::channel::{Receiver, Sender}; -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, +}; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use crate::{ - consensus::{order_block::OrderBlockMgr, proposal, timer::Timer}, + consensus::{order_block::OrderBlockMgr, timer::Timer}, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - RPathDelegate, Storage, VoteMgr, + PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, }; pub struct Hotstuff { @@ -18,16 +21,17 @@ pub struct Hotstuff { committee: Committee, store: Storage, signer: RsaCPUObjectSigner, - round: u64, // 当前轮次 - last_committed_round: u64, // 最后提交的轮次 - high_qc: HotstuffBlockQC, // 最后一次通过投票的确认信息 - timer: Timer, // 定时器 + round: u64, // 当前轮次 + high_qc: HotstuffBlockQC, // 最后一次通过投票的确认信息 + timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, rx_message: Receiver, + tx_proposal_consume: Sender, delegate: Arc>, order_block_mgr: OrderBlockMgr, + rpath: GroupRPath, } impl Hotstuff { @@ -40,9 +44,10 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, rx_message: Receiver, + tx_proposal_consume: Sender, delegate: Arc>, + rpath: GroupRPath, ) { - let last_committed_round = store.header_block().map_or(0, |block| block.round()); let mut round = 0; let mut high_qc = HotstuffBlockQC::default(); @@ -51,10 +56,8 @@ impl Hotstuff { round = block.round(); } - if let Some(qc) = block.qc().as_ref() { - if qc.round > high_qc.round { - high_qc = qc.clone(); - } + if block.qc().round > high_qc.round { + high_qc = block.qc().clone(); } } @@ -63,10 +66,8 @@ impl Hotstuff { round = block.round(); } - if let Some(qc) = block.qc().as_ref() { - if qc.round > high_qc.round { - high_qc = qc.clone(); - } + if block.qc().round > high_qc.round { + high_qc = block.qc().clone(); } } @@ -76,7 +77,6 @@ impl Hotstuff { store, signer, round, - last_committed_round, high_qc, timer: Timer::new(store.group().consensus_interval()), vote_mgr, @@ -85,6 +85,8 @@ impl Hotstuff { delegate, order_block_mgr: OrderBlockMgr::new(), non_driver, + rpath, + tx_proposal_consume, }; } @@ -96,22 +98,14 @@ impl Hotstuff { * 3. 同步块 * 4. 验证各个proposal执行结果 */ - { - if let Some(last_proposal) = block.proposals().last() { - if &last_proposal.result_state != block.result_state_id() { - log::warn!("the result-state({}) in last-proposal is missmatch with block.result_state_id({})" - , last_proposal.result_state, block.result_state_id()); - return Err(BuckyError::new( - BuckyErrorCode::Unmatch, - "result-state unmatch", - )); - } - } - } + Self::check_block_result_state(block)?; { // check leader - let leader = self.committee.get_leader(block.group_chunk_id()).await?; + let leader = self + .committee + .get_leader(block.group_chunk_id(), block.round()) + .await?; if &leader != block.owner() { log::warn!( "receive block from invalid leader({}), expected {}", @@ -144,28 +138,7 @@ impl Hotstuff { } crate::storage::BlockLinkState::Link(prev_block, proposals) => { // 顺序连接状态 - if block.proposals().is_empty() { - match prev_block.as_ref() { - Some(prev_block) => { - if block.result_state_id() != prev_block.result_state_id() { - log::warn!("block.result_state_id({}) is missmatch with prev_block.result_state_id({}) with no proposal." - , block.result_state_id(), prev_block.result_state_id()); - - return Err(BuckyError::new( - BuckyErrorCode::Unmatch, - "result-state unmatch", - )); - } - } - None => { - log::warn!("the first block is empty, ignore."); - return Err(BuckyError::new( - BuckyErrorCode::Ignored, - "empty first block", - )); - } - } - } + Self::check_empty_block_result_state_with_prev(block, &prev_block)?; (prev_block, proposals) } crate::storage::BlockLinkState::Pending => { @@ -175,62 +148,252 @@ impl Hotstuff { } }; - { - self.committee.verify_block(block).await?; + self.committee.verify_block(block).await?; + + self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await?; + + self.order_block_mgr.pop_link(block).await?; + + self.process_qc(block.qc()).await; + + if let Some(tc) = block.tc() { + self.advance_round(tc.round).await; } - { - let mut prev_state_id = prev_block - .as_ref() - .map_or(ObjectId::default(), |block| block.result_state_id().clone()); - - for proposal_exe_info in block.proposals() { - let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); - let receipt = if proposal_exe_info.receipt.len() > 0 { - Some(NONObjectInfo::new_from_object_raw( - proposal_exe_info.receipt.clone(), - )?) - } else { - None - }; - - let exe_result = ExecuteResult { - result_state_id: proposal_exe_info.result_state, - receipt, - context: proposal_exe_info.context.clone(), - }; - - if self - .delegate - .on_verify(proposal, prev_state_id, &exe_result) - .await? - { - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!("block verify failed by app, proposal: {}, prev_state: {}, expect-result: {}", - proposal_exe_info.proposal, prev_state_id, proposal_exe_info.result_state); + self.process_block(block).await + } + + fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { + if let Some(last_proposal) = block.proposals().last() { + if &last_proposal.result_state != block.result_state_id() { + log::warn!("the result-state({}) in last-proposal is unmatch with block.result_state_id({})" + , last_proposal.result_state, block.result_state_id()); + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "result-state unmatch", + )); + } + } + Ok(()) + } + + fn check_empty_block_result_state_with_prev( + block: &GroupConsensusBlock, + prev_block: &Option, + ) -> BuckyResult<()> { + if block.proposals().is_empty() { + match prev_block.as_ref() { + Some(prev_block) => { + if block.result_state_id() != prev_block.result_state_id() { + log::warn!("block.result_state_id({}) is unmatch with prev_block.result_state_id({}) with no proposal." + , block.result_state_id(), prev_block.result_state_id()); + + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "result-state unmatch", + )); + } + } + None => { + log::warn!("the first block is empty, ignore."); + return Err(BuckyError::new( + BuckyErrorCode::Ignored, + "empty first block", + )); } } + } + + Ok(()) + } + + async fn check_block_proposal_result_state_by_app( + &self, + block: &GroupConsensusBlock, + proposals: &HashMap, + prev_block: &Option, + ) -> BuckyResult<()> { + let mut prev_state_id = prev_block + .as_ref() + .map_or(ObjectId::default(), |block| block.result_state_id().clone()); + + for proposal_exe_info in block.proposals() { + let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); + let receipt = if proposal_exe_info.receipt.len() > 0 { + Some(NONObjectInfo::new_from_object_raw( + proposal_exe_info.receipt.clone(), + )?) + } else { + None + }; - assert_eq!( - &prev_state_id, - block.result_state_id(), - "the result state is missmatched" - ); + let exe_result = ExecuteResult { + result_state_id: proposal_exe_info.result_state, + receipt, + context: proposal_exe_info.context.clone(), + }; + + if self + .delegate + .on_verify(proposal, prev_state_id, &exe_result) + .await? + { + prev_state_id = proposal_exe_info.result_state; + } else { + log::warn!( + "block verify failed by app, proposal: {}, prev_state: {}, expect-result: {}", + proposal_exe_info.proposal, + prev_state_id, + proposal_exe_info.result_state + ); + + return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); + } } - unimplemented!() + assert_eq!( + &prev_state_id, + block.result_state_id(), + "the result state is unmatched" + ); + + Ok(()) } async fn process_block(&mut self, block: &GroupConsensusBlock) -> BuckyResult<()> { /** * 验证过的块执行这个函数 */ + let new_header_block = self.store.push_block(block.clone()).await?; + + if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + /** + * TODO: + * 这里只清理已经提交的block包含的proposal + * 已经执行过的待提交block包含的proposal在下次打包时候去重 + * */ + self.cleanup_proposal(&header_block).await; + + if block.owner() == &self.local_id { + self.notify_proposal_result(&header_block); + } + } + + if block.round() != self.round { + // 不是我的投票round + return Ok(()); + } + + if let Some(vote) = self.make_vote(block).await { + let next_leader = self + .committee + .get_leader(block.group_chunk_id(), self.round + 1) + .await?; + + if self.local_id == next_leader { + self.handle_vote(&vote).await?; + } else { + self.network_sender + .post_package( + HotstuffMessage::BlockVote(vote), + self.rpath.clone(), + &next_leader, + ) + .await; + } + } + + Ok(()) + } + + async fn process_qc(&mut self, qc: &HotstuffBlockQC) { + self.advance_round(qc.round).await; + self.update_high_qc(qc); + } + + async fn advance_round(&mut self, round: u64) { + if round < self.round { + return; + } + + if let Ok(group) = self.committee.get_group(None).await { + self.timer.reset(group.consensus_interval()); + self.round = round + 1; + self.vote_mgr.cleanup(self.round); + } + } + + fn update_high_qc(&mut self, qc: &HotstuffBlockQC) { + if qc.round > self.high_qc.round { + self.high_qc = qc.clone(); + } + } + + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { + let proposals = commited_block + .proposals() + .iter() + .map(|proposal| proposal.proposal) + .collect(); + PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, proposals).await + } + + fn notify_proposal_result(&self, block: &GroupConsensusBlock) { + // 通知客户端proposal执行结果 unimplemented!() } + async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { + if block.round() <= self.store.last_vote_round() { + return None; + } + + // round只能逐个递增 + let is_valid_round = if block.round() == block.qc().round + 1 { + true + } else if let Some(tc) = block.tc() { + block.round() == tc.round + 1 + && block.qc().round >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + } else { + false + }; + + if !is_valid_round { + return None; + } + + let vote = match HotstuffBlockQCVote::new(block, self.local_id, &self.signer).await { + Ok(vote) => vote, + Err(e) => { + log::warn!( + "signature for block-vote failed, block: {}, err: {}", + block.named_object().desc().object_id(), + e + ); + return None; + } + }; + + if self.store.set_last_vote_round(block.round()).await.is_err() { + return None; + } + + Some(vote) + } + async fn handle_vote(&mut self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { - unimplemented!() + if vote.round < self.round { + return Err(BuckyError::new(BuckyErrorCode::Expired, "expired vote")); + } + + self.committee.verify_vote(vote).await?; + + if let Some(qc) = self.vote_mgr.add_vote(vote.clone())? { + self.process_qc(&qc).await; + + if self.local_id == self.committee.get_leader(group_chunk_id, round) + } } async fn handle_timeout(&mut self, timeout: &HotstuffTimeoutVote) -> BuckyResult<()> { diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 80692ddd0..578a8d333 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -1,32 +1,28 @@ +use std::collections::HashSet; + use cyfs_base::{BuckyResult, Group, ObjectId}; use cyfs_core::GroupConsensusBlock; +use crate::HotstuffBlockQCVote; + pub struct Committee {} impl Committee { pub fn spawn() {} - pub async fn get_group(&self, group_chunk_id: &ObjectId) -> BuckyResult { + pub async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { unimplemented!() } pub async fn quorum_threshold( &self, - voters: &[ObjectId], - block_id: &ObjectId, + voters: &HashSet, + group_chunk_id: &ObjectId, ) -> BuckyResult { unimplemented!() } - pub async fn timeout_threshold( - &self, - voters: &[ObjectId], - high_qc_block_id: &ObjectId, - ) -> BuckyResult { - unimplemented!() - } - - pub async fn get_leader(&self, group_chunk_id: &ObjectId) -> BuckyResult { + pub async fn get_leader(&self, group_chunk_id: &ObjectId, round: u64) -> BuckyResult { unimplemented!() } @@ -36,4 +32,8 @@ impl Committee { * 验证block下的签名是否符合对上一个block归属group的确认 */ } + + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 0ec48f102..42b115f5e 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,27 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; -use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout, HotstuffTimeoutSign}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, +}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, + HotstuffTimeout, HotstuffTimeoutSign, +}; use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; pub struct VoteMgr { committee: Committee, - votes: HashMap>>, - timeouts: HashMap>, + round: u64, + blocks: HashMap, + votes: HashMap>>, // > + timeouts: HashMap>, // +} + +pub enum VoteThresholded { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), + None, } impl VoteMgr { @@ -17,36 +30,73 @@ impl VoteMgr { committee, votes: HashMap::new(), timeouts: HashMap::new(), + round: 0, + blocks: HashMap::new(), } } - pub fn add_vote(&mut self, vote: HotstuffBlockQCVote) -> BuckyResult> { - // TODO [issue #7]: A bad node may make us run out of memory by sending many votes - // with different round numbers or different digests. + pub async fn add_voting_block( + &mut self, + block: &GroupConsensusBlock, + ) -> BuckyResult { + if block.round() < self.round { + return Ok(None); + } + + let block_id = block.named_object().desc().object_id(); + self.blocks.insert(block_id, block.clone()); + + if let Some(votes) = self.votes.get(&block.round()) { + if let Some(qc_maker) = votes.get(&block_id) { + if let Some(qc) = qc_maker.on_block(block, &self.committee).await? { + return Ok(VoteThresholded::QC(qc)); + } + } + } + + // TODO timeout要取high_qc的最大值block + if let Some(votes) = self.timeouts.get(&block.round()) { + if let Some(qc_maker) = votes.get(&block_id) { + if let Some(qc) = qc_maker.on_block(block, &self.committee).await? { + return Ok(VoteThresholded::QC(qc)); + } + } + } + } + pub async fn add_vote( + &mut self, + vote: HotstuffBlockQCVote, + ) -> BuckyResult> { + let block_id = vote.block_id; // Add the new vote to our aggregator and see if we have a QC. self.votes .entry(vote.round) .or_insert_with(HashMap::new) .entry(vote.block_id) .or_insert_with(|| Box::new(QCMaker::new())) - .append(vote, &self.committee) + .append(vote, &self.committee, self.blocks.get(&block_id)) + .await } - pub fn add_timeout(&mut self, timeout: HotstuffTimeoutVote) -> BuckyResult> { - // TODO: A bad node may make us run out of memory by sending many timeouts - // with different round numbers. - + pub async fn add_timeout( + &mut self, + timeout: HotstuffTimeoutVote, + ) -> BuckyResult> { + let block_id = timeout.high_qc.block_id; // Add the new timeout to our aggregator and see if we have a TC. self.timeouts .entry(timeout.round) - .or_insert_with(|| Box::new(TCMaker::new())) - .append(timeout, &self.committee) + .or_insert_with(|| Box::new(TCMaker::new(timeout.round))) + .append(timeout, &self.committee, self.blocks.get(&block_id)) + .await } - pub fn cleanup(&mut self, round: &Round) { - self.votes.retain(|k, _| k >= round); - self.timeouts.retain(|k, _| k >= round); + pub fn cleanup(&mut self, round: u64) { + self.votes.retain(|k, _| k >= &round); + self.timeouts.retain(|k, _| k >= &round); + self.blocks.retain(|_, block| block.round() >= round); + self.round = round; } } @@ -66,10 +116,11 @@ impl QCMaker { } /// Try to append a signature to a (partial) quorum. - pub fn append( + pub async fn append( &mut self, vote: HotstuffBlockQCVote, committee: &Committee, + block: Option<&GroupConsensusBlock>, ) -> BuckyResult> { let author = vote.voter; @@ -78,31 +129,55 @@ impl QCMaker { } self.votes.push((author, vote.signature)); - if !self.thresholded - && committee - .quorum_threshold(self.votes.iter().map(|v| v.0).collect(), &vote.block_id)? - { - self.thresholded = true; - return Ok(Some(HotstuffBlockQC { - block_id: vote.block_id, - round: vote.round, - votes: self.votes.clone(), - dummy_round: todo!(), - })); + + match block { + Some(block) => self.on_block(block, committee).await, + None => Ok(None), + } + } + + pub async fn on_block( + &mut self, + block: &GroupConsensusBlock, + committee: &Committee, + ) -> BuckyResult> { + if !self.thresholded { + self.thresholded = committee + .quorum_threshold( + &self.votes.iter().map(|v| v.0).collect(), + block.group_chunk_id(), + ) + .await?; + if self.thresholded { + return Ok(Some(HotstuffBlockQC { + block_id: block.named_object().desc().object_id(), + round: block.round(), + votes: self + .votes + .iter() + .map(|(voter, signature)| HotstuffBlockQCSign { + voter: voter.clone(), + signature: signature.clone(), + }) + .collect(), + })); + } } Ok(None) } } struct TCMaker { + round: u64, votes: Vec<(ObjectId, Signature, u64)>, used: HashSet, thresholded: bool, } impl TCMaker { - pub fn new() -> Self { + pub fn new(round: u64) -> Self { Self { + round, votes: Vec::new(), used: HashSet::new(), thresholded: false, @@ -110,13 +185,16 @@ impl TCMaker { } /// Try to append a signature to a (partial) quorum. - pub fn append( + pub async fn append( &mut self, timeout: HotstuffTimeoutVote, committee: &Committee, + block: Option<&GroupConsensusBlock>, ) -> BuckyResult> { let author = timeout.voter; + assert_eq!(self.round, timeout.round); + // Ensure it is the first time this authority votes. if !self.used.insert(author) { return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, "has voted")); @@ -126,21 +204,38 @@ impl TCMaker { self.votes .push((author, timeout.signature, timeout.high_qc.round)); - if !self.thresholded - && committee.timeout_threshold( - self.votes.iter().map(|v| v.0).collect(), - &timeout.high_qc.block_id, - )? - { - self.thresholded = true; - return Ok(Some(HotstuffTimeout { - round: timeout.round, - votes: self.votes.iter().map(|v| HotstuffTimeoutSign { - voter: v.0, - high_qc_round: v.2, - signature: v.1, - }), - })); + match block { + Some(block) => self.on_block(block, committee).await, + None => Ok(None), + } + } + + pub async fn on_block( + &mut self, + block: &GroupConsensusBlock, + committee: &Committee, + ) -> BuckyResult> { + if !self.thresholded { + self.thresholded = committee + .quorum_threshold( + &self.votes.iter().map(|v| v.0).collect(), + block.group_chunk_id(), + ) + .await?; + if self.thresholded { + return Ok(Some(HotstuffTimeout { + round: self.round, + votes: self + .votes + .iter() + .map(|v| HotstuffTimeoutSign { + voter: v.0, + high_qc_round: v.2, + signature: v.1.clone(), + }) + .collect(), + })); + } } Ok(None) } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 2e2049d61..044e4b8ef 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -3,8 +3,9 @@ pub mod protos { } use cyfs_base::*; -use cyfs_core::{GroupRPath, HotstuffBlockQC}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use serde::Serialize; +use sha2::Digest; #[derive(Clone, RawEncode, RawDecode)] pub(crate) enum HotstuffMessage { @@ -33,11 +34,45 @@ pub(crate) enum ProtocolAddress { pub(crate) struct HotstuffBlockQCVote { pub block_id: ObjectId, pub round: u64, - pub dummy_round: u64, pub voter: ObjectId, pub signature: Signature, } +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.named_object().desc().object_id(); + let round = block.round(); + let signature = signer + .sign( + Self::hash_content(&block_id, round).as_slice(), + &SignatureSource::RefIndex(0), + ) + .await?; + + Ok(Self { + block_id, + round, + voter: local_id, + signature, + }) + } + + fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.round) + } + + fn hash_content(block_id: &ObjectId, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + impl ProtobufTransform for HotstuffBlockQCVote { fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { Ok(Self { @@ -45,7 +80,6 @@ impl ProtobufTransform for HotstuffBlockQCVo signature: Signature::raw_decode(value.signature.as_slice())?.0, block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, round: value.round, - dummy_round: value.dummy_round, }) } } @@ -55,7 +89,6 @@ impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcV let ret = crate::protos::HotstuffBlockQcVote { block_id: value.block_id.to_vec()?, round: value.round, - dummy_round: value.dummy_round, voter: value.voter.to_vec()?, signature: value.signature.to_vec()?, }; diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index 44dfd8055..a525d4ee4 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -100,22 +100,27 @@ impl Storage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - proposals: &[&GroupProposal], - ) -> BuckyResult<()> { + ) -> BuckyResult)>> { /** * 1. 把block存入prepares * 2. 把block.qc.block从prepares存入pre-commits * 3. 把block.qc.block.qc.block从pre-commits存入链上 - * 4. 把淘汰block清理掉 + * 4. 把其他分叉block清理掉 + * 5. 追加去重proposal + * 6. 如果header有变更,返回新的header和被清理的分叉blocks */ unimplemented!() } - pub async fn last_vote_round(&self) -> u64 { + pub fn last_vote_round(&self) -> u64 { unimplemented!() } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + if round <= self.last_vote_round { + return Ok(()); + } + unimplemented!() } From 3f5271a02da0c13391d79cad0602a30a30ecc57d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 30 Dec 2022 20:59:11 +0800 Subject: [PATCH 007/553] vote/timeout --- src/Cargo.lock | 1 + src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 180 +++++++++++++++++- .../src/consensus/vote/committee.rs | 12 +- .../cyfs-group/src/consensus/vote/mod.rs | 2 - .../cyfs-group/src/consensus/vote/vote.rs | 17 -- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 158 +++++++++++---- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/network/non_driver.rs | 20 +- .../cyfs-group/src/network/sender.rs | 2 +- .../cyfs-group/src/objects/protocol.rs | 34 ++++ .../cyfs-group/src/storage/storage.rs | 4 + 12 files changed, 360 insertions(+), 72 deletions(-) delete mode 100644 src/component/cyfs-group/src/consensus/vote/vote.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 3b61f69e1..026e4b4ed 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1948,6 +1948,7 @@ dependencies = [ name = "cyfs-group" version = "0.0.1" dependencies = [ + "async-recursion", "async-std", "async-trait", "chrono", diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index f14fd1d10..1a2820c21 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -24,6 +24,7 @@ prost = { version = '0.11.5' } protobuf = { version = '2', features = ['with-bytes'] } lazy_static = '1.4' sha2 = { version = '0.8' } +async-recursion = '1.0' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 62208ce67..b6c250449 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -2,7 +2,8 @@ use std::{collections::HashMap, sync::Arc}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, + RsaCPUObjectSigner, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath, HotstuffBlockQC, @@ -13,7 +14,8 @@ use cyfs_lib::NONObjectInfo; use crate::{ consensus::{order_block::OrderBlockMgr, timer::Timer}, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, + PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, + CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, }; pub struct Hotstuff { @@ -32,6 +34,8 @@ pub struct Hotstuff { delegate: Arc>, order_block_mgr: OrderBlockMgr, rpath: GroupRPath, + tx_message_inner: Sender, + rx_message_inner: Receiver, } impl Hotstuff { @@ -40,7 +44,6 @@ impl Hotstuff { committee: Committee, store: Storage, signer: RsaCPUObjectSigner, - vote_mgr: VoteMgr, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, rx_message: Receiver, @@ -71,6 +74,10 @@ impl Hotstuff { } } + let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); + + let vote_mgr = VoteMgr::new(committee.clone(), round); + let obj = Self { local_id, committee, @@ -87,6 +94,8 @@ impl Hotstuff { non_driver, rpath, tx_proposal_consume, + tx_message_inner, + rx_message_inner, }; } @@ -280,6 +289,14 @@ impl Hotstuff { } } + match self.vote_mgr.add_voting_block(block).await { + VoteThresholded::QC(qc) => return self.process_block_qc(qc, block).await, + VoteThresholded::TC(tc, max_high_qc_block) => { + return self.process_timeout_qc(tc, &max_high_qc_block).await + } + VoteThresholded::None => {} + } + if block.round() != self.round { // 不是我的投票round return Ok(()); @@ -292,7 +309,7 @@ impl Hotstuff { .await?; if self.local_id == next_leader { - self.handle_vote(&vote).await?; + self.handle_vote(&vote, Some(block)).await?; } else { self.network_sender .post_package( @@ -382,22 +399,113 @@ impl Hotstuff { Some(vote) } - async fn handle_vote(&mut self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { + async fn handle_vote( + &mut self, + vote: &HotstuffBlockQCVote, + block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { if vote.round < self.round { - return Err(BuckyError::new(BuckyErrorCode::Expired, "expired vote")); + return Ok(()); } self.committee.verify_vote(vote).await?; - if let Some(qc) = self.vote_mgr.add_vote(vote.clone())? { - self.process_qc(&qc).await; + let block = match block { + Some(b) => Some(b.clone()), + None => self + .store + .find_block(&vote.block_id) + .await + .map_or(None, |b| Some(b)), + }; + + if let Some((qc, block)) = self.vote_mgr.add_vote(vote.clone(), block).await? { + self.process_block_qc(qc, &block).await?; + } else if vote.round > self.round { + let block = self + .non_driver + .get_block(&vote.block_id, Some(&vote.voter)) + .await?; + + self.tx_message_inner + .send(HotstuffMessage::Block(block)) + .await; + } + + Ok(()) + } + + async fn process_block_qc( + &mut self, + qc: HotstuffBlockQC, + block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + self.process_qc(&qc).await; - if self.local_id == self.committee.get_leader(group_chunk_id, round) + if self.local_id + == self + .committee + .get_leader(block.group_chunk_id(), self.round) + .await? + { + self.generate_proposal(None).await; } + Ok(()) } async fn handle_timeout(&mut self, timeout: &HotstuffTimeoutVote) -> BuckyResult<()> { - unimplemented!() + if timeout.round < self.round || timeout.high_qc.round >= timeout.round { + return Ok(()); + } + + let block = match self.store.find_block(&timeout.high_qc.block_id).await { + Ok(block) => block, + Err(_) => { + self.vote_mgr.add_waiting_timeout(timeout.clone()); + let block = self + .non_driver + .get_block(&timeout.high_qc.block_id, Some(&timeout.voter)) + .await?; + + self.tx_message_inner + .send(HotstuffMessage::Block(block)) + .await; + return Ok(()); + } + }; + + self.committee.verify_timeout(timeout, &block).await?; + + self.process_qc(&timeout.high_qc).await; + + if let Some((tc, max_high_qc_block)) = + self.vote_mgr.add_timeout(timeout.clone(), block).await? + { + self.process_timeout_qc(tc, &max_high_qc_block).await?; + } + Ok(()) + } + + async fn process_timeout_qc( + &mut self, + tc: HotstuffTimeout, + max_high_qc_block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + self.advance_round(tc.round).await; + + if self.local_id + == self + .committee + .get_leader(max_high_qc_block.group_chunk_id(), self.round) + .await? + { + self.generate_proposal(Some(tc)).await; + Ok(()) + } else { + let latest_group = self.committee.get_group(None).await?; + self.broadcast(HotstuffMessage::Timeout(tc), &latest_group) + .await + } } async fn handle_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { @@ -405,9 +513,54 @@ impl Hotstuff { } async fn local_timeout_round(&mut self) -> BuckyResult<()> { + let latest_group = match self.committee.get_group(None).await { + Ok(group) => { + self.timer.reset(group.consensus_interval()); + group + } + Err(e) => { + self.timer.reset(HOTSTUFF_TIMEOUT_DEFAULT); + return Err(e); + } + }; + + let timeout = HotstuffTimeoutVote::new( + self.high_qc.clone(), + self.round, + self.local_id, + &self.signer, + ) + .await?; + + self.store.set_last_vote_round(self.round).await?; + + self.handle_timeout(&timeout).await; + + self.broadcast(HotstuffMessage::TimeoutVote(timeout), &latest_group) + .await; + + Ok(()) + } + + async fn generate_proposal(&mut self, tc: Option) { unimplemented!() } + async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { + let targets: Vec = group + .ood_list() + .iter() + .filter(|ood_id| **ood_id != self.local_id) + .map(|ood_id| ood_id.object_id().clone()) + .collect(); + + self.network_sender + .broadcast(msg, self.rpath.clone(), targets.as_slice()) + .await; + + Ok(()) + } + async fn run(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. @@ -438,6 +591,13 @@ impl Hotstuff { HotstuffMessage::Timeout(tc) => self.handle_tc(&tc).await, _ => panic!("Unexpected protocol message") }, + Some(message) = self.rx_message_inner.recv() => match message { + HotstuffMessage::Block(block) => self.handle_block(&block).await, + HotstuffMessage::BlockVote(vote) => self.handle_vote(&vote).await, + HotstuffMessage::TimeoutVote(timeout) => self.handle_timeout(&timeout).await, + HotstuffMessage::Timeout(tc) => self.handle_tc(&tc).await, + _ => panic!("Unexpected protocol message") + }, Some(block) = self.rx_loopback.recv() => self.process_block(&block).await, () = &mut self.timer => self.local_timeout_round().await, }; diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 578a8d333..3e54efb6d 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -3,8 +3,9 @@ use std::collections::HashSet; use cyfs_base::{BuckyResult, Group, ObjectId}; use cyfs_core::GroupConsensusBlock; -use crate::HotstuffBlockQCVote; +use crate::{HotstuffBlockQCVote, HotstuffTimeoutVote}; +#[derive(Clone)] pub struct Committee {} impl Committee { @@ -36,4 +37,13 @@ impl Committee { pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { unimplemented!() } + + pub async fn verify_timeout( + &self, + vote: &HotstuffTimeoutVote, + block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + // 用block验vote.high_qc + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/consensus/vote/mod.rs b/src/component/cyfs-group/src/consensus/vote/mod.rs index f2cf86596..5e1313752 100644 --- a/src/component/cyfs-group/src/consensus/vote/mod.rs +++ b/src/component/cyfs-group/src/consensus/vote/mod.rs @@ -1,7 +1,5 @@ mod committee; -mod vote; mod vote_mgr; pub use committee::*; -pub use vote::*; pub use vote_mgr::*; diff --git a/src/component/cyfs-group/src/consensus/vote/vote.rs b/src/component/cyfs-group/src/consensus/vote/vote.rs deleted file mode 100644 index 3c947db26..000000000 --- a/src/component/cyfs-group/src/consensus/vote/vote.rs +++ /dev/null @@ -1,17 +0,0 @@ -use cyfs_base::{BuckyResult, ObjectId, Signature}; -use cyfs_core::GroupConsensusBlock; - -use super::committee::Committee; - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - voter: ObjectId, /*stack*/ - ) -> BuckyResult { - unimplemented!() - } - - pub async fn verify(&self, committee: &Committee /*stack*/) -> BuckyResult { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 42b115f5e..30fd8f323 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -16,86 +16,166 @@ pub struct VoteMgr { blocks: HashMap, votes: HashMap>>, // > timeouts: HashMap>, // + waiting_timeouts: HashMap>>, // >> } pub enum VoteThresholded { QC(HotstuffBlockQC), - TC(HotstuffTimeout), + TC(HotstuffTimeout, GroupConsensusBlock), None, } +// TODO: 丢弃太大的round,避免恶意节点恶意用太大的round攻击内存 + impl VoteMgr { - pub fn new(committee: Committee) -> Self { + pub fn new(committee: Committee, round: u64) -> Self { Self { committee, votes: HashMap::new(), timeouts: HashMap::new(), - round: 0, + round, blocks: HashMap::new(), + waiting_timeouts: HashMap::new(), } } - pub async fn add_voting_block( - &mut self, - block: &GroupConsensusBlock, - ) -> BuckyResult { + pub async fn add_voting_block(&mut self, block: &GroupConsensusBlock) -> VoteThresholded { if block.round() < self.round { - return Ok(None); + return VoteThresholded::None; } let block_id = block.named_object().desc().object_id(); self.blocks.insert(block_id, block.clone()); - if let Some(votes) = self.votes.get(&block.round()) { - if let Some(qc_maker) = votes.get(&block_id) { - if let Some(qc) = qc_maker.on_block(block, &self.committee).await? { - return Ok(VoteThresholded::QC(qc)); + if let Some(qc_makers) = self.votes.get_mut(&block.round()) { + if let Some(qc_maker) = qc_makers.get_mut(&block_id) { + if let Some(qc) = qc_maker + .on_block(block, &self.committee) + .await + .unwrap_or(None) + { + return VoteThresholded::QC(qc); } } } - // TODO timeout要取high_qc的最大值block - if let Some(votes) = self.timeouts.get(&block.round()) { - if let Some(qc_maker) = votes.get(&block_id) { - if let Some(qc) = qc_maker.on_block(block, &self.committee).await? { - return Ok(VoteThresholded::QC(qc)); + let mut timeouts: Vec<(&u64, &mut Box)> = self + .timeouts + .iter_mut() + .filter(|(round, tc_maker)| { + **round >= block.round() + && tc_maker + .max_block() + .map_or(false, |max_block_id| block_id == max_block_id) + }) + .collect(); + + timeouts.sort_unstable_by(|l, r| r.0.cmp(l.0)); + + for (round, tc_maker) in timeouts { + if let Some(tc) = tc_maker + .on_block(block, &self.committee) + .await + .unwrap_or(None) + { + return VoteThresholded::TC(tc, block.clone()); + } + } + + let waiting_timeouts = self.waiting_timeouts.remove(&block_id); + if let Some(waiting_timeouts) = waiting_timeouts { + let mut waiting_timeouts: Vec<(u64, HashMap)> = + waiting_timeouts.into_iter().collect(); + waiting_timeouts.sort_unstable_by(|l, r| r.0.cmp(&l.0)); + + for (_, timeouts) in waiting_timeouts { + for (_, timeout) in timeouts { + if self.committee.verify_timeout(&timeout, block).await.is_ok() { + if let Some((tc, block)) = self + .add_timeout(timeout, block.clone()) + .await + .map_or(None, |r| r) + { + return VoteThresholded::TC(tc, block); + } + } } } } + + VoteThresholded::None } pub async fn add_vote( &mut self, vote: HotstuffBlockQCVote, - ) -> BuckyResult> { + block: Option, + ) -> BuckyResult> { + assert!(block + .as_ref() + .map_or(true, |b| b.named_object().desc().object_id() + == vote.block_id)); + let block_id = vote.block_id; + + if let Some(block) = block.as_ref() { + self.blocks.insert(block_id, block.clone()); + } + let block_ref = block.as_ref().or(self.blocks.get(&block_id)); + // Add the new vote to our aggregator and see if we have a QC. self.votes .entry(vote.round) .or_insert_with(HashMap::new) - .entry(vote.block_id) + .entry(block_id) .or_insert_with(|| Box::new(QCMaker::new())) - .append(vote, &self.committee, self.blocks.get(&block_id)) + .append(vote, &self.committee, block_ref) .await + .map(|vote| vote.map(|v| (v, block.unwrap().clone()))) } pub async fn add_timeout( &mut self, timeout: HotstuffTimeoutVote, - ) -> BuckyResult> { - let block_id = timeout.high_qc.block_id; + block: GroupConsensusBlock, + ) -> BuckyResult> { + assert!(block.named_object().desc().object_id() == timeout.high_qc.block_id); + // Add the new timeout to our aggregator and see if we have a TC. - self.timeouts + let tc_maker = self + .timeouts .entry(timeout.round) - .or_insert_with(|| Box::new(TCMaker::new(timeout.round))) - .append(timeout, &self.committee, self.blocks.get(&block_id)) + .or_insert_with(|| Box::new(TCMaker::new(timeout.round))); + + self.blocks.insert(timeout.high_qc.block_id, block); + let max_block_id = tc_maker.max_block().unwrap_or(timeout.high_qc.block_id); + let max_block = self.blocks.get(&max_block_id).unwrap(); + + tc_maker + .append(timeout, &self.committee, max_block) .await + .map(|vote| vote.map(|v| (v, max_block.clone()))) + } + + pub fn add_waiting_timeout(&mut self, timeout: HotstuffTimeoutVote) { + let block_id = timeout.high_qc.block_id; + self.waiting_timeouts + .entry(block_id) + .or_insert_with(HashMap::new) + .entry(timeout.round) + .or_insert_with(HashMap::new) + .entry(timeout.voter) + .or_insert(timeout); } pub fn cleanup(&mut self, round: u64) { self.votes.retain(|k, _| k >= &round); self.timeouts.retain(|k, _| k >= &round); self.blocks.retain(|_, block| block.round() >= round); + self.waiting_timeouts.retain(|_, timeouts| { + timeouts.retain(|k, timeouts| k >= &round); + !timeouts.is_empty() + }); self.round = round; } } @@ -169,7 +249,7 @@ impl QCMaker { struct TCMaker { round: u64, - votes: Vec<(ObjectId, Signature, u64)>, + votes: Vec, used: HashSet, thresholded: bool, } @@ -189,7 +269,7 @@ impl TCMaker { &mut self, timeout: HotstuffTimeoutVote, committee: &Committee, - block: Option<&GroupConsensusBlock>, + block: &GroupConsensusBlock, ) -> BuckyResult> { let author = timeout.voter; @@ -201,13 +281,9 @@ impl TCMaker { } // Add the timeout to the accumulator. - self.votes - .push((author, timeout.signature, timeout.high_qc.round)); + self.votes.push(timeout); - match block { - Some(block) => self.on_block(block, committee).await, - None => Ok(None), - } + self.on_block(block, committee).await } pub async fn on_block( @@ -218,10 +294,11 @@ impl TCMaker { if !self.thresholded { self.thresholded = committee .quorum_threshold( - &self.votes.iter().map(|v| v.0).collect(), + &self.votes.iter().map(|v| v.voter).collect(), block.group_chunk_id(), ) .await?; + if self.thresholded { return Ok(Some(HotstuffTimeout { round: self.round, @@ -229,9 +306,9 @@ impl TCMaker { .votes .iter() .map(|v| HotstuffTimeoutSign { - voter: v.0, - high_qc_round: v.2, - signature: v.1.clone(), + voter: v.voter, + high_qc_round: v.high_qc.round, + signature: v.signature.clone(), }) .collect(), })); @@ -239,4 +316,11 @@ impl TCMaker { } Ok(None) } + + pub fn max_block(&self) -> Option { + self.votes + .iter() + .max_by(|l, r| l.high_qc.round.cmp(&r.high_qc.round)) + .map(|v| v.high_qc.block_id) + } } diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 2a64bf053..735aec3b1 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -13,3 +13,4 @@ pub enum GroupUpdateDecide { pub const ASYNC_TIMEOUT: Duration = Duration::from_millis(500); pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; +pub const CHANNEL_CAPACITY: usize = 1000; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 029a8734a..6bf32917e 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,10 +1,11 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, RawDecode}; +use cyfs_core::GroupConsensusBlock; use cyfs_lib::NONObjectInfo; pub struct NonDriver {} impl NonDriver { - pub fn get_object( + pub async fn get_object( &self, object_id: &ObjectId, from: Option<&ObjectId>, @@ -12,11 +13,22 @@ impl NonDriver { unimplemented!() } - pub fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { unimplemented!() } - pub fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) -> BuckyResult<()> { + pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) -> BuckyResult<()> { unimplemented!() } + + pub async fn get_block( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupConsensusBlock::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 4e47c0e43..8bb483a83 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -11,5 +11,5 @@ impl Sender { pub async fn post_package(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &ObjectId) {} - pub async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[&ObjectId]) {} + pub async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[ObjectId]) {} } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 044e4b8ef..45dea8907 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -106,6 +106,40 @@ pub(crate) struct HotstuffTimeoutVote { pub signature: Signature, } +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: HotstuffBlockQC, + round: u64, + local_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.round, round).as_slice(), + &SignatureSource::RefIndex(0), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_id, + signature, + }) + } + + fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.round, self.round) + } + + fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + impl ProtobufTransform for HotstuffTimeoutVote { fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { Ok(Self { diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index a525d4ee4..4a8b8eee3 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -144,4 +144,8 @@ impl Storage { Ok(linked_state) } + + pub async fn find_block(&self, block_id: &ObjectId) -> BuckyResult { + unimplemented!() + } } From d4ee476c22accd0785eea0d05d168bbcc696f00a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 3 Jan 2023 21:18:00 +0800 Subject: [PATCH 008/553] generate block --- .../cyfs-core/protos/core_objects.proto | 5 +- .../cyfs-core/src/group/group_proposal.rs | 9 +- .../cyfs-group/src/consensus/block.rs | 16 +- .../src/consensus/hotstuff/hotstuff.rs | 161 ++++++++++++++++-- .../proposal/pending_proposal_mgr.rs | 41 ++--- .../src/consensus/vote/committee.rs | 11 +- src/component/cyfs-group/src/constant.rs | 2 +- .../cyfs-group/src/storage/storage.rs | 25 ++- 8 files changed, 199 insertions(+), 71 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 15d913836..14a857612 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -332,9 +332,8 @@ message GroupProposalDescContent { // time optional bytes meta_block_id = 4; - uint64 timestamp = 5; - optional uint64 effective_begining = 6; - optional uint64 effective_ending = 7; + optional uint64 effective_begining = 5; + optional uint64 effective_ending = 6; } message GroupProposalBodyContent { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index adba33d44..38762d4fd 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -12,7 +12,6 @@ pub struct GroupProposalDescContent { params: Option>, meta_block_id: Option, - timestamp: u64, effective_begining: Option, effective_ending: Option, } @@ -129,7 +128,6 @@ impl GroupProposalDescContent { r_path: GroupRPath, method: String, params: Option>, - timestamp: Option, meta_block_id: Option, effective_begining: Option, effective_ending: Option, @@ -139,7 +137,6 @@ impl GroupProposalDescContent { method, params, meta_block_id, - timestamp: timestamp.map_or(bucky_time_now(), |t| t), effective_begining, effective_ending, } @@ -226,7 +223,6 @@ impl GroupProposalObject for GroupProposal { method, params, meta_block_id, - timestamp: timestamp.map_or(bucky_time_now(), |t| t), effective_begining, effective_ending, }; @@ -238,6 +234,7 @@ impl GroupProposalObject for GroupProposal { decide_signatures: vec![], }, ) + .create_time(timestamp.map_or(bucky_time_now(), |t| t)) } fn r_path(&self) -> &GroupRPath { @@ -294,10 +291,6 @@ impl GroupProposalObject for GroupProposal { &self.desc().content().meta_block_id } - fn timestamp(&self) -> u64 { - self.desc().content().timestamp - } - fn effective_begining(&self) -> Option { self.desc().content().effective_begining } diff --git a/src/component/cyfs-group/src/consensus/block.rs b/src/component/cyfs-group/src/consensus/block.rs index 0f4ef8371..a4be3c4da 100644 --- a/src/component/cyfs-group/src/consensus/block.rs +++ b/src/component/cyfs-group/src/consensus/block.rs @@ -1,19 +1,5 @@ -use cyfs_base::BuckyResult; -use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_core::GroupConsensusBlock; pub trait AsBlock {} -#[async_trait::async_trait] -pub trait BlockBuilder { - async fn build( - &self, - proposals: Vec, - ) -> BuckyResult>; -} - impl AsBlock for GroupConsensusBlock {} - -pub struct GroupBlockBuilder {} - -#[async_trait::async_trait] -impl BlockBuilder for GroupBlockBuilder {} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index b6c250449..0e841d453 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,21 +1,21 @@ -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, - RsaCPUObjectSigner, + bucky_time_now, bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, + NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, }; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use crate::{ - consensus::{order_block::OrderBlockMgr, timer::Timer}, - Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, - CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, + consensus::{order_block::OrderBlockMgr, proposal, timer::Timer}, + AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, + HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, + VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; pub struct Hotstuff { @@ -228,6 +228,7 @@ impl Hotstuff { .map_or(ObjectId::default(), |block| block.result_state_id().clone()); for proposal_exe_info in block.proposals() { + // TODO: 去重 let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); let receipt = if proposal_exe_info.receipt.len() > 0 { Some(NONObjectInfo::new_from_object_raw( @@ -285,7 +286,7 @@ impl Hotstuff { self.cleanup_proposal(&header_block).await; if block.owner() == &self.local_id { - self.notify_proposal_result(&header_block); + self.notify_proposal_result_for_block(&header_block); } } @@ -356,11 +357,15 @@ impl Hotstuff { PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, proposals).await } - fn notify_proposal_result(&self, block: &GroupConsensusBlock) { + fn notify_proposal_result(&self, proposal: &GroupProposal, result: &NONObjectInfo) { // 通知客户端proposal执行结果 unimplemented!() } + fn notify_proposal_result_for_block(&self, block: &GroupConsensusBlock) { + unimplemented!() + } + async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { if block.round() <= self.store.last_vote_round() { return None; @@ -414,7 +419,7 @@ impl Hotstuff { Some(b) => Some(b.clone()), None => self .store - .find_block(&vote.block_id) + .find_block_in_cache(&vote.block_id) .await .map_or(None, |b| Some(b)), }; @@ -458,7 +463,11 @@ impl Hotstuff { return Ok(()); } - let block = match self.store.find_block(&timeout.high_qc.block_id).await { + let block = match self + .store + .find_block_in_cache(&timeout.high_qc.block_id) + .await + { Ok(block) => block, Err(_) => { self.vote_mgr.add_waiting_timeout(timeout.clone()); @@ -509,7 +518,38 @@ impl Hotstuff { } async fn handle_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { - unimplemented!() + let max_high_qc = tc + .votes + .iter() + .max_by(|high_qc_l, high_qc_r| high_qc_l.high_qc_round.cmp(&high_qc_r.high_qc_round)); + + let max_high_qc = if let Some(max_high_qc) = max_high_qc { + max_high_qc + } else { + return Ok(()); + }; + + if tc.round < self.round || max_high_qc.high_qc_round >= tc.round { + return Ok(()); + } + + let block = self + .store + .find_block_in_cache_by_round(max_high_qc.high_qc_round) + .await?; + self.committee.verify_tc(tc, &block).await?; + + self.advance_round(tc.round).await; + + if self.local_id + == self + .committee + .get_leader(block.group_chunk_id(), self.round) + .await? + { + self.generate_proposal(Some(tc.clone())).await; + } + Ok(()) } async fn local_timeout_round(&mut self) -> BuckyResult<()> { @@ -542,8 +582,97 @@ impl Hotstuff { Ok(()) } - async fn generate_proposal(&mut self, tc: Option) { - unimplemented!() + async fn generate_proposal(&mut self, tc: Option) -> BuckyResult<()> { + let mut proposals = PendingProposalMgr::query_proposals(&self.tx_proposal_consume).await?; + proposals.sort_by(|left, right| left.desc().create_time().cmp(right.desc().create_time())); + + let now = SystemTime::now(); + + let mut remove_proposals = vec![]; + // let mut dup_proposals = vec![]; + let mut time_adjust_proposals = vec![]; + let mut timeout_proposals = vec![]; + let mut executed_proposals = vec![]; + let mut failed_proposals = vec![]; + let mut result_state_id = self.store.dec_state_id(); + + for proposal in proposals { + if let Ok(is_finished) = self + .store + .is_proposal_finished(&proposal.id(), &self.high_qc.block_id) + .await + { + if is_finished { + // dup_proposals.push(proposal); + remove_proposals.push(proposal.id()); + continue; + } + } + + let create_time = bucky_time_to_system_time(proposal.desc().create_time()); + if now + .duration_since(create_time) + .or(create_time.duration_since(now)) + > TIME_PRECISION + { + // 时间误差太大 + time_adjust_proposals.push(proposal); + remove_proposals.push(proposal.id()); + continue; + } + + if let Some(ending) = proposal.effective_ending() { + if now >= bucky_time_to_system_time(ending) { + timeout_proposals.push(proposal); + remove_proposals.push(proposal.id()) + } + } + + match self + .delegate + .on_execute(&proposal, result_state_id) + .await + { + Ok(exe_result) => { + result_state_id = exe_result.result_state_id; + executed_proposals.push((proposal, exe_result)); + }, + Err(e) => { + remove_proposals.push(proposal.id()); + failed_proposals.push((proposal, e)); + } + }; + } + + for proposal in time_adjust_proposals { + // TODO: 矫正系统时间 + // self.notify_proposal_result(&proposal, result); + } + + for proposal in timeout_proposals { + // TODO: 超时 + // self.notify_proposal_result(&proposal, result); + } + + for proposal in failed_proposals { + // TODO: 执行失败 + // self.notify_proposal_result(&proposal, result) + } + + PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, remove_proposals).await; + + let proposals_param = executed_proposals + .into_iter() + .map(|(proposal, exe_result)| GroupConsensusBlockProposal { + proposal: proposal.id(), + result_state: exe_result.result_state_id, + receipt: exe_result + .receipt + .map_or(vec![], |receipt| receipt.object_raw), + context: exe_result.context, + }); + + GroupConsensusBlock::create(self.rpath.clone(), proposals_param, result_state_id, self.store.header_height()) } async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs index e03285f58..f7a8305cd 100644 --- a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -5,10 +5,10 @@ use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::GroupProposal; use futures::FutureExt; -use crate::{AsProposal, BlockBuilder, GroupBlockBuilder, ASYNC_TIMEOUT}; +use crate::AsProposal; pub enum ProposalConsumeMessage { - BuildBlock(GroupBlockBuilder), + Query(Sender>), Remove(Vec), } @@ -18,7 +18,6 @@ pub struct PendingProposalMgr { network_sender: crate::network::Sender, // TODO: 需要设计一个结构便于按时间或数量拆分 - // TODO: 要把修改group的提案单独排序处理 buffer: HashMap, } @@ -40,17 +39,22 @@ impl PendingProposalMgr { }); } - pub async fn build_block( + pub async fn query_proposals( tx_consume: &Sender, - builder: GroupBlockBuilder, - ) -> BuckyResult<()> { + ) -> BuckyResult> { + let (sender, receiver) = async_std::channel::bounded(1); tx_consume - .send(ProposalConsumeMessage::BuildBlock(builder)) + .send(ProposalConsumeMessage::Query(sender)) .await .map_err(|e| { log::error!("[pending_proposal_mgr] send message(query) faield: {}", e); BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") - }) + })?; + + receiver.recv().await.map_err(|e| { + log::error!("[pending_proposal_mgr] recv message(query) failed: {}", e); + BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") + }) } pub async fn remove_proposals( @@ -66,19 +70,8 @@ impl PendingProposalMgr { }) } - async fn build_block_impl(&mut self, builder: GroupBlockBuilder) -> BuckyResult<()> { - let proposals = self.buffer.drain().map(|(_, p)| p).collect(); - - let block = builder.build(proposals).await?; - if block.is_none() { - return Ok(()); - } - - /** - * TODO: - * 1. broadcast - */ - Ok(()) + async fn query_proposals_impl(&mut self) -> Vec { + self.buffer.iter().map(|(_, p)| p.clone()).collect() } async fn run(&mut self) { @@ -92,9 +85,9 @@ impl PendingProposalMgr { message = self.rx_consume.recv().fuse() => { if let Ok(message) = message { match message { - ProposalConsumeMessage::BuildBlock(builder) => { - let r = self.build_block_impl(builder).await; - notifier.send(r).await; + ProposalConsumeMessage::Query(sender) => { + let proposals = self.query_proposals_impl().await; + sender.send(proposals).await; }, ProposalConsumeMessage::Remove(proposal_ids) => { for id in &proposal_ids { diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 3e54efb6d..111fb31b6 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use cyfs_base::{BuckyResult, Group, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffTimeout}; use crate::{HotstuffBlockQCVote, HotstuffTimeoutVote}; @@ -46,4 +46,13 @@ impl Committee { // 用block验vote.high_qc unimplemented!() } + + pub async fn verify_tc( + &self, + tc: &HotstuffTimeout, + block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + // 用block验vote.high_qc + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 735aec3b1..79aa0694e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -10,7 +10,7 @@ pub enum GroupUpdateDecide { } // Some config -pub const ASYNC_TIMEOUT: Duration = Duration::from_millis(500); pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; +pub const TIME_PRECISION: Duration = Duration::from_millis(60000); diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index 4a8b8eee3..1cde9450c 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -20,10 +20,11 @@ pub struct Storage { dec_id: ObjectId, rpath: String, - dec_state_id: Option, + dec_state_id: Option, // max-height, max-round group_chunk_id: ObjectId, - height: u64, + height: u64, // commited/header height last_vote_round: u64, // 参与投票的最后一个轮次 + max_height_block: Option, header_block: Option, first_block: Option, prepares: HashMap, @@ -145,7 +146,25 @@ impl Storage { Ok(linked_state) } - pub async fn find_block(&self, block_id: &ObjectId) -> BuckyResult { + pub async fn find_block_in_cache( + &self, + block_id: &ObjectId, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn find_block_in_cache_by_round( + &self, + round: u64, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn is_proposal_finished( + &self, + proposal_id: &ObjectId, + pre_block_id: &ObjectId, + ) -> BuckyResult { unimplemented!() } } From 6c9c00ced401d670bfaa42218312f8e777904440 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 4 Jan 2023 19:36:30 +0800 Subject: [PATCH 009/553] generate block --- src/component/cyfs-base/src/objects/group.rs | 24 +- .../cyfs-core/protos/core_objects.proto | 2 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 1 - .../protos/group_bft_protocol.proto | 2 +- .../src/consensus/hotstuff/hotstuff.rs | 273 ++++++++++++------ .../proposal/pending_proposal_mgr.rs | 8 + .../src/consensus/vote/committee.rs | 12 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 60 ++-- .../cyfs-group/src/objects/protocol.rs | 20 +- .../cyfs-group/src/storage/storage.rs | 3 +- 11 files changed, 281 insertions(+), 140 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 59ad2a685..1cab779e3 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -286,18 +286,18 @@ impl Group { } } - pub fn group_hash(&self) -> ObjectId { - let mut without_sign = self.clone(); - without_sign.common_mut().join_signatures = vec![]; - - let mut hash = HashValue::default(); - let remain = without_sign - .raw_encode(hash.as_mut_slice(), &Some(RawEncodePurpose::Hash)) - .unwrap(); - assert_eq!(remain.len(), 0); - - ObjectId::from_slice_value(&hash.as_slice()[..31]) - } + // pub fn group_hash(&self) -> ObjectId { + // let mut without_sign = self.clone(); + // without_sign.common_mut().join_signatures = vec![]; + + // let mut hash = HashValue::default(); + // let remain = without_sign + // .raw_encode(hash.as_mut_slice(), &Some(RawEncodePurpose::Hash)) + // .unwrap(); + // assert_eq!(remain.len(), 0); + + // ObjectId::from_slice_value(&hash.as_slice()[..31]) + // } fn common(&self) -> &CommonGroupBodyContent { self.body().as_ref().unwrap().content().common() diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 14a857612..1e3faac20 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -413,7 +413,7 @@ message GroupConsensusBlockBodyContent { repeated Proposal proposals = 1; - HotstuffBlockQc qc = 2; + optional HotstuffBlockQc qc = 2; optional HotstuffTimeout tc = 3; } diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 0a5b0646d..82eee45e2 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -161,7 +161,7 @@ impl ProtobufTransform<&GroupConsensusBlockProposal> #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockBodyContent)] pub struct GroupConsensusBlockBodyContent { proposals: Vec, - qc: HotstuffBlockQC, + qc: Option, tc: Option, } @@ -213,7 +213,7 @@ pub trait GroupConsensusBlockObject { meta_block_id: ObjectId, round: u64, group_chunk_id: ObjectId, - qc: HotstuffBlockQC, + qc: Option, tc: Option, owner: ObjectId, ) -> Self; @@ -223,12 +223,12 @@ pub trait GroupConsensusBlockObject { fn result_state_id(&self) -> &ObjectId; fn height(&self) -> u64; fn meta_block_id(&self) -> &ObjectId; - fn prev_block_id(&self) -> &ObjectId; + fn prev_block_id(&self) -> Option<&ObjectId>; fn owner(&self) -> &ObjectId; fn named_object(&self) -> &NamedObjectBase; fn round(&self) -> u64; fn group_chunk_id(&self) -> &ObjectId; - fn qc(&self) -> &HotstuffBlockQC; + fn qc(&self) -> &Option; fn tc(&self) -> &Option; } @@ -241,7 +241,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { meta_block_id: ObjectId, round: u64, group_chunk_id: ObjectId, - qc: HotstuffBlockQC, + qc: Option, tc: Option, owner: ObjectId, ) -> Self { @@ -308,9 +308,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &desc.meta_block_id } - fn prev_block_id(&self) -> &ObjectId { + fn prev_block_id(&self) -> Option<&ObjectId> { let body = self.0.body().as_ref().unwrap().content(); - &body.qc.block_id + body.qc.as_ref().map(|qc| &qc.block_id) } fn owner(&self) -> &ObjectId { @@ -332,7 +332,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &desc.group_chunk_id } - fn qc(&self) -> &HotstuffBlockQC { + fn qc(&self) -> &Option { let body = self.0.body().as_ref().unwrap().content(); &body.qc } diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 38762d4fd..748b0ee8c 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -176,7 +176,6 @@ pub trait GroupProposalObject { fn params_hash(&self) -> BuckyResult>; fn params_object_id(&self) -> BuckyResult>; fn meta_block_id(&self) -> &Option; - fn timestamp(&self) -> u64; fn effective_begining(&self) -> Option; fn effective_ending(&self) -> Option; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index a27a91dbe..590c827b8 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -9,7 +9,7 @@ message HotstuffBlockQCVote { } message HotstuffTimeoutVote { - bytes high_qc = 1; // encode(core:HotstuffBlockQc) + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) uint64 round = 2; bytes voter = 3; bytes signature = 4; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 0e841d453..622c3d5af 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -2,9 +2,10 @@ use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ - bucky_time_now, bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, + bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, ChunkId, Group, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, }; +use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, @@ -23,9 +24,9 @@ pub struct Hotstuff { committee: Committee, store: Storage, signer: RsaCPUObjectSigner, - round: u64, // 当前轮次 - high_qc: HotstuffBlockQC, // 最后一次通过投票的确认信息 - timer: Timer, // 定时器 + round: u64, // 当前轮次 + high_qc: Option, // 最后一次通过投票的确认信息 + timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, @@ -34,8 +35,9 @@ pub struct Hotstuff { delegate: Arc>, order_block_mgr: OrderBlockMgr, rpath: GroupRPath, - tx_message_inner: Sender, - rx_message_inner: Receiver, + tx_message_inner: Sender<(GroupConsensusBlock, bool)>, + rx_message_inner: Receiver<(GroupConsensusBlock, bool)>, + rx_proposal_waiter: Option<(Receiver, u64)>, } impl Hotstuff { @@ -52,14 +54,15 @@ impl Hotstuff { rpath: GroupRPath, ) { let mut round = 0; - let mut high_qc = HotstuffBlockQC::default(); + let mut high_qc = None; + let mut high_qc_round = 0; for block in store.prepares().values() { if block.round() > round { round = block.round(); } - if block.qc().round > high_qc.round { + if block.qc().as_ref().map_or(0, |qc| qc.round) > high_qc_round { high_qc = block.qc().clone(); } } @@ -69,7 +72,7 @@ impl Hotstuff { round = block.round(); } - if block.qc().round > high_qc.round { + if block.qc().as_ref().map_or(0, |qc| qc.round) > high_qc_round { high_qc = block.qc().clone(); } } @@ -96,6 +99,7 @@ impl Hotstuff { tx_proposal_consume, tx_message_inner, rx_message_inner, + rx_proposal_waiter: None, }; } @@ -113,7 +117,7 @@ impl Hotstuff { // check leader let leader = self .committee - .get_leader(block.group_chunk_id(), block.round()) + .get_leader(Some(block.group_chunk_id()), block.round()) .await?; if &leader != block.owner() { log::warn!( @@ -293,7 +297,9 @@ impl Hotstuff { match self.vote_mgr.add_voting_block(block).await { VoteThresholded::QC(qc) => return self.process_block_qc(qc, block).await, VoteThresholded::TC(tc, max_high_qc_block) => { - return self.process_timeout_qc(tc, &max_high_qc_block).await + return self + .process_timeout_qc(tc, max_high_qc_block.as_ref()) + .await } VoteThresholded::None => {} } @@ -306,7 +312,7 @@ impl Hotstuff { if let Some(vote) = self.make_vote(block).await { let next_leader = self .committee - .get_leader(block.group_chunk_id(), self.round + 1) + .get_leader(Some(block.group_chunk_id()), self.round + 1) .await?; if self.local_id == next_leader { @@ -325,8 +331,9 @@ impl Hotstuff { Ok(()) } - async fn process_qc(&mut self, qc: &HotstuffBlockQC) { - self.advance_round(qc.round).await; + async fn process_qc(&mut self, qc: &Option) { + self.advance_round(qc.as_ref().map_or(0, |qc| qc.round)) + .await; self.update_high_qc(qc); } @@ -342,8 +349,8 @@ impl Hotstuff { } } - fn update_high_qc(&mut self, qc: &HotstuffBlockQC) { - if qc.round > self.high_qc.round { + fn update_high_qc(&mut self, qc: &Option) { + if qc.as_ref().map_or(0, |qc| qc.round) > self.high_qc.as_ref().map_or(0, |qc| qc.round) { self.high_qc = qc.clone(); } } @@ -372,11 +379,12 @@ impl Hotstuff { } // round只能逐个递增 - let is_valid_round = if block.round() == block.qc().round + 1 { + let is_valid_round = if block.round() == block.qc().as_ref().map_or(0, |qc| qc.round) + 1 { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && block.qc().round >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + && block.qc().as_ref().map_or(0, |qc| qc.round) + >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() } else { false }; @@ -432,9 +440,7 @@ impl Hotstuff { .get_block(&vote.block_id, Some(&vote.voter)) .await?; - self.tx_message_inner - .send(HotstuffMessage::Block(block)) - .await; + self.tx_message_inner.send((block, false)).await; } Ok(()) @@ -445,12 +451,12 @@ impl Hotstuff { qc: HotstuffBlockQC, block: &GroupConsensusBlock, ) -> BuckyResult<()> { - self.process_qc(&qc).await; + self.process_qc(&Some(qc)).await; if self.local_id == self .committee - .get_leader(block.group_chunk_id(), self.round) + .get_leader(Some(block.group_chunk_id()), self.round) .await? { self.generate_proposal(None).await; @@ -459,38 +465,42 @@ impl Hotstuff { } async fn handle_timeout(&mut self, timeout: &HotstuffTimeoutVote) -> BuckyResult<()> { - if timeout.round < self.round || timeout.high_qc.round >= timeout.round { + if timeout.round < self.round + || timeout.high_qc.as_ref().map_or(0, |qc| qc.round) >= timeout.round + { return Ok(()); } - let block = match self - .store - .find_block_in_cache(&timeout.high_qc.block_id) - .await - { - Ok(block) => block, - Err(_) => { - self.vote_mgr.add_waiting_timeout(timeout.clone()); - let block = self - .non_driver - .get_block(&timeout.high_qc.block_id, Some(&timeout.voter)) - .await?; - - self.tx_message_inner - .send(HotstuffMessage::Block(block)) - .await; - return Ok(()); - } + let block = match timeout.high_qc.as_ref() { + Some(qc) => match self.store.find_block_in_cache(&qc.block_id).await { + Ok(block) => Some(block), + Err(_) => { + self.vote_mgr.add_waiting_timeout(timeout.clone()); + let block = self + .non_driver + .get_block(&qc.block_id, Some(&timeout.voter)) + .await?; + + self.tx_message_inner.send((block, false)).await; + return Ok(()); + } + }, + None => None, }; - self.committee.verify_timeout(timeout, &block).await?; + self.committee + .verify_timeout(timeout, block.as_ref()) + .await?; self.process_qc(&timeout.high_qc).await; - if let Some((tc, max_high_qc_block)) = - self.vote_mgr.add_timeout(timeout.clone(), block).await? + if let Some((tc, max_high_qc_block)) = self + .vote_mgr + .add_timeout(timeout.clone(), block.as_ref()) + .await? { - self.process_timeout_qc(tc, &max_high_qc_block).await?; + self.process_timeout_qc(tc, max_high_qc_block.as_ref()) + .await?; } Ok(()) } @@ -498,14 +508,17 @@ impl Hotstuff { async fn process_timeout_qc( &mut self, tc: HotstuffTimeout, - max_high_qc_block: &GroupConsensusBlock, + max_high_qc_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { self.advance_round(tc.round).await; if self.local_id == self .committee - .get_leader(max_high_qc_block.group_chunk_id(), self.round) + .get_leader( + max_high_qc_block.map(|block| block.group_chunk_id()), + self.round, + ) .await? { self.generate_proposal(Some(tc)).await; @@ -533,18 +546,26 @@ impl Hotstuff { return Ok(()); } - let block = self - .store - .find_block_in_cache_by_round(max_high_qc.high_qc_round) - .await?; - self.committee.verify_tc(tc, &block).await?; + let block = if max_high_qc.high_qc_round == 0 { + None + } else { + let block = self + .store + .find_block_in_cache_by_round(max_high_qc.high_qc_round) + .await?; + Some(block) + }; + self.committee.verify_tc(tc, block.as_ref()).await?; self.advance_round(tc.round).await; if self.local_id == self .committee - .get_leader(block.group_chunk_id(), self.round) + .get_leader( + block.as_ref().map(|block| block.group_chunk_id()), + self.round, + ) .await? { self.generate_proposal(Some(tc.clone())).await; @@ -584,28 +605,39 @@ impl Hotstuff { async fn generate_proposal(&mut self, tc: Option) -> BuckyResult<()> { let mut proposals = PendingProposalMgr::query_proposals(&self.tx_proposal_consume).await?; - proposals.sort_by(|left, right| left.desc().create_time().cmp(right.desc().create_time())); + proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let now = SystemTime::now(); + let pre_block = match self.high_qc.as_ref() { + Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id).await?), + None => None, + }; + let latest_group = self.committee.get_group(None).await?; + let mut remove_proposals = vec![]; // let mut dup_proposals = vec![]; let mut time_adjust_proposals = vec![]; let mut timeout_proposals = vec![]; let mut executed_proposals = vec![]; let mut failed_proposals = vec![]; - let mut result_state_id = self.store.dec_state_id(); + let mut result_state_id = match pre_block.as_ref() { + Some(block) => block.result_state_id().clone(), + None => self.store.dec_state_id(), + }; for proposal in proposals { - if let Ok(is_finished) = self - .store - .is_proposal_finished(&proposal.id(), &self.high_qc.block_id) - .await - { - if is_finished { - // dup_proposals.push(proposal); - remove_proposals.push(proposal.id()); - continue; + if let Some(high_qc) = self.high_qc.as_ref() { + if let Ok(is_finished) = self + .store + .is_proposal_finished(&proposal.id(), &high_qc.block_id) + .await + { + if is_finished { + // dup_proposals.push(proposal); + remove_proposals.push(proposal.id()); + continue; + } } } @@ -613,30 +645,28 @@ impl Hotstuff { if now .duration_since(create_time) .or(create_time.duration_since(now)) + .unwrap() > TIME_PRECISION { // 时间误差太大 - time_adjust_proposals.push(proposal); remove_proposals.push(proposal.id()); + time_adjust_proposals.push(proposal); continue; } if let Some(ending) = proposal.effective_ending() { if now >= bucky_time_to_system_time(ending) { + remove_proposals.push(proposal.id()); timeout_proposals.push(proposal); - remove_proposals.push(proposal.id()) + continue; } } - match self - .delegate - .on_execute(&proposal, result_state_id) - .await - { + match self.delegate.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); - }, + } Err(e) => { remove_proposals.push(proposal.id()); failed_proposals.push((proposal, e)); @@ -661,6 +691,13 @@ impl Hotstuff { PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, remove_proposals).await; + if self + .try_wait_proposals(executed_proposals.as_slice(), &pre_block) + .await + { + return Ok(()); + } + let proposals_param = executed_proposals .into_iter() .map(|(proposal, exe_result)| GroupConsensusBlockProposal { @@ -670,9 +707,35 @@ impl Hotstuff { .receipt .map_or(vec![], |receipt| receipt.object_raw), context: exe_result.context, - }); + }) + .collect(); + + let group_chunk_id = ChunkMeta::from(&latest_group) + .to_chunk() + .await + .unwrap() + .calculate_id(); + + let block = GroupConsensusBlock::create( + self.rpath.clone(), + proposals_param, + result_state_id, + self.store.header_height(), + ObjectId::default(), // TODO: meta block id + self.round, + group_chunk_id.object_id(), + self.high_qc.clone(), + tc, + self.local_id, + ); - GroupConsensusBlock::create(self.rpath.clone(), proposals_param, result_state_id, self.store.header_height()) + self.tx_message_inner.send((block.clone(), true)).await; + + self.broadcast(HotstuffMessage::Block(block), &latest_group) + .await; + + self.rx_proposal_waiter = None; + Ok(()) } async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { @@ -690,6 +753,41 @@ impl Hotstuff { Ok(()) } + async fn try_wait_proposals( + &mut self, + executed_proposals: &[(GroupProposal, ExecuteResult)], + pre_block: &Option, + ) -> bool { + // empty block, qc only, it's unuseful when no block to qc + let mut will_wait_proposals = false; + if executed_proposals.len() == 0 { + match pre_block.as_ref() { + None => will_wait_proposals = true, + Some(pre_block) => { + if pre_block.proposals().len() == 0 { + match pre_block.prev_block_id() { + Some(pre_pre_block_id) => { + let pre_pre_block = + self.store.find_block_in_cache(pre_pre_block_id).await?; + if pre_pre_block.proposals().len() == 0 { + will_wait_proposals = true; + } + } + None => will_wait_proposals = true, + } + } + } + } + } + + if will_wait_proposals { + let (tx, rx) = async_std::channel::bounded(1); + self.rx_proposal_waiter = Some((rx, self.round)); + } + + will_wait_proposals + } + async fn run(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. @@ -713,22 +811,27 @@ impl Hotstuff { // and receive timeout notifications from our Timeout Manager. loop { let result = futures::select! { - Some(message) = self.rx_message.recv() => match message { + message = self.rx_message.recv().fuse() => match message { HotstuffMessage::Block(block) => self.handle_block(&block).await, - HotstuffMessage::BlockVote(vote) => self.handle_vote(&vote).await, + HotstuffMessage::BlockVote(vote) => self.handle_vote(&vote, None).await, HotstuffMessage::TimeoutVote(timeout) => self.handle_timeout(&timeout).await, HotstuffMessage::Timeout(tc) => self.handle_tc(&tc).await, - _ => panic!("Unexpected protocol message") }, - Some(message) = self.rx_message_inner.recv() => match message { - HotstuffMessage::Block(block) => self.handle_block(&block).await, - HotstuffMessage::BlockVote(vote) => self.handle_vote(&vote).await, - HotstuffMessage::TimeoutVote(timeout) => self.handle_timeout(&timeout).await, - HotstuffMessage::Timeout(tc) => self.handle_tc(&tc).await, - _ => panic!("Unexpected protocol message") + (block, is_from_local) = self.rx_message_inner.recv().fuse() => { + if is_from_local { + self.process_block(&block).await + } else { + self.handle_block(&block).await + } }, - Some(block) = self.rx_loopback.recv() => self.process_block(&block).await, () = &mut self.timer => self.local_timeout_round().await, + wait_round = self.rx_proposal_waiter.map_or(std::future::pending::(), |(rx, round)| rx.recv().fuse()) => { + if let Some((_, round)) = self.rx_proposal_waiter { + if wait_round == round { + self.generate_proposal(None).await + } + } + } }; } } diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs index f7a8305cd..075bf5d1f 100644 --- a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -9,6 +9,7 @@ use crate::AsProposal; pub enum ProposalConsumeMessage { Query(Sender>), + Wait(Sender, u64), Remove(Vec), } @@ -93,6 +94,13 @@ impl PendingProposalMgr { for id in &proposal_ids { self.buffer.remove(id); } + }, + ProposalConsumeMessage::Wait(tx_waker, round) => { + if self.buffer.len() > 0 { + tx_waker.send(round).await + } else { + self. + } } } } diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 111fb31b6..e00824f02 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -18,12 +18,16 @@ impl Committee { pub async fn quorum_threshold( &self, voters: &HashSet, - group_chunk_id: &ObjectId, + group_chunk_id: Option<&ObjectId>, ) -> BuckyResult { unimplemented!() } - pub async fn get_leader(&self, group_chunk_id: &ObjectId, round: u64) -> BuckyResult { + pub async fn get_leader( + &self, + group_chunk_id: Option<&ObjectId>, + round: u64, + ) -> BuckyResult { unimplemented!() } @@ -41,7 +45,7 @@ impl Committee { pub async fn verify_timeout( &self, vote: &HotstuffTimeoutVote, - block: &GroupConsensusBlock, + pre_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { // 用block验vote.high_qc unimplemented!() @@ -50,7 +54,7 @@ impl Committee { pub async fn verify_tc( &self, tc: &HotstuffTimeout, - block: &GroupConsensusBlock, + pre_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { // 用block验vote.high_qc unimplemented!() diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 30fd8f323..3554ce5dd 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -21,7 +21,7 @@ pub struct VoteMgr { pub enum VoteThresholded { QC(HotstuffBlockQC), - TC(HotstuffTimeout, GroupConsensusBlock), + TC(HotstuffTimeout, Option), None, } @@ -74,11 +74,11 @@ impl VoteMgr { for (round, tc_maker) in timeouts { if let Some(tc) = tc_maker - .on_block(block, &self.committee) + .on_block(Some(block), &self.committee) .await .unwrap_or(None) { - return VoteThresholded::TC(tc, block.clone()); + return VoteThresholded::TC(tc, Some(block.clone())); } } @@ -90,9 +90,14 @@ impl VoteMgr { for (_, timeouts) in waiting_timeouts { for (_, timeout) in timeouts { - if self.committee.verify_timeout(&timeout, block).await.is_ok() { + if self + .committee + .verify_timeout(&timeout, Some(block)) + .await + .is_ok() + { if let Some((tc, block)) = self - .add_timeout(timeout, block.clone()) + .add_timeout(timeout, Some(block)) .await .map_or(None, |r| r) { @@ -137,9 +142,12 @@ impl VoteMgr { pub async fn add_timeout( &mut self, timeout: HotstuffTimeoutVote, - block: GroupConsensusBlock, - ) -> BuckyResult> { - assert!(block.named_object().desc().object_id() == timeout.high_qc.block_id); + block: Option<&GroupConsensusBlock>, + ) -> BuckyResult)>> { + assert!( + block.map(|block| block.named_object().desc().object_id()) + == timeout.high_qc.as_ref().map(|qc| qc.block_id) + ); // Add the new timeout to our aggregator and see if we have a TC. let tc_maker = self @@ -147,18 +155,25 @@ impl VoteMgr { .entry(timeout.round) .or_insert_with(|| Box::new(TCMaker::new(timeout.round))); - self.blocks.insert(timeout.high_qc.block_id, block); - let max_block_id = tc_maker.max_block().unwrap_or(timeout.high_qc.block_id); - let max_block = self.blocks.get(&max_block_id).unwrap(); + if let Some(qc) = timeout.high_qc.as_ref() { + self.blocks + .insert(qc.block_id, block.clone().unwrap().clone()); + } + + let max_block = tc_maker + .max_block() + .or(timeout.high_qc.as_ref().map(|qc| qc.block_id)) + .as_ref() + .map(|max_block_id| self.blocks.get(max_block_id).unwrap()); tc_maker .append(timeout, &self.committee, max_block) .await - .map(|vote| vote.map(|v| (v, max_block.clone()))) + .map(|vote| vote.map(|v| (v, max_block.cloned()))) } pub fn add_waiting_timeout(&mut self, timeout: HotstuffTimeoutVote) { - let block_id = timeout.high_qc.block_id; + let block_id = timeout.high_qc.unwrap().block_id; self.waiting_timeouts .entry(block_id) .or_insert_with(HashMap::new) @@ -225,7 +240,7 @@ impl QCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.0).collect(), - block.group_chunk_id(), + Some(block.group_chunk_id()), ) .await?; if self.thresholded { @@ -269,7 +284,7 @@ impl TCMaker { &mut self, timeout: HotstuffTimeoutVote, committee: &Committee, - block: &GroupConsensusBlock, + block: Option<&GroupConsensusBlock>, ) -> BuckyResult> { let author = timeout.voter; @@ -288,14 +303,14 @@ impl TCMaker { pub async fn on_block( &mut self, - block: &GroupConsensusBlock, + block: Option<&GroupConsensusBlock>, committee: &Committee, ) -> BuckyResult> { if !self.thresholded { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.voter).collect(), - block.group_chunk_id(), + block.map(|block| block.group_chunk_id()), ) .await?; @@ -307,7 +322,7 @@ impl TCMaker { .iter() .map(|v| HotstuffTimeoutSign { voter: v.voter, - high_qc_round: v.high_qc.round, + high_qc_round: v.high_qc.as_ref().map_or(0, |qc| qc.round), signature: v.signature.clone(), }) .collect(), @@ -320,7 +335,12 @@ impl TCMaker { pub fn max_block(&self) -> Option { self.votes .iter() - .max_by(|l, r| l.high_qc.round.cmp(&r.high_qc.round)) - .map(|v| v.high_qc.block_id) + .max_by(|l, r| { + l.high_qc + .as_ref() + .map_or(0, |qc| qc.round) + .cmp(&r.high_qc.as_ref().map_or(0, |qc| qc.round)) + }) + .map_or(None, |v| v.high_qc.as_ref().map(|qc| qc.block_id)) } } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 45dea8907..2d5cbcd0a 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -100,7 +100,7 @@ impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcV #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] #[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] pub(crate) struct HotstuffTimeoutVote { - pub high_qc: HotstuffBlockQC, + pub high_qc: Option, pub round: u64, pub voter: ObjectId, pub signature: Signature, @@ -108,14 +108,14 @@ pub(crate) struct HotstuffTimeoutVote { impl HotstuffTimeoutVote { pub async fn new( - high_qc: HotstuffBlockQC, + high_qc: Option, round: u64, local_id: ObjectId, signer: &RsaCPUObjectSigner, ) -> BuckyResult { let signature = signer .sign( - Self::hash_content(high_qc.round, round).as_slice(), + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), &SignatureSource::RefIndex(0), ) .await?; @@ -129,7 +129,7 @@ impl HotstuffTimeoutVote { } fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.round, self.round) + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) } fn hash_content(high_qc_round: u64, round: u64) -> HashValue { @@ -142,11 +142,16 @@ impl HotstuffTimeoutVote { impl ProtobufTransform for HotstuffTimeoutVote { fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; Ok(Self { voter: ObjectId::raw_decode(value.voter.as_slice())?.0, signature: Signature::raw_decode(value.signature.as_slice())?.0, round: value.round, - high_qc: HotstuffBlockQC::raw_decode(value.high_qc.as_slice())?.0, + high_qc, }) } } @@ -154,7 +159,10 @@ impl ProtobufTransform for HotstuffTimeoutVo impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { let ret = crate::protos::HotstuffTimeoutVote { - high_qc: value.high_qc.to_vec()?, + high_qc: match value.high_qc { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, round: value.round, voter: value.voter.to_vec()?, signature: value.signature.to_vec()?, diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index 1cde9450c..53dd6abeb 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -20,11 +20,10 @@ pub struct Storage { dec_id: ObjectId, rpath: String, - dec_state_id: Option, // max-height, max-round + dec_state_id: Option, // commited/header state id group_chunk_id: ObjectId, height: u64, // commited/header height last_vote_round: u64, // 参与投票的最后一个轮次 - max_height_block: Option, header_block: Option, first_block: Option, prepares: HashMap, From 5ddda9cd3caba0be318726f5a987cf74b2777c55 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 5 Jan 2023 19:02:32 +0800 Subject: [PATCH 010/553] core hotstuff --- .../cyfs-group/src/consensus/consensus.rs | 2 - .../src/consensus/hotstuff/hotstuff.rs | 263 ++++++++++++------ .../consensus/order_block/order_block_mgr.rs | 19 +- .../proposal/pending_proposal_mgr.rs | 13 +- .../cyfs-group/src/consensus/timer.rs | 21 +- .../cyfs-group/src/storage/storage.rs | 20 ++ 6 files changed, 228 insertions(+), 110 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/consensus.rs b/src/component/cyfs-group/src/consensus/consensus.rs index 7aaf5d126..b6fdb6535 100644 --- a/src/component/cyfs-group/src/consensus/consensus.rs +++ b/src/component/cyfs-group/src/consensus/consensus.rs @@ -3,8 +3,6 @@ use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::GroupProposal; -use crate::AsProposal; - #[async_trait::async_trait] pub trait AsConsensus { async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 622c3d5af..7e4b32f1d 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,6 +11,7 @@ use cyfs_core::{ GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use futures::FutureExt; use crate::{ consensus::{order_block::OrderBlockMgr, proposal, timer::Timer}, @@ -26,17 +27,18 @@ pub struct Hotstuff { signer: RsaCPUObjectSigner, round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 - timer: Timer, // 定时器 + tc: Option, + timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, - rx_message: Receiver, + rx_message: Receiver<(HotstuffMessage, ObjectId)>, tx_proposal_consume: Sender, delegate: Arc>, order_block_mgr: OrderBlockMgr, rpath: GroupRPath, - tx_message_inner: Sender<(GroupConsensusBlock, bool)>, - rx_message_inner: Receiver<(GroupConsensusBlock, bool)>, + tx_message_inner: Sender<(GroupConsensusBlock, ObjectId)>, + rx_message_inner: Receiver<(GroupConsensusBlock, ObjectId)>, rx_proposal_waiter: Option<(Receiver, u64)>, } @@ -48,34 +50,17 @@ impl Hotstuff { signer: RsaCPUObjectSigner, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, - rx_message: Receiver, + rx_message: Receiver<(HotstuffMessage, ObjectId)>, tx_proposal_consume: Sender, delegate: Arc>, rpath: GroupRPath, ) { - let mut round = 0; - let mut high_qc = None; - let mut high_qc_round = 0; + let max_round_block = store.block_with_max_round(); - for block in store.prepares().values() { - if block.round() > round { - round = block.round(); - } - - if block.qc().as_ref().map_or(0, |qc| qc.round) > high_qc_round { - high_qc = block.qc().clone(); - } - } - - for block in store.pre_commits().values() { - if block.round() > round { - round = block.round(); - } - - if block.qc().as_ref().map_or(0, |qc| qc.round) > high_qc_round { - high_qc = block.qc().clone(); - } - } + let mut round = store + .last_vote_round() + .max(max_round_block.as_ref().map_or(1, |block| block.round())); + let mut high_qc = max_round_block.map_or(None, |block| block.qc().clone()); let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -100,11 +85,16 @@ impl Hotstuff { tx_message_inner, rx_message_inner, rx_proposal_waiter: None, + tc: None, }; } // TODO: 网络层应该防御,只从当前group节点获取信息 - async fn handle_block(&mut self, block: &GroupConsensusBlock) -> BuckyResult<()> { + async fn handle_block( + &mut self, + block: &GroupConsensusBlock, + remote: ObjectId, + ) -> BuckyResult<()> { /** * 1. 验证block投票签名 * 2. 验证出块节点 @@ -156,7 +146,21 @@ impl Hotstuff { } crate::storage::BlockLinkState::Pending => { // 乱序,同步 - return self.order_block_mgr.push_block(block).await; + if block.height() <= self.store.header_height() + 3 { + self.fetch_block(block.prev_block_id().unwrap(), remote) + .await; + } + + let max_round_block = self.store.block_with_max_round(); + return self.order_block_mgr.push_outorder_block( + block, + max_round_block.map_or(1, |block| block.round() + 1), + remote, + ); + } + crate::storage::BlockLinkState::InvalidBranch => { + log::warn!("receive block in invalid branch."); + return Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch")); } } }; @@ -166,7 +170,7 @@ impl Hotstuff { self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) .await?; - self.order_block_mgr.pop_link(block).await?; + self.order_block_mgr.pop_link_from(block)?; self.process_qc(block.qc()).await; @@ -174,7 +178,7 @@ impl Hotstuff { self.advance_round(tc.round).await; } - self.process_block(block).await + self.process_block(block, remote).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -275,7 +279,11 @@ impl Hotstuff { Ok(()) } - async fn process_block(&mut self, block: &GroupConsensusBlock) -> BuckyResult<()> { + async fn process_block( + &mut self, + block: &GroupConsensusBlock, + remote: ObjectId, + ) -> BuckyResult<()> { /** * 验证过的块执行这个函数 */ @@ -295,7 +303,7 @@ impl Hotstuff { } match self.vote_mgr.add_voting_block(block).await { - VoteThresholded::QC(qc) => return self.process_block_qc(qc, block).await, + VoteThresholded::QC(qc) => return self.process_block_qc(qc, block, remote).await, VoteThresholded::TC(tc, max_high_qc_block) => { return self .process_timeout_qc(tc, max_high_qc_block.as_ref()) @@ -316,7 +324,7 @@ impl Hotstuff { .await?; if self.local_id == next_leader { - self.handle_vote(&vote, Some(block)).await?; + self.handle_vote(&vote, Some(block), remote).await?; } else { self.network_sender .post_package( @@ -346,6 +354,7 @@ impl Hotstuff { self.timer.reset(group.consensus_interval()); self.round = round + 1; self.vote_mgr.cleanup(self.round); + self.tc = None; } } @@ -416,6 +425,7 @@ impl Hotstuff { &mut self, vote: &HotstuffBlockQCVote, block: Option<&GroupConsensusBlock>, + remote: ObjectId, ) -> BuckyResult<()> { if vote.round < self.round { return Ok(()); @@ -433,14 +443,9 @@ impl Hotstuff { }; if let Some((qc, block)) = self.vote_mgr.add_vote(vote.clone(), block).await? { - self.process_block_qc(qc, &block).await?; + self.process_block_qc(qc, &block, remote).await?; } else if vote.round > self.round { - let block = self - .non_driver - .get_block(&vote.block_id, Some(&vote.voter)) - .await?; - - self.tx_message_inner.send((block, false)).await; + self.fetch_block(&vote.block_id, remote).await; } Ok(()) @@ -450,6 +455,7 @@ impl Hotstuff { &mut self, qc: HotstuffBlockQC, block: &GroupConsensusBlock, + remote: ObjectId, ) -> BuckyResult<()> { self.process_qc(&Some(qc)).await; @@ -464,7 +470,11 @@ impl Hotstuff { Ok(()) } - async fn handle_timeout(&mut self, timeout: &HotstuffTimeoutVote) -> BuckyResult<()> { + async fn handle_timeout( + &mut self, + timeout: &HotstuffTimeoutVote, + remote: ObjectId, + ) -> BuckyResult<()> { if timeout.round < self.round || timeout.high_qc.as_ref().map_or(0, |qc| qc.round) >= timeout.round { @@ -476,12 +486,7 @@ impl Hotstuff { Ok(block) => Some(block), Err(_) => { self.vote_mgr.add_waiting_timeout(timeout.clone()); - let block = self - .non_driver - .get_block(&qc.block_id, Some(&timeout.voter)) - .await?; - - self.tx_message_inner.send((block, false)).await; + self.fetch_block(&qc.block_id, remote).await; return Ok(()); } }, @@ -511,6 +516,7 @@ impl Hotstuff { max_high_qc_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { self.advance_round(tc.round).await; + self.tc = Some(tc.clone()); if self.local_id == self @@ -530,7 +536,7 @@ impl Hotstuff { } } - async fn handle_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + async fn handle_tc(&mut self, tc: &HotstuffTimeout, remote: ObjectId) -> BuckyResult<()> { let max_high_qc = tc .votes .iter() @@ -549,15 +555,28 @@ impl Hotstuff { let block = if max_high_qc.high_qc_round == 0 { None } else { - let block = self + let block = match self .store .find_block_in_cache_by_round(max_high_qc.high_qc_round) - .await?; + .await + { + Ok(block) => block, + Err(_) => { + // 同步前序block + let max_round_block = self.store.block_with_max_round(); + return self.order_block_mgr.sync_with_round( + max_round_block.map_or(1, |block| block.round() + 1), + remote, + ); + } + }; Some(block) }; + self.committee.verify_tc(tc, block.as_ref()).await?; self.advance_round(tc.round).await; + self.tc = Some(tc.clone()); if self.local_id == self @@ -585,20 +604,30 @@ impl Hotstuff { } }; - let timeout = HotstuffTimeoutVote::new( - self.high_qc.clone(), - self.round, - self.local_id, - &self.signer, - ) - .await?; + match self.tc.as_ref() { + Some(tc) => { + if tc.round + 1 == self.round { + self.broadcast(HotstuffMessage::Timeout(tc.clone()), &latest_group) + .await; + } + } + None => { + let timeout = HotstuffTimeoutVote::new( + self.high_qc.clone(), + self.round, + self.local_id, + &self.signer, + ) + .await?; - self.store.set_last_vote_round(self.round).await?; + self.store.set_last_vote_round(self.round).await?; - self.handle_timeout(&timeout).await; + self.handle_timeout(&timeout, self.local_id).await; - self.broadcast(HotstuffMessage::TimeoutVote(timeout), &latest_group) - .await; + self.broadcast(HotstuffMessage::TimeoutVote(timeout), &latest_group) + .await; + } + } Ok(()) } @@ -729,7 +758,9 @@ impl Hotstuff { self.local_id, ); - self.tx_message_inner.send((block.clone(), true)).await; + self.tx_message_inner + .send((block.clone(), self.local_id)) + .await; self.broadcast(HotstuffMessage::Block(block), &latest_group) .await; @@ -768,7 +799,10 @@ impl Hotstuff { match pre_block.prev_block_id() { Some(pre_pre_block_id) => { let pre_pre_block = - self.store.find_block_in_cache(pre_pre_block_id).await?; + match self.store.find_block_in_cache(pre_pre_block_id).await { + Ok(pre_pre_block) => pre_pre_block, + Err(_) => return false, + }; if pre_pre_block.proposals().len() == 0 { will_wait_proposals = true; } @@ -788,49 +822,94 @@ impl Hotstuff { will_wait_proposals } - async fn run(&mut self) { + async fn fetch_block(&self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { + let block = self.non_driver.get_block(block_id, Some(&remote)).await?; + + self.tx_message_inner.send((block, remote)).await; + Ok(()) + } + + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. - self.timer.reset( - self.committee - .get_group(self.header_block()) - .await - .map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| g.consensus_interval()), - ); - if let Ok(leader) = self - .committee - .get_next_leader(self.store.header_block()) - .await - { + let max_round_block = self.store.block_with_max_round(); + let group_chunk_id = max_round_block.as_ref().map(|block| block.group_chunk_id()); + let last_group = self.committee.get_group(group_chunk_id).await; + + let duration = last_group + .as_ref() + .map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| g.consensus_interval()); + self.timer.reset(duration); + + if let Ok(leader) = self.committee.get_leader(group_chunk_id, self.round).await { if leader == self.local_id { - self.generate_proposal(None).await; + match max_round_block { + Some(max_round_block) + if max_round_block.owner() == &self.local_id && last_group.is_ok() => + { + self.broadcast( + HotstuffMessage::Block(max_round_block), + &last_group.unwrap(), + ) + .await; + } + _ => { + self.generate_proposal(None).await; + } + } + } + } + } + + fn proposal_waiter(waiter: Option<(Receiver, u64)>) -> impl futures::Future { + async move { + match waiter.as_ref() { + Some((waiter, wait_round)) => { + waiter.recv().await; + *wait_round + } + None => std::future::pending::().await, } } + } + + async fn run(&mut self) { + self.recover().await; // This is the main loop: it processes incoming blocks and votes, // and receive timeout notifications from our Timeout Manager. loop { let result = futures::select! { message = self.rx_message.recv().fuse() => match message { - HotstuffMessage::Block(block) => self.handle_block(&block).await, - HotstuffMessage::BlockVote(vote) => self.handle_vote(&vote, None).await, - HotstuffMessage::TimeoutVote(timeout) => self.handle_timeout(&timeout).await, - HotstuffMessage::Timeout(tc) => self.handle_tc(&tc).await, - }, - (block, is_from_local) = self.rx_message_inner.recv().fuse() => { - if is_from_local { - self.process_block(&block).await - } else { - self.handle_block(&block).await + Ok((HotstuffMessage::Block(block), remote)) => self.handle_block(&block, remote).await, + Ok((HotstuffMessage::BlockVote(vote), remote)) => self.handle_vote(&vote, None, remote).await, + Ok((HotstuffMessage::TimeoutVote(timeout), remote)) => self.handle_timeout(&timeout, remote).await, + Ok((HotstuffMessage::Timeout(tc), remote)) => self.handle_tc(&tc, remote).await, + Err(e) => { + log::warn!("[hotstuff] rx_message closed."); + Ok(()) } }, - () = &mut self.timer => self.local_timeout_round().await, - wait_round = self.rx_proposal_waiter.map_or(std::future::pending::(), |(rx, round)| rx.recv().fuse()) => { - if let Some((_, round)) = self.rx_proposal_waiter { - if wait_round == round { - self.generate_proposal(None).await + message = self.rx_message_inner.recv().fuse() => match message { + Ok((block, remote)) => { + if remote == self.local_id { + self.process_block(&block, remote).await + } else { + self.handle_block(&block, remote).await } } + Err(e) => { + log::warn!("[hotstuff] rx_message_inner closed."); + Ok(()) + } + }, + () = self.timer.wait_next().fuse() => self.local_timeout_round().await, + wait_round = Self::proposal_waiter(self.rx_proposal_waiter.clone()).fuse() => { + if wait_round == self.round { + self.generate_proposal(None).await + } else { + Ok(()) + } } }; } diff --git a/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs b/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs index 2a9a8bf33..b544a9dae 100644 --- a/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs +++ b/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs @@ -1,4 +1,4 @@ -use cyfs_base::BuckyResult; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::GroupConsensusBlock; pub struct OrderBlockMgr {} @@ -8,11 +8,24 @@ impl OrderBlockMgr { Self {} } - pub async fn push_block(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + pub fn sync_with_height(&self, min_height: u64, remote: ObjectId) -> BuckyResult<()> { unimplemented!() } - pub async fn pop_link(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + pub fn sync_with_round(&self, min_round: u64, remote: ObjectId) -> BuckyResult<()> { + unimplemented!() + } + + pub fn push_outorder_block( + &self, + block: &GroupConsensusBlock, + min_round: u64, + remote: ObjectId, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub fn pop_link_from(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { unimplemented!() } } diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs index 075bf5d1f..83f10275c 100644 --- a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -9,13 +9,14 @@ use crate::AsProposal; pub enum ProposalConsumeMessage { Query(Sender>), - Wait(Sender, u64), + Wait(Sender<()>), Remove(Vec), } pub struct PendingProposalMgr { rx_product: Receiver, rx_consume: Receiver, + tx_proposal_waker: Option>, network_sender: crate::network::Sender, // TODO: 需要设计一个结构便于按时间或数量拆分 @@ -34,6 +35,7 @@ impl PendingProposalMgr { rx_consume, buffer: HashMap::new(), network_sender, + tx_proposal_waker: None, } .run() .await @@ -81,6 +83,9 @@ impl PendingProposalMgr { proposal = self.rx_product.recv().fuse() => { if let Ok(proposal) = proposal { self.buffer.insert(proposal.id(), proposal); + if let Some(waker) = self.tx_proposal_waker.take() { + waker.send(()).await; + } } }, message = self.rx_consume.recv().fuse() => { @@ -95,11 +100,11 @@ impl PendingProposalMgr { self.buffer.remove(id); } }, - ProposalConsumeMessage::Wait(tx_waker, round) => { + ProposalConsumeMessage::Wait(tx_waker) => { if self.buffer.len() > 0 { - tx_waker.send(round).await + tx_waker.send(()).await; } else { - self. + self.tx_proposal_waker = Some(tx_waker) } } } diff --git a/src/component/cyfs-group/src/consensus/timer.rs b/src/component/cyfs-group/src/consensus/timer.rs index 226578d13..2cef90de6 100644 --- a/src/component/cyfs-group/src/consensus/timer.rs +++ b/src/component/cyfs-group/src/consensus/timer.rs @@ -4,7 +4,8 @@ use std::task::{Context, Poll}; use std::time::Duration; pub struct Timer { - sleep: Pin>>, + sleep: Option>>>, + duration: u64, } impl Timer { @@ -16,24 +17,26 @@ impl Timer { ) .await; }); - Self { sleep } + Self { + sleep: Some(sleep), + duration, + } } pub fn reset(&mut self, duration: u64) { - self.sleep = Box::pin(async { + let sleep = Box::pin(async { async_std::future::timeout( Duration::from_millis(duration), std::future::pending::<()>(), ) .await; }); + self.duration = duration; + self.sleep = Some(sleep); } -} - -impl Future for Timer { - type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { - self.sleep.as_mut().poll(cx) + pub async fn wait_next(&mut self) { + self.sleep.take().unwrap().await; + self.reset(self.duration); } } diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index 53dd6abeb..a099d3c55 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -12,6 +12,7 @@ pub enum BlockLinkState { HashMap, ), // Pending, + InvalidBranch, } pub struct Storage { @@ -166,4 +167,23 @@ impl Storage { ) -> BuckyResult { unimplemented!() } + + pub fn block_with_max_round(&self) -> Option { + let mut max_round = 0; + let mut max_block = None; + for block in self.prepares().values() { + if block.round() > max_round { + max_round = block.round(); + max_block = Some(block); + } + } + + for block in self.pre_commits().values() { + if block.round() > max_round { + max_round = block.round(); + max_block = Some(block); + } + } + max_block.map(|block| block.clone()) + } } From 271b007921c80d028066763c9315d4f488537335 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 5 Jan 2023 19:58:01 +0800 Subject: [PATCH 011/553] init --- .../src/consensus/hotstuff/hotstuff.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7e4b32f1d..6c027c6bb 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -14,7 +14,7 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{order_block::OrderBlockMgr, proposal, timer::Timer}, + consensus::{order_block::OrderBlockMgr, timer::Timer}, AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, @@ -43,7 +43,8 @@ pub struct Hotstuff { } impl Hotstuff { - pub fn spawn( + #[allow(clippy::too_many_arguments)] + pub async fn spawn( local_id: ObjectId, committee: Committee, store: Storage, @@ -65,15 +66,16 @@ impl Hotstuff { let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); let vote_mgr = VoteMgr::new(committee.clone(), round); + let init_timer_interval = store.group().consensus_interval(); - let obj = Self { + let mut hotstuff = Self { local_id, committee, store, signer, round, high_qc, - timer: Timer::new(store.group().consensus_interval()), + timer: Timer::new(init_timer_interval), vote_mgr, network_sender, rx_message, @@ -87,6 +89,8 @@ impl Hotstuff { rx_proposal_waiter: None, tc: None, }; + + async_std::task::spawn(async move { hotstuff.run().await }); } // TODO: 网络层应该防御,只从当前group节点获取信息 @@ -226,7 +230,7 @@ impl Hotstuff { } async fn check_block_proposal_result_state_by_app( - &self, + &mut self, block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, @@ -769,7 +773,7 @@ impl Hotstuff { Ok(()) } - async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { + async fn broadcast(&mut self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { let targets: Vec = group .ood_list() .iter() @@ -822,7 +826,7 @@ impl Hotstuff { will_wait_proposals } - async fn fetch_block(&self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { + async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { let block = self.non_driver.get_block(block_id, Some(&remote)).await?; self.tx_message_inner.send((block, remote)).await; From 18fbeaa8a59bad06b6f9d55ec05046d16abf9fd7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 5 Jan 2023 20:15:37 +0800 Subject: [PATCH 012/553] send + sync --- .../cyfs-group/src/consensus/hotstuff/hotstuff.rs | 8 ++++---- src/component/cyfs-group/src/consensus/timer.rs | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 6c027c6bb..bab4f19d1 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -58,10 +58,10 @@ impl Hotstuff { ) { let max_round_block = store.block_with_max_round(); - let mut round = store + let round = store .last_vote_round() .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let mut high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -230,7 +230,7 @@ impl Hotstuff { } async fn check_block_proposal_result_state_by_app( - &mut self, + &self, block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, @@ -773,7 +773,7 @@ impl Hotstuff { Ok(()) } - async fn broadcast(&mut self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { + async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { let targets: Vec = group .ood_list() .iter() diff --git a/src/component/cyfs-group/src/consensus/timer.rs b/src/component/cyfs-group/src/consensus/timer.rs index 2cef90de6..57230ccb7 100644 --- a/src/component/cyfs-group/src/consensus/timer.rs +++ b/src/component/cyfs-group/src/consensus/timer.rs @@ -1,10 +1,9 @@ use std::future::Future; use std::pin::Pin; -use std::task::{Context, Poll}; use std::time::Duration; pub struct Timer { - sleep: Option>>>, + sleep: Option>>>, duration: u64, } From a1d8d6a2593aee1b50dc34fd6dc342e7a1c64629 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 6 Jan 2023 16:10:31 +0800 Subject: [PATCH 013/553] discard the block from devices not included in the latest group --- src/component/cyfs-base/src/objects/group.rs | 98 ++++++++++++------- .../src/consensus/hotstuff/hotstuff.rs | 35 +++++-- 2 files changed, 86 insertions(+), 47 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 1cab779e3..632984754 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -54,11 +54,11 @@ impl GroupBodyContent { &mut self.common_mut().members } - pub fn ood_list(&self) -> &Vec { + pub fn ood_list(&self) -> &Vec { &self.common().ood_list } - pub fn ood_list_mut(&mut self) -> &mut Vec { + pub fn ood_list_mut(&mut self) -> &mut Vec { &mut self.common_mut().ood_list } @@ -172,14 +172,36 @@ impl Group { self.common_mut().members = members; } - pub fn ood_list(&self) -> &[DeviceId] { + pub fn ood_list(&self) -> &[ObjectId] { self.common().ood_list.as_slice() } - pub fn set_ood_list(&mut self, oods: Vec) { + pub fn set_ood_list(&mut self, oods: Vec) { self.common_mut().ood_list = oods; } + pub fn contain_ood(&self, ood_id: &ObjectId) -> bool { + self.ood_list().contains(ood_id) + } + + pub fn is_same_ood_list(&self, other: &Group) -> bool { + let my_oods = self.ood_list(); + let other_oods = other.ood_list(); + + for id in my_oods { + if !other_oods.contains(id) { + return false; + } + } + + for id in other_oods { + if !my_oods.contains(id) { + return false; + } + } + true + } + pub fn version(&self) -> u64 { self.common().version } @@ -196,39 +218,39 @@ impl Group { self.common_mut().consensus_interval = interval; } - pub fn join_member( - &self, - member_id: &ObjectId, - private_key: &PrivateKey, - ) -> BuckyResult<&GroupJoinSignature> { - unimplemented!() - } + // pub fn join_member( + // &self, + // member_id: &ObjectId, + // private_key: &PrivateKey, + // ) -> BuckyResult<&GroupJoinSignature> { + // unimplemented!() + // } - pub fn verify( - &self, - signature: &GroupJoinSignature, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult { - unimplemented!() - } + // pub fn verify( + // &self, + // signature: &GroupJoinSignature, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult { + // unimplemented!() + // } - pub fn verify_member( - &self, - member_id: &ObjectId, - is_admin: bool, - public_key: &PublicKey, - ) -> BuckyResult { - unimplemented!() - } + // pub fn verify_member( + // &self, + // member_id: &ObjectId, + // is_admin: bool, + // public_key: &PublicKey, + // ) -> BuckyResult { + // unimplemented!() + // } - pub fn verify_members( - &self, - members: &[(ObjectId, PublicKey)], - is_admin: bool, - ) -> BuckyResult { - unimplemented!() - } + // pub fn verify_members( + // &self, + // members: &[(ObjectId, PublicKey)], + // is_admin: bool, + // ) -> BuckyResult { + // unimplemented!() + // } pub fn is_simple_group(&self) -> bool { match self.desc().content() { @@ -522,7 +544,7 @@ struct CommonGroupBodyContent { role_acls: Vec, - ood_list: Vec, + ood_list: Vec, history_block_max: u64, history_block_lifespan: u64, @@ -539,7 +561,7 @@ impl CommonGroupBodyContent { icon: Option, description: String, members: Vec, - ood_list: Vec, + ood_list: Vec, ) -> Self { Self { name, @@ -686,7 +708,7 @@ impl SimpleGroupBodyContent { icon: Option, description: String, members: Vec, - ood_list: Vec, + ood_list: Vec, ) -> Self { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), @@ -764,7 +786,7 @@ impl OrgBodyContent { description: String, admins: Vec, members: Vec, - ood_list: Vec, + ood_list: Vec, ) -> Self { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index bab4f19d1..691291f93 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -93,12 +93,21 @@ impl Hotstuff { async_std::task::spawn(async move { hotstuff.run().await }); } - // TODO: 网络层应该防御,只从当前group节点获取信息 async fn handle_block( &mut self, block: &GroupConsensusBlock, remote: ObjectId, ) -> BuckyResult<()> { + let latest_group = self.committee.get_group(None).await?; + if !latest_group.contain_ood(&remote) { + log::warn!( + "receive block({}) from unknown({})", + block.named_object().desc().object_id(), + remote + ); + return Ok(()); + } + /** * 1. 验证block投票签名 * 2. 验证出块节点 @@ -322,10 +331,7 @@ impl Hotstuff { } if let Some(vote) = self.make_vote(block).await { - let next_leader = self - .committee - .get_leader(Some(block.group_chunk_id()), self.round + 1) - .await?; + let next_leader = self.committee.get_leader(None, self.round + 1).await?; if self.local_id == next_leader { self.handle_vote(&vote, Some(block), remote).await?; @@ -839,21 +845,32 @@ impl Hotstuff { let max_round_block = self.store.block_with_max_round(); let group_chunk_id = max_round_block.as_ref().map(|block| block.group_chunk_id()); let last_group = self.committee.get_group(group_chunk_id).await; + let latest_group = match group_chunk_id.as_ref() { + Some(_) => self.committee.get_group(None).await, + None => last_group.clone(), + }; - let duration = last_group + let duration = latest_group .as_ref() .map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| g.consensus_interval()); self.timer.reset(duration); - if let Ok(leader) = self.committee.get_leader(group_chunk_id, self.round).await { + if let Ok(leader) = self.committee.get_leader(None, self.round).await { if leader == self.local_id { match max_round_block { Some(max_round_block) - if max_round_block.owner() == &self.local_id && last_group.is_ok() => + if max_round_block.owner() == &self.local_id + && latest_group.is_ok() + && last_group.is_ok() + && last_group + .as_ref() + .unwrap() + .is_same_ood_list(latest_group.as_ref().unwrap()) => { + // discard the generated block when the ood-list is changed self.broadcast( HotstuffMessage::Block(max_round_block), - &last_group.unwrap(), + &latest_group.unwrap(), ) .await; } From a5d7ec70c7ce7495dda807a05f353f095db9dd12 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 6 Jan 2023 16:16:43 +0800 Subject: [PATCH 014/553] note --- src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 691291f93..2b131df29 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -665,6 +665,7 @@ impl Hotstuff { None => self.store.dec_state_id(), }; + // TODO: The time may be too long for too many proposals for proposal in proposals { if let Some(high_qc) = self.high_qc.as_ref() { if let Ok(is_finished) = self From 02ede387c1c92d3f892912b113a741863af0e77b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 6 Jan 2023 16:46:46 +0800 Subject: [PATCH 015/553] rename order-block to synchronizer --- .../src/consensus/hotstuff/hotstuff.rs | 16 +++++++++------- src/component/cyfs-group/src/consensus/mod.rs | 2 +- .../src/consensus/order_block/mod.rs | 3 --- .../src/consensus/synchronizer/mod.rs | 3 +++ .../synchronizer.rs} | 18 ++++++++++++++---- .../cyfs-group/src/objects/protocol.rs | 3 +++ .../cyfs-group/src/statepath/design.md | 1 - 7 files changed, 30 insertions(+), 16 deletions(-) delete mode 100644 src/component/cyfs-group/src/consensus/order_block/mod.rs create mode 100644 src/component/cyfs-group/src/consensus/synchronizer/mod.rs rename src/component/cyfs-group/src/consensus/{order_block/order_block_mgr.rs => synchronizer/synchronizer.rs} (59%) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 2b131df29..ece9e446a 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -14,7 +14,7 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{order_block::OrderBlockMgr, timer::Timer}, + consensus::{synchronizer::Synchronizer, timer::Timer}, AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, @@ -35,7 +35,7 @@ pub struct Hotstuff { rx_message: Receiver<(HotstuffMessage, ObjectId)>, tx_proposal_consume: Sender, delegate: Arc>, - order_block_mgr: OrderBlockMgr, + synchronizer: Synchronizer, rpath: GroupRPath, tx_message_inner: Sender<(GroupConsensusBlock, ObjectId)>, rx_message_inner: Receiver<(GroupConsensusBlock, ObjectId)>, @@ -80,7 +80,7 @@ impl Hotstuff { network_sender, rx_message, delegate, - order_block_mgr: OrderBlockMgr::new(), + synchronizer: Synchronizer::new(), non_driver, rpath, tx_proposal_consume, @@ -165,7 +165,7 @@ impl Hotstuff { } let max_round_block = self.store.block_with_max_round(); - return self.order_block_mgr.push_outorder_block( + return self.synchronizer.push_outorder_block( block, max_round_block.map_or(1, |block| block.round() + 1), remote, @@ -183,7 +183,7 @@ impl Hotstuff { self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) .await?; - self.order_block_mgr.pop_link_from(block)?; + self.synchronizer.pop_link_from(block)?; self.process_qc(block.qc()).await; @@ -574,8 +574,9 @@ impl Hotstuff { Err(_) => { // 同步前序block let max_round_block = self.store.block_with_max_round(); - return self.order_block_mgr.sync_with_round( + return self.synchronizer.sync_with_round( max_round_block.map_or(1, |block| block.round() + 1), + max_high_qc.high_qc_round, remote, ); } @@ -910,7 +911,8 @@ impl Hotstuff { Err(e) => { log::warn!("[hotstuff] rx_message closed."); Ok(()) - } + }, + _ => panic!("unknown message") }, message = self.rx_message_inner.recv().fuse() => match message { Ok((block, remote)) => { diff --git a/src/component/cyfs-group/src/consensus/mod.rs b/src/component/cyfs-group/src/consensus/mod.rs index 0f41c0ff3..f8ba322dc 100644 --- a/src/component/cyfs-group/src/consensus/mod.rs +++ b/src/component/cyfs-group/src/consensus/mod.rs @@ -1,7 +1,7 @@ mod block; mod consensus; mod hotstuff; -mod order_block; +mod synchronizer; mod proposal; mod timer; mod vote; diff --git a/src/component/cyfs-group/src/consensus/order_block/mod.rs b/src/component/cyfs-group/src/consensus/order_block/mod.rs deleted file mode 100644 index 12d837386..000000000 --- a/src/component/cyfs-group/src/consensus/order_block/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod order_block_mgr; - -pub use order_block_mgr::*; \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/synchronizer/mod.rs b/src/component/cyfs-group/src/consensus/synchronizer/mod.rs new file mode 100644 index 000000000..2fa7f37ba --- /dev/null +++ b/src/component/cyfs-group/src/consensus/synchronizer/mod.rs @@ -0,0 +1,3 @@ +mod synchronizer; + +pub use synchronizer::*; \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs similarity index 59% rename from src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs rename to src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index b544a9dae..63b27ce12 100644 --- a/src/component/cyfs-group/src/consensus/order_block/order_block_mgr.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -1,18 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::GroupConsensusBlock; -pub struct OrderBlockMgr {} +pub struct Synchronizer {} -impl OrderBlockMgr { +impl Synchronizer { pub fn new() -> Self { Self {} } - pub fn sync_with_height(&self, min_height: u64, remote: ObjectId) -> BuckyResult<()> { + pub fn sync_with_height( + &self, + min_height: u64, + max_height: u64, + remote: ObjectId, + ) -> BuckyResult<()> { unimplemented!() } - pub fn sync_with_round(&self, min_round: u64, remote: ObjectId) -> BuckyResult<()> { + pub fn sync_with_round( + &self, + min_round: u64, + max_round: u64, + remote: ObjectId, + ) -> BuckyResult<()> { unimplemented!() } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 2d5cbcd0a..0b8d7fdab 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -13,6 +13,9 @@ pub(crate) enum HotstuffMessage { BlockVote(HotstuffBlockQCVote), TimeoutVote(HotstuffTimeoutVote), Timeout(cyfs_core::HotstuffTimeout), + + SyncWithHeight(u64, u64), + SyncWithRound(u64, u64), } #[derive(Clone, RawEncode, RawDecode)] diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index c0fb7c6be..6143d36bc 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -40,7 +40,6 @@ | |--pre-commits // pre-commit状态的block | | |--${block.id} | | |--block -| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 From 336d6dfbbed12c66773eb98c997eaac17be516de Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 6 Jan 2023 17:07:46 +0800 Subject: [PATCH 016/553] leader for latest-group --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++---------------- .../consensus/synchronizer/synchronizer.rs | 17 ++++++++++- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ece9e446a..97ff1cdc2 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -80,7 +80,7 @@ impl Hotstuff { network_sender, rx_message, delegate, - synchronizer: Synchronizer::new(), + synchronizer: Synchronizer::spawn(network_sender.clone(), rpath.clone(), rx_message), non_driver, rpath, tx_proposal_consume, @@ -469,12 +469,7 @@ impl Hotstuff { ) -> BuckyResult<()> { self.process_qc(&Some(qc)).await; - if self.local_id - == self - .committee - .get_leader(Some(block.group_chunk_id()), self.round) - .await? - { + if self.local_id == self.committee.get_leader(None, self.round).await? { self.generate_proposal(None).await; } Ok(()) @@ -528,15 +523,7 @@ impl Hotstuff { self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - if self.local_id - == self - .committee - .get_leader( - max_high_qc_block.map(|block| block.group_chunk_id()), - self.round, - ) - .await? - { + if self.local_id == self.committee.get_leader(None, self.round).await? { self.generate_proposal(Some(tc)).await; Ok(()) } else { @@ -589,15 +576,7 @@ impl Hotstuff { self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - if self.local_id - == self - .committee - .get_leader( - block.as_ref().map(|block| block.group_chunk_id()), - self.round, - ) - .await? - { + if self.local_id == self.committee.get_leader(None, self.round).await? { self.generate_proposal(Some(tc.clone())).await; } Ok(()) diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 63b27ce12..4ab6fde41 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -4,7 +4,11 @@ use cyfs_core::GroupConsensusBlock; pub struct Synchronizer {} impl Synchronizer { - pub fn new() -> Self { + pub fn spawn( + network_sender: crate::network::Sender, + rpath: GroupRPath, + rx_message: Receiver<(HotstuffMessage, ObjectId)>, + ) -> Self { Self {} } @@ -39,3 +43,14 @@ impl Synchronizer { unimplemented!() } } + + +struct SynchronizerRunner { + +} + +impl SynchronizerRunner { + async fn run(&mut self) { + + } +} \ No newline at end of file From 0aff125eaa10cb85e74499dfdd0af08651433240 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 6 Jan 2023 17:11:03 +0800 Subject: [PATCH 017/553] note --- src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 97ff1cdc2..911aaac56 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -20,6 +20,10 @@ use crate::{ VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; +/** + * TODO: generate empty block when the 'Node' is synchronizing +*/ + pub struct Hotstuff { local_id: ObjectId, committee: Committee, From 2b57916d32fccc97671382ec7d4da13851031ffb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 7 Jan 2023 20:50:41 +0800 Subject: [PATCH 018/553] synchronizer --- .../src/consensus/hotstuff/hotstuff.rs | 6 +- .../consensus/synchronizer/synchronizer.rs | 496 +++++++++++++++++- src/component/cyfs-group/src/constant.rs | 1 + 3 files changed, 492 insertions(+), 11 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 911aaac56..160788fc1 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -170,8 +170,8 @@ impl Hotstuff { let max_round_block = self.store.block_with_max_round(); return self.synchronizer.push_outorder_block( - block, - max_round_block.map_or(1, |block| block.round() + 1), + block.clone(), + max_round_block.map_or(1, |block| block.height() + 1), remote, ); } @@ -566,7 +566,7 @@ impl Hotstuff { // 同步前序block let max_round_block = self.store.block_with_max_round(); return self.synchronizer.sync_with_round( - max_round_block.map_or(1, |block| block.round() + 1), + max_round_block.map_or(1, |block| block.height() + 1), max_high_qc.high_qc_round, remote, ); diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 4ab6fde41..01ad052d9 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -1,5 +1,76 @@ -use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::Instant, + vec, +}; + +use async_std::channel::{Receiver, Sender}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject}; + +use crate::{consensus::timer::Timer, HotstuffMessage, SYNCHRONIZER_TIMEOUT}; + +enum SyncMaxBound { + Height(u64), + Round(u64), +} + +impl SyncMaxBound { + fn value(&self) -> u64 { + match self { + Self::Height(h) => h, + Self::Round(r) => r, + } + } + + fn add(&self, value: u64) -> Self { + match self { + Self::Height(h) => Self::Height(*h + value), + Self::Round(r) => Self::Round(*r + value), + } + } + + fn sub(&self, value: u64) -> Self { + match self { + Self::Height(h) => Self::Height(*h - value), + Self::Round(r) => Self::Round(*r - value), + } + } +} + +impl Ord for SyncMaxBound { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match self { + Self::Height(height) => match other { + Self::Height(other_height) => height.cmp(other_height), + Self::Round(other_round) => { + if height >= other_round { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Less + } + } + }, + Self::Round(round) => match other { + Self::Round(other_round) => round.cmp(other_round), + Self::Height(other_height) => { + if other_height >= round { + std::cmp::Ordering::Less + } else { + std::cmp::Ordering::Greater + } + } + }, + } + } +} + +enum SynchronizerMessage { + Sync(u64, SyncMaxBound, ObjectId), // ([min-height, max-bound], remote) + PushBlock(u64, GroupConsensusBlock, ObjectId), // (min-height, block, remote) + PopBlock(u64, u64, ObjectId), // (new-height, new-round, blockid) +} pub struct Synchronizer {} @@ -7,7 +78,9 @@ impl Synchronizer { pub fn spawn( network_sender: crate::network::Sender, rpath: GroupRPath, - rx_message: Receiver<(HotstuffMessage, ObjectId)>, + height: u64, + round: u64, + tx_block: Sender<(HotstuffMessage, ObjectId)>, ) -> Self { Self {} } @@ -18,12 +91,15 @@ impl Synchronizer { max_height: u64, remote: ObjectId, ) -> BuckyResult<()> { + if min_height > max_height { + return Ok(()); + } unimplemented!() } pub fn sync_with_round( &self, - min_round: u64, + min_height: u64, max_round: u64, remote: ObjectId, ) -> BuckyResult<()> { @@ -32,8 +108,8 @@ impl Synchronizer { pub fn push_outorder_block( &self, - block: &GroupConsensusBlock, - min_round: u64, + block: GroupConsensusBlock, + min_height: u64, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() @@ -44,13 +120,417 @@ impl Synchronizer { } } +#[derive(Clone)] +struct ResendInfo { + last_send_time: Instant, + send_times: usize, + cmd: Arc<(u64, SyncMaxBound, ObjectId)>, +} + +#[derive(Clone)] +struct RequestSendInfo { + min_bound: SyncMaxBound, + max_bound: SyncMaxBound, + + resends: Vec, +} + +impl RequestSendInfo { + fn new( + min_bound: SyncMaxBound, + max_bound: SyncMaxBound, + req: Arc<(u64, SyncMaxBound, ObjectId)>, + ) -> Self { + RequestSendInfo { + min_bound, + max_bound: max_bound, + resends: vec![ResendInfo { + last_send_time: Instant::now(), + send_times: 1, + cmd: req, + }], + } + } + + fn splite(&mut self, bound: SyncMaxBound) -> Option { + match bound.cmp(&self.max_bound) { + std::cmp::Ordering::Greater => None, + _ => match bound.cmp(&self.min_bound) { + std::cmp::Ordering::Greater => { + self.max_bound = bound.sub(1); + Some(Self { + min_bound: bound, + max_bound: self.max_bound, + resends: self.resends.clone(), + }) + } + _ => None, + }, + } + } + + fn try_send(&mut self) { + // todo 选send次数最少,间隔最长的发送一次 + } + + fn is_valid(&self) -> bool { + if let std::cmp::Ordering::Greater = self.min_bound.cmp(&self.max_bound) { + false + } else { + true + } + } +} struct SynchronizerRunner { + network_sender: crate::network::Sender, + rpath: GroupRPath, + tx_block: Sender<(HotstuffMessage, ObjectId)>, + rx_message: Receiver<(HotstuffMessage, ObjectId)>, + timer: Timer, + height: u64, + round: u64, + sync_requests: Vec, // order by min_bound + out_order_blocks: Vec<(GroupConsensusBlock, ObjectId)>, // Vec<(block, remote)> } impl SynchronizerRunner { + fn new( + network_sender: crate::network::Sender, + rpath: GroupRPath, + tx_block: Sender<(HotstuffMessage, ObjectId)>, + rx_message: Receiver, + height: u64, + round: u64, + ) -> Self { + Self { + network_sender, + rpath, + rx_message, + timer: Timer::new(SYNCHRONIZER_TIMEOUT), + height, + round, + sync_requests: vec![], + out_order_blocks: vec![], + tx_block, + } + } + + async fn handle_sync(&mut self, min_height: u64, max_bound: SyncMaxBound, remote: ObjectId) { + let min_height = min_height.max(self.height + 1); + let max_bound = match max_bound { + SyncMaxBound::Height(height) => SyncMaxBound::Height(height.max(self.height + 1)), + SyncMaxBound::Round(round) => SyncMaxBound::Round(round.max(self.round + 1)), + }; + + let requests: Vec> = self + .filter_outorder_blocks(min_height, max_bound) + .into_iter() + .map(|req| Arc::new((req.0, req.1, remote))) + .collect(); + + // combine requests + let mut pos = 0; + for req in requests { + let mut range = (SyncMaxBound::Height(req.0), req.1); + while range.0 <= range.1 { + while pos < self.sync_requests.len() { + let req1 = self.sync_requests.get_mut(pos).unwrap(); + match range.0.cmp(&req1.min_bound) { + std::cmp::Ordering::Less => { + let max_bound = match range.1.cmp(&req1.min_bound) { + std::cmp::Ordering::Less => range.1, + _ => req1.min_bound.sub(1), + }; + + let new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); + new_req.try_send(); + self.sync_requests.insert(i, new_req); + range.0 = max_bound.value() + 1; + } + std::cmp::Ordering::Equal => { + match range.1.cmp(&req1.max_bound) { + std::cmp::Ordering::Greater => { + range.0 = req1.max_bound.add(1); + } + _ => { + range.0 = range.1.add(1); + let cut = req1.splite(range.0); + assert!(req1.is_valid()); + if let Some(cut) = cut { + self.sync_requests.insert(i + 1, cut); + } + } + }; + req1.resends.push(ResendInfo { + last_send_time: 0, + send_times: 0, + cmd: req.clone(), + }); + } + std::cmp::Ordering::Greater => match range.0.cmp(&req1.max_bound) { + std::cmp::Ordering::Greater => {} + _ => { + let cut = req1.splite(range.0); + assert!(req1.is_valid()); + if let Some(cut) = cut { + self.sync_requests.insert(i + 1, cut); + } + } + }, + } + pos += 1; + + if range.0 > range.1 { + break; + } + } + + if pos == self.sync_requests.len() { + if range.0 <= range.1 { + let new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); + new_req.try_send(); + self.sync_requests.push(new_req); + pos += 1; + } + break; + } + } + } + } + + fn filter_outorder_blocks( + &self, + mut min_height: u64, + mut max_bound: SyncMaxBound, + ) -> Vec<(u64, SyncMaxBound)> { + let mut last_range = Some((SyncMaxBound::Height(min_height), max_bound)); + let mut requests = vec![]; + for (block, _) in self.out_order_blocks.as_slice() { + match last_range { + Some(range) => { + let (range1, range2) = + Self::splite_range_with_block(range, block.height(), block.round()); + if let Some(range1) = range1 { + requests.push(range1); + } + last_range = range2; + } + None => break, + } + } + + if let Some(last_range) = last_range { + requests.push(last_range); + } + + requests + } + + fn splite_range_with_block( + mut range: (SyncMaxBound, SyncMaxBound), + height: u64, + round: u64, + ) -> ( + Option<(SyncMaxBound, SyncMaxBound)>, + Option<(SyncMaxBound, SyncMaxBound)>, + ) { + let min_ord = match range.0 { + SyncMaxBound::Height(height) => height.cmp(&height), + SyncMaxBound::Round(round) => round.cmp(&round), + }; + + match min_ord { + std::cmp::Ordering::Less => (None, Some((range.0, range.1))), + std::cmp::Ordering::Equal => { + range.0 = range.0.add(1); + match range.0.cmp(&range.1) { + std::cmp::Ordering::Greater => (None, None), + _ => (None, Some((range.0, range.1))), + } + } + std::cmp::Ordering::Greater => { + let ord = match range.1 { + SyncMaxBound::Height(height) => height.cmp(&height), + SyncMaxBound::Round(round) => round.cmp(&round), + }; + + match ord { + std::cmp::Ordering::Less => ( + Some((range.0, SyncMaxBound::Height(height - 1))), + Some((SyncMaxBound::Height(height + 1), range.1)), + ), + std::cmp::Ordering::Equal => { + (Some((range.0, SyncMaxBound::Height(height - 1))), None) + } + std::cmp::Ordering::Greater => (Some((range.0, range.1)), None), + } + } + } + } + + async fn handle_push_block( + &mut self, + min_height: u64, + block: GroupConsensusBlock, + remote: ObjectId, + ) { + if block.round() <= self.round { + return; + } + + if min_height >= block.height() { + return; + } + + let pos = self.out_order_blocks.binary_search_by(|(block0, _)| { + let ord = block0.height().cmp(&block.height()); + if let std::cmp::Ordering::Equal = ord { + block0.round().cmp(&block.round()) + } else { + ord + } + }); + + match pos { + Ok(_) => return, + Err(pos) => self.out_order_blocks.insert(pos, (block, remote)), + }; + + self.timer.reset(SYNCHRONIZER_TIMEOUT); + + for i in 0..self.sync_requests.len() { + let req = self.sync_requests.get_mut(i).unwrap(); + let (range1, range2) = Self::splite_range_with_block( + (req.min_bound, req.max_bound), + block.height(), + block.round(), + ); + match range1 { + Some(range1) => { + req.max_bound = range1.1; + if let Some(range2) = range2 { + let mut new_req = req.clone(); + new_req.min_bound = range2.0; + new_req.max_bound = range2.1; + self.sync_requests.insert(i + 1, new_req); + break; + } + } + None => { + match range2 { + Some(range2) => req.min_bound = range2.0, + None => self.sync_requests.remove(i), + } + break; + } + } + } + + self.handle_sync(min_height, SyncMaxBound::Height(block.height()), remote) + .await; + } + + async fn handle_pop_block(&mut self, new_height: u64, new_round: u64, block_id: ObjectId) { + if new_round <= self.round { + return; + } + + self.timer.reset(SYNCHRONIZER_TIMEOUT); + + let mut max_height = self.height.max(&new_height); + let mut max_round = new_round; + + let mut remove_block_ids = HashSet::from(&[block_id]); + + let mut remove_pos = None; + + for pos in 0..self.out_order_blocks.len() { + let (block, remote) = self.out_order_blocks.get(pos).unwrap(); + + let block_id_out = block.named_object().desc().object_id(); + if remove_block_ids.contains(&block.prev_block_id()) || block_id_out == block_id { + remove_block_ids.insert(block_id_out); + remove_pos = Some(pos); + max_height = max_height.max(block.height()); + max_round = max_round.max(block.round()); + } else if block.height() > max_height && block.round() > max_round { + break; + } + } + + let order_blocks = match remove_pos { + Some(remove_pos) => self + .out_order_blocks + .splice(0..(remove_pos + 1), []) + .collect(), + None => vec![], + }; + + self.height = max_height; + self.round = max_round; + + let mut remove_request_pos = None; + for pos in 0..self.sync_requests.len() { + let req = self.sync_requests.get_mut(pos).unwrap(); + let (first, second) = Self::splite_range_with_block( + (req.min_bound, req.max_bound), + self.height, + self.round, + ); + match first { + Some(first) => { + remove_request_pos = Some(pos); + req.max_bound = first.1; + if let Some(second) = second { + let mut new_req = req.clone(); + new_req.min_bound = second.0; + new_req.max_bound = second.1; + self.sync_requests.insert(pos + 1, new_req); + break; + } + } + None => { + if let Some(second) = second { + req.min_bound = second.0; + } + break; + } + }; + } + + if let Some(remove_request_pos) = remove_request_pos { + self.sync_requests.splice(0..(pos + 1), []); + } + + futures::future::join_all(order_blocks.into_iter().map(|(order_block, remote)| { + self.tx_block + .send((HotstuffMessage::Block(order_block), remote)) + })) + .await; + } + + async fn handle_timeout(&mut self) { + for req in self.sync_requests.iter() { + req.try_send(); + } + } + async fn run(&mut self) { - + loop { + futures::select! { + message = self.rx_message.recv().fuse() => match message { + Ok(SynchronizerMessage::Sync(min_height, max_bound, remote)) => self.handle_sync(min_height, max_bound, remote).await, + Ok(SynchronizerMessage::PushBlock(min_height, block, remote)) => self.handle_push_block(min_height, block, remote).await, + Ok(SynchronizerMessage::PopBlock(new_height, new_round, block_id)) => self.handle_pop_block(new_height, new_round, block_id).await, + Err(e) => { + log::warn!("[synchronizer] rx_message closed."); + Ok(()) + }, + }, + () = self.timer.wait_next().fuse() => self.handle_timeout().await, + }; + } } -} \ No newline at end of file +} diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 79aa0694e..b02e9866e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,3 +14,4 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const SYNCHRONIZER_TIMEOUT: u64 = 500; From 5468a9ac9e19573dc60813a41a16ee44a49bf58c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 9 Jan 2023 20:26:48 +0800 Subject: [PATCH 019/553] synchronizer responce --- .../src/consensus/hotstuff/hotstuff.rs | 20 +- .../consensus/synchronizer/synchronizer.rs | 334 ++++++++++++++---- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/network/sender.rs | 1 + .../cyfs-group/src/objects/protocol.rs | 9 +- .../cyfs-group/src/storage/storage.rs | 6 +- 6 files changed, 294 insertions(+), 77 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 160788fc1..e6172ffc8 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -71,6 +71,7 @@ impl Hotstuff { let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); + let max_height = store.header_height() + 2; let mut hotstuff = Self { local_id, @@ -84,7 +85,13 @@ impl Hotstuff { network_sender, rx_message, delegate, - synchronizer: Synchronizer::spawn(network_sender.clone(), rpath.clone(), rx_message), + synchronizer: Synchronizer::spawn( + network_sender.clone(), + rpath.clone(), + max_height, + round, + rx_message, + ), non_driver, rpath, tx_proposal_consume, @@ -169,11 +176,13 @@ impl Hotstuff { } let max_round_block = self.store.block_with_max_round(); - return self.synchronizer.push_outorder_block( + self.synchronizer.push_outorder_block( block.clone(), max_round_block.map_or(1, |block| block.height() + 1), remote, ); + + return Ok(()); } crate::storage::BlockLinkState::InvalidBranch => { log::warn!("receive block in invalid branch."); @@ -565,11 +574,12 @@ impl Hotstuff { Err(_) => { // 同步前序block let max_round_block = self.store.block_with_max_round(); - return self.synchronizer.sync_with_round( + self.synchronizer.sync_with_round( max_round_block.map_or(1, |block| block.height() + 1), max_high_qc.high_qc_round, remote, ); + return Ok(()); } }; Some(block) @@ -879,7 +889,7 @@ impl Hotstuff { } } - async fn run(&mut self) { + async fn run(&mut self) -> ! { self.recover().await; // This is the main loop: it processes incoming blocks and votes, @@ -895,7 +905,7 @@ impl Hotstuff { log::warn!("[hotstuff] rx_message closed."); Ok(()) }, - _ => panic!("unknown message") + Ok((HotstuffMessage::SyncRequest((min_bound, max_bound)), remote)) => self.synchronizer.process_sync_request(min_bound, max_bound, remote, &self.store).await }, message = self.rx_message_inner.recv().fuse() => match message { Ok((block, remote)) => { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 01ad052d9..6c3ef4e11 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -7,16 +7,15 @@ use std::{ use async_std::channel::{Receiver, Sender}; use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use protobuf::well_known_types::Duration; -use crate::{consensus::timer::Timer, HotstuffMessage, SYNCHRONIZER_TIMEOUT}; - -enum SyncMaxBound { - Height(u64), - Round(u64), -} +use crate::{ + consensus::timer::Timer, storage::Storage, HotstuffMessage, SyncBound, CHANNEL_CAPACITY, + SYNCHRONIZER_TIMEOUT, SYNCHRONIZER_TRY_TIMES, +}; -impl SyncMaxBound { +impl SyncBound { fn value(&self) -> u64 { match self { Self::Height(h) => h, @@ -39,7 +38,7 @@ impl SyncMaxBound { } } -impl Ord for SyncMaxBound { +impl Ord for SyncBound { fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self { Self::Height(height) => match other { @@ -67,12 +66,16 @@ impl Ord for SyncMaxBound { } enum SynchronizerMessage { - Sync(u64, SyncMaxBound, ObjectId), // ([min-height, max-bound], remote) + Sync(u64, SyncBound, ObjectId), // ([min-height, max-bound], remote) PushBlock(u64, GroupConsensusBlock, ObjectId), // (min-height, block, remote) - PopBlock(u64, u64, ObjectId), // (new-height, new-round, blockid) + PopBlock(u64, u64, ObjectId), // (new-height, new-round, blockid) } -pub struct Synchronizer {} +pub struct Synchronizer { + tx_sync_message: Sender, + network_sender: crate::network::Sender, + rpath: GroupRPath, +} impl Synchronizer { pub fn spawn( @@ -82,28 +85,57 @@ impl Synchronizer { round: u64, tx_block: Sender<(HotstuffMessage, ObjectId)>, ) -> Self { - Self {} + let (tx_sync_message, rx_sync_message) = async_std::channel::bounded(CHANNEL_CAPACITY); + let runner = SynchronizerRunner::new( + network_sender.clone(), + rpath.clone(), + tx_block, + rx_sync_message, + height, + round, + ); + + async_std::task::spawn(async move || runner.run().await); + + Self { + tx_sync_message, + network_sender, + rpath, + } } - pub fn sync_with_height( - &self, - min_height: u64, - max_height: u64, - remote: ObjectId, - ) -> BuckyResult<()> { + pub fn sync_with_height(&self, min_height: u64, max_height: u64, remote: ObjectId) { if min_height > max_height { return Ok(()); } - unimplemented!() + + let tx_sync_message = self.tx_sync_message.clone(); + async_std::task::spawn(async move || { + tx_sync_message + .send(SynchronizerMessage::Sync( + min_height, + SyncBound::Height(max_height), + remote, + )) + .await + }); } - pub fn sync_with_round( - &self, - min_height: u64, - max_round: u64, - remote: ObjectId, - ) -> BuckyResult<()> { - unimplemented!() + pub fn sync_with_round(&self, min_height: u64, max_round: u64, remote: ObjectId) { + if min_height > max_round { + return Ok(()); + } + + let tx_sync_message = self.tx_sync_message.clone(); + async_std::task::spawn(async move || { + tx_sync_message + .send(SynchronizerMessage::Sync( + min_height, + SyncBound::Round(max_round), + remote, + )) + .await + }); } pub fn push_outorder_block( @@ -111,12 +143,139 @@ impl Synchronizer { block: GroupConsensusBlock, min_height: u64, remote: ObjectId, - ) -> BuckyResult<()> { - unimplemented!() + ) { + let tx_sync_message = self.tx_sync_message.clone(); + async_std::task::spawn(async move || { + tx_sync_message + .send(SynchronizerMessage::PushBlock(min_height, block, remote)) + .await + }); + } + + pub fn pop_link_from(&self, block: &GroupConsensusBlock) { + let tx_sync_message = self.tx_sync_message.clone(); + let height = block.height(); + let round = block.round(); + let block_id = block.named_object().desc().object_id(); + async_std::task::spawn(async move || { + tx_sync_message + .send(SynchronizerMessage::PopBlock(height, round, block_id)) + .await + }); } - pub fn pop_link_from(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { - unimplemented!() + pub async fn process_sync_request( + &self, + min_bound: SyncBound, + max_bound: SyncBound, + remote: ObjectId, + store: &Storage, + ) -> BuckyResult<()> { + let header_block = store.header_block(); + if header_block.is_none() { + return Ok(()); + } + + let mut blocks = vec![]; + + // map SyncBound::Round(x) to height, and collect the blocks found + let header_block = header_block.as_ref().unwrap(); + let min_height = match min_bound { + SyncBound::Round(round) => { + if round > header_block.round() { + return Ok(()); + } + + // find the height + let mut block = header_block.clone(); + let mut min_height = 1; + let mut min_round = 1; + let mut max_height = block.height(); + let mut max_round = block.round(); + + while min_height < max_height { + match block.round().cmp(&round) { + std::cmp::Ordering::Equal => { + let pos = blocks + .binary_search_by(|b| b.round().cmp(&block.round())) + .unwrap_err(); + blocks.insert(pos, block); + break; + } + std::cmp::Ordering::Less => { + min_round = block.round() + 1; + min_height = block.height() + 1; + } + std::cmp::Ordering::Greater => { + max_round = block.round() - 1; + max_height = block.height() - 1; + + let is_include = match max_bound { + SyncBound::Round(max_round) => block.round() <= max_round, + SyncBound::Height(max_height) => block.height() <= max_height, + }; + if is_include { + let pos = blocks + .binary_search_by(|b| b.round().cmp(&block.round())) + .unwrap_err(); + blocks.insert(pos, block); + } + } + } + + let height = min_height + + (round - min_round) * (max_height - min_height) / (max_round - min_round); + + block = match store.get_block_by_height(height).await { + Ok(block) => block, + Err(_) => break, + } + } + + if block.round() == round { + Some(block.height()) + } else { + None + } + } + SyncBound::Height(height) => { + if height > header_block.height() { + return Ok(()); + } + + Some(height) + } + }; + + // load all blocks in [min_height, max_bound] + // TODO: limit count + if let Some(min_height) = min_height { + for height in min_height..(header_block.height() + 1) { + if let Err(pos) = blocks.binary_search_by(|b| b.height().cmp(&height)) { + if let Ok(block) = store.get_block_by_height(height).await { + let is_include = match max_bound { + SyncBound::Height(height) => block.height() <= height, + SyncBound::Round(round) => block.round() <= round, + }; + if !is_include { + break; + } + blocks.insert(pos, block); + } + } + } + } + + let network_sender = self.network_sender.clone(); + let rpath = self.rpath.clone(); + async_std::task::spawn(async move || { + futures::future::join_all(blocks.into_iter().map(|block| { + network_sender.post_package(HotstuffMessage::Block(block), rpath.clone(), &remote) + })) + .await; + }); + + Ok(()) } } @@ -124,35 +283,35 @@ impl Synchronizer { struct ResendInfo { last_send_time: Instant, send_times: usize, - cmd: Arc<(u64, SyncMaxBound, ObjectId)>, + cmd: Arc<(u64, SyncBound, ObjectId)>, } #[derive(Clone)] struct RequestSendInfo { - min_bound: SyncMaxBound, - max_bound: SyncMaxBound, + min_bound: SyncBound, + max_bound: SyncBound, resends: Vec, } impl RequestSendInfo { fn new( - min_bound: SyncMaxBound, - max_bound: SyncMaxBound, - req: Arc<(u64, SyncMaxBound, ObjectId)>, + min_bound: SyncBound, + max_bound: SyncBound, + req: Arc<(u64, SyncBound, ObjectId)>, ) -> Self { RequestSendInfo { min_bound, max_bound: max_bound, resends: vec![ResendInfo { last_send_time: Instant::now(), - send_times: 1, + send_times: 0, cmd: req, }], } } - fn splite(&mut self, bound: SyncMaxBound) -> Option { + fn splite(&mut self, bound: SyncBound) -> Option { match bound.cmp(&self.max_bound) { std::cmp::Ordering::Greater => None, _ => match bound.cmp(&self.min_bound) { @@ -169,8 +328,51 @@ impl RequestSendInfo { } } - fn try_send(&mut self) { - // todo 选send次数最少,间隔最长的发送一次 + fn try_send(&mut self, rpath: GroupRPath, sender: &crate::network::Sender) { + // 选send次数最少,间隔最长的发送一次 + if let SyncBound::Round(_) = self.min_bound { + return; + } + + let now = Instant::now(); + let max_send_info_pos = 0; + for i in 1..self.resends.len() { + let resend_info = self.resends.get(i).unwrap(); + let max_send_info = self.resends.get(max_send_info_pos).unwrap(); + + if now.duration_since(resend_info.last_send_time) + <= Duration::from_millis(SYNCHRONIZER_TIMEOUT * (1 << resend_info.send_times)) + { + return; + } + match resend_info.send_times.cmp(&max_send_info.send_times) { + std::cmp::Ordering::Less => { + max_send_info_pos = i; + } + std::cmp::Ordering::Greater => {} + std::cmp::Ordering::Equal => { + if let std::cmp::Ordering::Greater = now + .duration_since(resend_info.last_send_time) + .cmp(&now.duration_since(max_send_info.last_send_time)) + { + max_send_info_pos = i; + } + } + } + } + + if let Some(resend_info) = self.resends.get_mut(max_send_info_pos) { + resend_info.last_send_time = now; + resend_info.send_times += 1; + + let msg = HotstuffMessage::SyncRequest(self.min_bound, self.max_bound); + let remote = resend_info.cmd.2; + async_std::task::spawn(async move || sender.post_package(msg, rpath, &remote).await); + + if resend_info.send_times >= SYNCHRONIZER_TRY_TIMES { + self.resends.remove(max_send_info_pos); + } + } } fn is_valid(&self) -> bool { @@ -217,14 +419,14 @@ impl SynchronizerRunner { } } - async fn handle_sync(&mut self, min_height: u64, max_bound: SyncMaxBound, remote: ObjectId) { + async fn handle_sync(&mut self, min_height: u64, max_bound: SyncBound, remote: ObjectId) { let min_height = min_height.max(self.height + 1); let max_bound = match max_bound { - SyncMaxBound::Height(height) => SyncMaxBound::Height(height.max(self.height + 1)), - SyncMaxBound::Round(round) => SyncMaxBound::Round(round.max(self.round + 1)), + SyncBound::Height(height) => SyncBound::Height(height.max(self.height + 1)), + SyncBound::Round(round) => SyncBound::Round(round.max(self.round + 1)), }; - let requests: Vec> = self + let requests: Vec> = self .filter_outorder_blocks(min_height, max_bound) .into_iter() .map(|req| Arc::new((req.0, req.1, remote))) @@ -233,7 +435,7 @@ impl SynchronizerRunner { // combine requests let mut pos = 0; for req in requests { - let mut range = (SyncMaxBound::Height(req.0), req.1); + let mut range = (SyncBound::Height(req.0), req.1); while range.0 <= range.1 { while pos < self.sync_requests.len() { let req1 = self.sync_requests.get_mut(pos).unwrap(); @@ -245,7 +447,7 @@ impl SynchronizerRunner { }; let new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); - new_req.try_send(); + new_req.try_send(self.rpath.clone(), &self.network_sender); self.sync_requests.insert(i, new_req); range.0 = max_bound.value() + 1; } @@ -290,7 +492,7 @@ impl SynchronizerRunner { if pos == self.sync_requests.len() { if range.0 <= range.1 { let new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); - new_req.try_send(); + new_req.try_send(self.rpath.clone(), &self.network_sender); self.sync_requests.push(new_req); pos += 1; } @@ -303,9 +505,10 @@ impl SynchronizerRunner { fn filter_outorder_blocks( &self, mut min_height: u64, - mut max_bound: SyncMaxBound, - ) -> Vec<(u64, SyncMaxBound)> { - let mut last_range = Some((SyncMaxBound::Height(min_height), max_bound)); + mut max_bound: SyncBound, + ) -> Vec<(u64, SyncBound)> { + // TODO: limit the lenght of per range + let mut last_range = Some((SyncBound::Height(min_height), max_bound)); let mut requests = vec![]; for (block, _) in self.out_order_blocks.as_slice() { match last_range { @@ -329,16 +532,16 @@ impl SynchronizerRunner { } fn splite_range_with_block( - mut range: (SyncMaxBound, SyncMaxBound), + mut range: (SyncBound, SyncBound), height: u64, round: u64, ) -> ( - Option<(SyncMaxBound, SyncMaxBound)>, - Option<(SyncMaxBound, SyncMaxBound)>, + Option<(SyncBound, SyncBound)>, + Option<(SyncBound, SyncBound)>, ) { let min_ord = match range.0 { - SyncMaxBound::Height(height) => height.cmp(&height), - SyncMaxBound::Round(round) => round.cmp(&round), + SyncBound::Height(height) => height.cmp(&height), + SyncBound::Round(round) => round.cmp(&round), }; match min_ord { @@ -352,17 +555,17 @@ impl SynchronizerRunner { } std::cmp::Ordering::Greater => { let ord = match range.1 { - SyncMaxBound::Height(height) => height.cmp(&height), - SyncMaxBound::Round(round) => round.cmp(&round), + SyncBound::Height(height) => height.cmp(&height), + SyncBound::Round(round) => round.cmp(&round), }; match ord { std::cmp::Ordering::Less => ( - Some((range.0, SyncMaxBound::Height(height - 1))), - Some((SyncMaxBound::Height(height + 1), range.1)), + Some((range.0, SyncBound::Height(height - 1))), + Some((SyncBound::Height(height + 1), range.1)), ), std::cmp::Ordering::Equal => { - (Some((range.0, SyncMaxBound::Height(height - 1))), None) + (Some((range.0, SyncBound::Height(height - 1))), None) } std::cmp::Ordering::Greater => (Some((range.0, range.1)), None), } @@ -428,7 +631,7 @@ impl SynchronizerRunner { } } - self.handle_sync(min_height, SyncMaxBound::Height(block.height()), remote) + self.handle_sync(min_height, SyncBound::Height(block.height()), remote) .await; } @@ -512,9 +715,10 @@ impl SynchronizerRunner { } async fn handle_timeout(&mut self) { - for req in self.sync_requests.iter() { - req.try_send(); - } + self.sync_requests.retain_mut(|req| { + req.try_send(self.rpath.clone(), &self.network_sender); + req.resends.len() > 0 + }); } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index b02e9866e..451044820 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -15,3 +15,4 @@ pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; +pub const SYNCHRONIZER_TRY_TIMES: usize = 3; diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 8bb483a83..5f790057f 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -4,6 +4,7 @@ use cyfs_core::GroupRPath; use crate::HotstuffMessage; +#[derive(Clone)] pub(crate) struct Sender {} impl Sender { diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 0b8d7fdab..d73073925 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,12 @@ use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, Hots use serde::Serialize; use sha2::Digest; +#[derive(Copy, RawEncode, RawDecode)] +pub enum SyncBound { + Height(u64), + Round(u64), +} + #[derive(Clone, RawEncode, RawDecode)] pub(crate) enum HotstuffMessage { Block(cyfs_core::GroupConsensusBlock), @@ -14,8 +20,7 @@ pub(crate) enum HotstuffMessage { TimeoutVote(HotstuffTimeoutVote), Timeout(cyfs_core::HotstuffTimeout), - SyncWithHeight(u64, u64), - SyncWithRound(u64, u64), + SyncRequest(SyncBound, SyncBound), } #[derive(Clone, RawEncode, RawDecode)] diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index a099d3c55..aa9a76655 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -66,10 +66,6 @@ impl Storage { unimplemented!() } - pub fn prepare_height(&self) -> u64 { - unimplemented!() - } - pub fn pre_commits(&self) -> &HashMap { unimplemented!() } @@ -94,7 +90,7 @@ impl Storage { unimplemented!() } - pub fn get_rpath_by_id(rpath_id: &ObjectId) -> BuckyResult> { + pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { unimplemented!() } From 2ac4c0ff9473fc90cefba7dab87ccaac02546b1b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 10 Jan 2023 12:57:05 +0800 Subject: [PATCH 020/553] optimization --- src/component/cyfs-base/src/objects/group.rs | 21 ++- .../src/consensus/hotstuff/hotstuff.rs | 2 +- .../consensus/synchronizer/synchronizer.rs | 154 ++++-------------- .../cyfs-group/src/objects/protocol.rs | 57 ++++++- .../cyfs-group/src/storage/storage.rs | 63 ++++++- 5 files changed, 166 insertions(+), 131 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 632984754..ac795c423 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -54,11 +54,11 @@ impl GroupBodyContent { &mut self.common_mut().members } - pub fn ood_list(&self) -> &Vec { + pub fn ood_list(&self) -> &Vec { &self.common().ood_list } - pub fn ood_list_mut(&mut self) -> &mut Vec { + pub fn ood_list_mut(&mut self) -> &mut Vec { &mut self.common_mut().ood_list } @@ -172,16 +172,19 @@ impl Group { self.common_mut().members = members; } - pub fn ood_list(&self) -> &[ObjectId] { + pub fn ood_list(&self) -> &[DeviceId] { self.common().ood_list.as_slice() } - pub fn set_ood_list(&mut self, oods: Vec) { + pub fn set_ood_list(&mut self, oods: Vec) { self.common_mut().ood_list = oods; } pub fn contain_ood(&self, ood_id: &ObjectId) -> bool { - self.ood_list().contains(ood_id) + self.ood_list() + .iter() + .find(|id| id.object_id() == ood_id) + .is_some() } pub fn is_same_ood_list(&self, other: &Group) -> bool { @@ -544,7 +547,7 @@ struct CommonGroupBodyContent { role_acls: Vec, - ood_list: Vec, + ood_list: Vec, history_block_max: u64, history_block_lifespan: u64, @@ -561,7 +564,7 @@ impl CommonGroupBodyContent { icon: Option, description: String, members: Vec, - ood_list: Vec, + ood_list: Vec, ) -> Self { Self { name, @@ -708,7 +711,7 @@ impl SimpleGroupBodyContent { icon: Option, description: String, members: Vec, - ood_list: Vec, + ood_list: Vec, ) -> Self { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), @@ -786,7 +789,7 @@ impl OrgBodyContent { description: String, admins: Vec, members: Vec, - ood_list: Vec, + ood_list: Vec, ) -> Self { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e6172ffc8..5f6a65eae 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -90,7 +90,7 @@ impl Hotstuff { rpath.clone(), max_height, round, - rx_message, + tx_message_inner.clone(), ), non_driver, rpath, diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 6c3ef4e11..99e7866d7 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -1,9 +1,4 @@ -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, - time::Instant, - vec, -}; +use std::{collections::HashSet, sync::Arc, time::Instant, vec}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId}; @@ -15,56 +10,6 @@ use crate::{ SYNCHRONIZER_TIMEOUT, SYNCHRONIZER_TRY_TIMES, }; -impl SyncBound { - fn value(&self) -> u64 { - match self { - Self::Height(h) => h, - Self::Round(r) => r, - } - } - - fn add(&self, value: u64) -> Self { - match self { - Self::Height(h) => Self::Height(*h + value), - Self::Round(r) => Self::Round(*r + value), - } - } - - fn sub(&self, value: u64) -> Self { - match self { - Self::Height(h) => Self::Height(*h - value), - Self::Round(r) => Self::Round(*r - value), - } - } -} - -impl Ord for SyncBound { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - match self { - Self::Height(height) => match other { - Self::Height(other_height) => height.cmp(other_height), - Self::Round(other_round) => { - if height >= other_round { - std::cmp::Ordering::Greater - } else { - std::cmp::Ordering::Less - } - } - }, - Self::Round(round) => match other { - Self::Round(other_round) => round.cmp(other_round), - Self::Height(other_height) => { - if other_height >= round { - std::cmp::Ordering::Less - } else { - std::cmp::Ordering::Greater - } - } - }, - } - } -} - enum SynchronizerMessage { Sync(u64, SyncBound, ObjectId), // ([min-height, max-bound], remote) PushBlock(u64, GroupConsensusBlock, ObjectId), // (min-height, block, remote) @@ -83,7 +28,7 @@ impl Synchronizer { rpath: GroupRPath, height: u64, round: u64, - tx_block: Sender<(HotstuffMessage, ObjectId)>, + tx_block: Sender<(GroupConsensusBlock, ObjectId)>, ) -> Self { let (tx_sync_message, rx_sync_message) = async_std::channel::bounded(CHANNEL_CAPACITY); let runner = SynchronizerRunner::new( @@ -171,6 +116,8 @@ impl Synchronizer { remote: ObjectId, store: &Storage, ) -> BuckyResult<()> { + // TODO: combine the requests + let header_block = store.header_block(); if header_block.is_none() { return Ok(()); @@ -186,56 +133,13 @@ impl Synchronizer { return Ok(()); } - // find the height - let mut block = header_block.clone(); - let mut min_height = 1; - let mut min_round = 1; - let mut max_height = block.height(); - let mut max_round = block.round(); - - while min_height < max_height { - match block.round().cmp(&round) { - std::cmp::Ordering::Equal => { - let pos = blocks - .binary_search_by(|b| b.round().cmp(&block.round())) - .unwrap_err(); - blocks.insert(pos, block); - break; - } - std::cmp::Ordering::Less => { - min_round = block.round() + 1; - min_height = block.height() + 1; - } - std::cmp::Ordering::Greater => { - max_round = block.round() - 1; - max_height = block.height() - 1; - - let is_include = match max_bound { - SyncBound::Round(max_round) => block.round() <= max_round, - SyncBound::Height(max_height) => block.height() <= max_height, - }; - if is_include { - let pos = blocks - .binary_search_by(|b| b.round().cmp(&block.round())) - .unwrap_err(); - blocks.insert(pos, block); - } - } - } + let (ret, mut cached_blocks) = store.find_block_by_round(round); + cached_blocks.sort_unstable_by(|left, right| left.height().cmp(&right.height())); + blocks = cached_blocks; - let height = min_height - + (round - min_round) * (max_height - min_height) / (max_round - min_round); - - block = match store.get_block_by_height(height).await { - Ok(block) => block, - Err(_) => break, - } - } - - if block.round() == round { - Some(block.height()) - } else { - None + match ret { + Ok(found_block) => Some(found_block.height()), + Err(_) => None, } } SyncBound::Height(height) => { @@ -250,28 +154,42 @@ impl Synchronizer { // load all blocks in [min_height, max_bound] // TODO: limit count if let Some(min_height) = min_height { + let mut pos = 0; for height in min_height..(header_block.height() + 1) { - if let Err(pos) = blocks.binary_search_by(|b| b.height().cmp(&height)) { - if let Ok(block) = store.get_block_by_height(height).await { - let is_include = match max_bound { - SyncBound::Height(height) => block.height() <= height, - SyncBound::Round(round) => block.round() <= round, - }; - if !is_include { - break; + let exist_block = blocks.get(pos); + if let Some(exist_block) = exist_block { + match exist_block.height().cmp(&height) { + std::cmp::Ordering::Less => unreachable!(), + std::cmp::Ordering::Equal => { + pos += 1; + continue; } - blocks.insert(pos, block); + std::cmp::Ordering::Greater => {} } } + + if let Ok(block) = store.get_block_by_height(height).await { + let is_include = match max_bound { + SyncBound::Height(height) => block.height() <= height, + SyncBound::Round(round) => block.round() <= round, + }; + if !is_include { + break; + } + blocks.insert(pos, block); + pos += 1; + } } } let network_sender = self.network_sender.clone(); let rpath = self.rpath.clone(); async_std::task::spawn(async move || { - futures::future::join_all(blocks.into_iter().map(|block| { - network_sender.post_package(HotstuffMessage::Block(block), rpath.clone(), &remote) - })) + futures::future::join_all( + blocks + .into_iter() + .map(|block| network_sender.post_package(block, rpath.clone(), &remote)), + ) .await; }); diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index d73073925..fe45e5d73 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -4,15 +4,68 @@ pub mod protos { use cyfs_base::*; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; -use serde::Serialize; use sha2::Digest; -#[derive(Copy, RawEncode, RawDecode)] +#[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone)] pub enum SyncBound { Height(u64), Round(u64), } +impl Copy for SyncBound {} + +impl SyncBound { + fn value(&self) -> u64 { + match self { + Self::Height(h) => h, + Self::Round(r) => r, + } + } + + fn add(&self, value: u64) -> Self { + match self { + Self::Height(h) => Self::Height(*h + value), + Self::Round(r) => Self::Round(*r + value), + } + } + + fn sub(&self, value: u64) -> Self { + match self { + Self::Height(h) => Self::Height(*h - value), + Self::Round(r) => Self::Round(*r - value), + } + } +} + +impl PartialOrd for SyncBound { + fn partial_cmp(&self, other: &SyncBound) -> Option { + let ord = match self { + Self::Height(height) => match other { + Self::Height(other_height) => height.cmp(other_height), + Self::Round(other_round) => { + if height >= other_round { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Less + } + } + }, + Self::Round(round) => match other { + Self::Round(other_round) => round.cmp(other_round), + Self::Height(other_height) => { + if other_height >= round { + std::cmp::Ordering::Less + } else { + std::cmp::Ordering::Greater + } + } + }, + }; + + Some(ord) + } +} + #[derive(Clone, RawEncode, RawDecode)] pub(crate) enum HotstuffMessage { Block(cyfs_core::GroupConsensusBlock), diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index aa9a76655..cd5cf0d46 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; pub enum BlockLinkState { @@ -182,4 +182,65 @@ impl Storage { } max_block.map(|block| block.clone()) } + + // (found_block, cached_blocks) + pub fn find_block_by_round( + &self, + round: u64, + ) -> (BuckyResult, Vec) { + if self.header_block.is_none() { + return ( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), + vec![], + ); + } + + let mut block = self.header_block.clone().unwrap(); + let mut min_height = 1; + let mut min_round = 1; + let mut max_height = block.height(); + let mut max_round = block.round(); + + while min_height < max_height { + match block.round().cmp(&round) { + std::cmp::Ordering::Equal => { + blocks.push(block.clone()); + return (Ok(block), blocks); + } + std::cmp::Ordering::Less => { + min_round = block.round() + 1; + min_height = block.height() + 1; + } + std::cmp::Ordering::Greater => { + max_round = block.round() - 1; + max_height = block.height() - 1; + + let is_include = match max_bound { + SyncBound::Round(max_round) => block.round() <= max_round, + SyncBound::Height(max_height) => block.height() <= max_height, + }; + if is_include { + blocks.push(block); + } + } + } + + let height = min_height + + (round - min_round) * (max_height - min_height) / (max_round - min_round); + + block = match store.get_block_by_height(height).await { + Ok(block) => block, + Err(e) => return (Err(e), blocks), + } + } + + if block.round() == round { + (Ok(block), blocks) + } else { + ( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), + blocks, + ) + } + } } From 6682b1386dde78b3d409879c2bf2bd46c6b4ce00 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 10 Jan 2023 15:06:07 +0800 Subject: [PATCH 021/553] compile --- src/component/cyfs-base/src/objects/group.rs | 8 +- .../src/consensus/hotstuff/hotstuff.rs | 24 ++-- .../consensus/synchronizer/synchronizer.rs | 115 ++++++++++-------- .../cyfs-group/src/objects/protocol.rs | 24 +++- .../cyfs-group/src/storage/storage.rs | 15 +-- 5 files changed, 106 insertions(+), 80 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ac795c423..7e7b390d2 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -355,7 +355,7 @@ impl GroupMember { impl TryFrom for GroupMember { type Error = BuckyError; - fn try_from(mut value: protos::GroupMember) -> BuckyResult { + fn try_from(value: protos::GroupMember) -> BuckyResult { let ret = Self { id: ProtobufCodecHelper::decode_buf(value.id)?, title: value.title, @@ -506,7 +506,7 @@ pub struct GroupJoinSignature { impl TryFrom for GroupJoinSignature { type Error = BuckyError; - fn try_from(mut value: protos::GroupJoinSignature) -> BuckyResult { + fn try_from(value: protos::GroupJoinSignature) -> BuckyResult { let ret = Self { signature: ProtobufCodecHelper::decode_buf(value.signature)?, member_id: ProtobufCodecHelper::decode_buf(value.member_id)?, @@ -673,7 +673,7 @@ pub struct SimpleGroupDescContent { impl TryFrom for SimpleGroupDescContent { type Error = BuckyError; - fn try_from(mut value: protos::SimpleGroupDescContent) -> BuckyResult { + fn try_from(value: protos::SimpleGroupDescContent) -> BuckyResult { let ret = Self { unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, admins: ProtobufCodecHelper::decode_value_list(value.admins)?, @@ -752,7 +752,7 @@ pub struct OrgDescContent { impl TryFrom for OrgDescContent { type Error = BuckyError; - fn try_from(mut value: protos::OrgDescContent) -> BuckyResult { + fn try_from(value: protos::OrgDescContent) -> BuckyResult { let ret = Self { unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 5f6a65eae..3fbdaaefe 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -2,8 +2,8 @@ use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, ChunkId, Group, - NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, + bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, + ObjectDesc, ObjectId, RsaCPUObjectSigner, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -73,6 +73,14 @@ impl Hotstuff { let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; + let synchronizer = Synchronizer::spawn( + network_sender.clone(), + rpath.clone(), + max_height, + round, + tx_message_inner.clone(), + ); + let mut hotstuff = Self { local_id, committee, @@ -85,13 +93,7 @@ impl Hotstuff { network_sender, rx_message, delegate, - synchronizer: Synchronizer::spawn( - network_sender.clone(), - rpath.clone(), - max_height, - round, - tx_message_inner.clone(), - ), + synchronizer, non_driver, rpath, tx_proposal_consume, @@ -196,7 +198,7 @@ impl Hotstuff { self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) .await?; - self.synchronizer.pop_link_from(block)?; + self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -905,7 +907,7 @@ impl Hotstuff { log::warn!("[hotstuff] rx_message closed."); Ok(()) }, - Ok((HotstuffMessage::SyncRequest((min_bound, max_bound)), remote)) => self.synchronizer.process_sync_request(min_bound, max_bound, remote, &self.store).await + Ok((HotstuffMessage::SyncRequest(min_bound, max_bound), remote)) => self.synchronizer.process_sync_request(min_bound, max_bound, remote, &self.store).await }, message = self.rx_message_inner.recv().fuse() => match message { Ok((block, remote)) => { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 99e7866d7..fb5620702 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -1,9 +1,14 @@ -use std::{collections::HashSet, sync::Arc, time::Instant, vec}; +use std::{ + collections::HashSet, + sync::Arc, + time::{Duration, Instant}, + vec, +}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use protobuf::well_known_types::Duration; +use futures::FutureExt; use crate::{ consensus::timer::Timer, storage::Storage, HotstuffMessage, SyncBound, CHANNEL_CAPACITY, @@ -40,7 +45,7 @@ impl Synchronizer { round, ); - async_std::task::spawn(async move || runner.run().await); + async_std::task::spawn(async move { runner.run().await }); Self { tx_sync_message, @@ -51,11 +56,11 @@ impl Synchronizer { pub fn sync_with_height(&self, min_height: u64, max_height: u64, remote: ObjectId) { if min_height > max_height { - return Ok(()); + return; } let tx_sync_message = self.tx_sync_message.clone(); - async_std::task::spawn(async move || { + async_std::task::spawn(async move { tx_sync_message .send(SynchronizerMessage::Sync( min_height, @@ -68,11 +73,11 @@ impl Synchronizer { pub fn sync_with_round(&self, min_height: u64, max_round: u64, remote: ObjectId) { if min_height > max_round { - return Ok(()); + return; } let tx_sync_message = self.tx_sync_message.clone(); - async_std::task::spawn(async move || { + async_std::task::spawn(async move { tx_sync_message .send(SynchronizerMessage::Sync( min_height, @@ -90,7 +95,7 @@ impl Synchronizer { remote: ObjectId, ) { let tx_sync_message = self.tx_sync_message.clone(); - async_std::task::spawn(async move || { + async_std::task::spawn(async move { tx_sync_message .send(SynchronizerMessage::PushBlock(min_height, block, remote)) .await @@ -102,7 +107,7 @@ impl Synchronizer { let height = block.height(); let round = block.round(); let block_id = block.named_object().desc().object_id(); - async_std::task::spawn(async move || { + async_std::task::spawn(async move { tx_sync_message .send(SynchronizerMessage::PopBlock(height, round, block_id)) .await @@ -133,7 +138,15 @@ impl Synchronizer { return Ok(()); } - let (ret, mut cached_blocks) = store.find_block_by_round(round); + let (ret, mut cached_blocks) = store.find_block_by_round(round).await; + cached_blocks.retain(|block| { + let is_include = block.round() >= round + && match max_bound { + SyncBound::Round(max_round) => block.round() <= max_round, + SyncBound::Height(max_height) => block.height() <= max_height, + }; + is_include + }); cached_blocks.sort_unstable_by(|left, right| left.height().cmp(&right.height())); blocks = cached_blocks; @@ -184,12 +197,10 @@ impl Synchronizer { let network_sender = self.network_sender.clone(); let rpath = self.rpath.clone(); - async_std::task::spawn(async move || { - futures::future::join_all( - blocks - .into_iter() - .map(|block| network_sender.post_package(block, rpath.clone(), &remote)), - ) + async_std::task::spawn(async move { + futures::future::join_all(blocks.into_iter().map(|block| { + network_sender.post_package(HotstuffMessage::Block(block), rpath.clone(), &remote) + })) .await; }); @@ -285,7 +296,7 @@ impl RequestSendInfo { let msg = HotstuffMessage::SyncRequest(self.min_bound, self.max_bound); let remote = resend_info.cmd.2; - async_std::task::spawn(async move || sender.post_package(msg, rpath, &remote).await); + async_std::task::spawn(async move { sender.post_package(msg, rpath, &remote).await }); if resend_info.send_times >= SYNCHRONIZER_TRY_TIMES { self.resends.remove(max_send_info_pos); @@ -305,8 +316,8 @@ impl RequestSendInfo { struct SynchronizerRunner { network_sender: crate::network::Sender, rpath: GroupRPath, - tx_block: Sender<(HotstuffMessage, ObjectId)>, - rx_message: Receiver<(HotstuffMessage, ObjectId)>, + tx_block: Sender<(GroupConsensusBlock, ObjectId)>, + rx_message: Receiver, timer: Timer, height: u64, round: u64, @@ -319,7 +330,7 @@ impl SynchronizerRunner { fn new( network_sender: crate::network::Sender, rpath: GroupRPath, - tx_block: Sender<(HotstuffMessage, ObjectId)>, + tx_block: Sender<(GroupConsensusBlock, ObjectId)>, rx_message: Receiver, height: u64, round: u64, @@ -364,30 +375,34 @@ impl SynchronizerRunner { _ => req1.min_bound.sub(1), }; - let new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); + let mut new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); new_req.try_send(self.rpath.clone(), &self.network_sender); - self.sync_requests.insert(i, new_req); - range.0 = max_bound.value() + 1; + self.sync_requests.insert(pos, new_req); + range.0 = max_bound.add(1); } std::cmp::Ordering::Equal => { - match range.1.cmp(&req1.max_bound) { + let cut_req = match range.1.cmp(&req1.max_bound) { std::cmp::Ordering::Greater => { range.0 = req1.max_bound.add(1); + None } _ => { range.0 = range.1.add(1); let cut = req1.splite(range.0); assert!(req1.is_valid()); - if let Some(cut) = cut { - self.sync_requests.insert(i + 1, cut); - } + cut } }; req1.resends.push(ResendInfo { - last_send_time: 0, + last_send_time: Instant::now() + .checked_sub(Duration::from_millis(SYNCHRONIZER_TIMEOUT << 1)) + .unwrap(), send_times: 0, cmd: req.clone(), }); + if let Some(cut) = cut_req { + self.sync_requests.insert(pos + 1, cut); + } } std::cmp::Ordering::Greater => match range.0.cmp(&req1.max_bound) { std::cmp::Ordering::Greater => {} @@ -395,7 +410,7 @@ impl SynchronizerRunner { let cut = req1.splite(range.0); assert!(req1.is_valid()); if let Some(cut) = cut { - self.sync_requests.insert(i + 1, cut); + self.sync_requests.insert(pos + 1, cut); } } }, @@ -409,7 +424,7 @@ impl SynchronizerRunner { if pos == self.sync_requests.len() { if range.0 <= range.1 { - let new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); + let mut new_req = RequestSendInfo::new(range.0, max_bound, req.clone()); new_req.try_send(self.rpath.clone(), &self.network_sender); self.sync_requests.push(new_req); pos += 1; @@ -434,7 +449,7 @@ impl SynchronizerRunner { let (range1, range2) = Self::splite_range_with_block(range, block.height(), block.round()); if let Some(range1) = range1 { - requests.push(range1); + requests.push((range1.0.height(), range1.1)); } last_range = range2; } @@ -443,7 +458,7 @@ impl SynchronizerRunner { } if let Some(last_range) = last_range { - requests.push(last_range); + requests.push((last_range.0.height(), last_range.1)); } requests @@ -497,11 +512,10 @@ impl SynchronizerRunner { block: GroupConsensusBlock, remote: ObjectId, ) { - if block.round() <= self.round { - return; - } - - if min_height >= block.height() { + if block.round() <= self.round + || min_height <= block.height() + || block.prev_block_id().is_none() + { return; } @@ -516,7 +530,7 @@ impl SynchronizerRunner { match pos { Ok(_) => return, - Err(pos) => self.out_order_blocks.insert(pos, (block, remote)), + Err(pos) => self.out_order_blocks.insert(pos, (block.clone(), remote)), }; self.timer.reset(SYNCHRONIZER_TIMEOUT); @@ -542,7 +556,9 @@ impl SynchronizerRunner { None => { match range2 { Some(range2) => req.min_bound = range2.0, - None => self.sync_requests.remove(i), + None => { + self.sync_requests.remove(i); + } } break; } @@ -560,10 +576,10 @@ impl SynchronizerRunner { self.timer.reset(SYNCHRONIZER_TIMEOUT); - let mut max_height = self.height.max(&new_height); + let mut max_height = self.height.max(new_height); let mut max_round = new_round; - let mut remove_block_ids = HashSet::from(&[block_id]); + let mut remove_block_ids = HashSet::from([block_id]); let mut remove_pos = None; @@ -571,7 +587,8 @@ impl SynchronizerRunner { let (block, remote) = self.out_order_blocks.get(pos).unwrap(); let block_id_out = block.named_object().desc().object_id(); - if remove_block_ids.contains(&block.prev_block_id()) || block_id_out == block_id { + if remove_block_ids.contains(block.prev_block_id().unwrap()) || block_id_out == block_id + { remove_block_ids.insert(block_id_out); remove_pos = Some(pos); max_height = max_height.max(block.height()); @@ -622,13 +639,14 @@ impl SynchronizerRunner { } if let Some(remove_request_pos) = remove_request_pos { - self.sync_requests.splice(0..(pos + 1), []); + self.sync_requests.splice(0..(remove_request_pos + 1), []); } - futures::future::join_all(order_blocks.into_iter().map(|(order_block, remote)| { - self.tx_block - .send((HotstuffMessage::Block(order_block), remote)) - })) + futures::future::join_all( + order_blocks + .into_iter() + .map(|(order_block, remote)| self.tx_block.send((order_block, remote))), + ) .await; } @@ -647,8 +665,7 @@ impl SynchronizerRunner { Ok(SynchronizerMessage::PushBlock(min_height, block, remote)) => self.handle_push_block(min_height, block, remote).await, Ok(SynchronizerMessage::PopBlock(new_height, new_round, block_id)) => self.handle_pop_block(new_height, new_round, block_id).await, Err(e) => { - log::warn!("[synchronizer] rx_message closed."); - Ok(()) + log::warn!("[synchronizer] rx_message closed.") }, }, () = self.timer.wait_next().fuse() => self.handle_timeout().await, diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index fe45e5d73..9509a1043 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -15,21 +15,35 @@ pub enum SyncBound { impl Copy for SyncBound {} impl SyncBound { - fn value(&self) -> u64 { + pub fn value(&self) -> u64 { match self { - Self::Height(h) => h, - Self::Round(r) => r, + Self::Height(h) => *h, + Self::Round(r) => *r, } } - fn add(&self, value: u64) -> Self { + pub fn height(&self) -> u64 { + match self { + Self::Height(h) => *h, + Self::Round(r) => panic!("should be height"), + } + } + + pub fn round(&self) -> u64 { + match self { + Self::Round(r) => *r, + Self::Height(h) => panic!("should be round"), + } + } + + pub fn add(&self, value: u64) -> Self { match self { Self::Height(h) => Self::Height(*h + value), Self::Round(r) => Self::Round(*r + value), } } - fn sub(&self, value: u64) -> Self { + pub fn sub(&self, value: u64) -> Self { match self { Self::Height(h) => Self::Height(*h - value), Self::Round(r) => Self::Round(*r - value), diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/storage.rs index cd5cf0d46..daab2fc2c 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/storage.rs @@ -184,7 +184,7 @@ impl Storage { } // (found_block, cached_blocks) - pub fn find_block_by_round( + pub async fn find_block_by_round( &self, round: u64, ) -> (BuckyResult, Vec) { @@ -195,6 +195,7 @@ impl Storage { ); } + let mut blocks = vec![]; let mut block = self.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; @@ -202,9 +203,9 @@ impl Storage { let mut max_round = block.round(); while min_height < max_height { + blocks.push(block.clone()); match block.round().cmp(&round) { std::cmp::Ordering::Equal => { - blocks.push(block.clone()); return (Ok(block), blocks); } std::cmp::Ordering::Less => { @@ -214,21 +215,13 @@ impl Storage { std::cmp::Ordering::Greater => { max_round = block.round() - 1; max_height = block.height() - 1; - - let is_include = match max_bound { - SyncBound::Round(max_round) => block.round() <= max_round, - SyncBound::Height(max_height) => block.height() <= max_height, - }; - if is_include { - blocks.push(block); - } } } let height = min_height + (round - min_round) * (max_height - min_height) / (max_round - min_round); - block = match store.get_block_by_height(height).await { + block = match self.get_block_by_height(height).await { Ok(block) => block, Err(e) => return (Err(e), blocks), } From c62d90a90c7b05980c44ff26ffb3bdcd66b44dad Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 11 Jan 2023 11:57:30 +0800 Subject: [PATCH 022/553] compile --- .../src/consensus/hotstuff/hotstuff.rs | 2 +- .../consensus/synchronizer/synchronizer.rs | 5 +++-- .../cyfs-group/src/consensus/timer.rs | 4 ++-- .../src/consensus/vote/committee.rs | 2 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 19 ++++++++++++------- src/component/cyfs-group/src/dec/rpath_mgr.rs | 2 +- .../cyfs-group/src/manager/group_manager.rs | 4 ++-- .../cyfs-group/src/network/sender.rs | 13 ++++++++++--- .../cyfs-group/src/objects/protocol.rs | 2 +- 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 3fbdaaefe..04d8ad245 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -24,7 +24,7 @@ use crate::{ * TODO: generate empty block when the 'Node' is synchronizing */ -pub struct Hotstuff { +pub(crate) struct Hotstuff { local_id: ObjectId, committee: Committee, store: Storage, diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index fb5620702..58ea4d39f 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -36,7 +36,7 @@ impl Synchronizer { tx_block: Sender<(GroupConsensusBlock, ObjectId)>, ) -> Self { let (tx_sync_message, rx_sync_message) = async_std::channel::bounded(CHANNEL_CAPACITY); - let runner = SynchronizerRunner::new( + let mut runner = SynchronizerRunner::new( network_sender.clone(), rpath.clone(), tx_block, @@ -264,7 +264,7 @@ impl RequestSendInfo { } let now = Instant::now(); - let max_send_info_pos = 0; + let mut max_send_info_pos = 0; for i in 1..self.resends.len() { let resend_info = self.resends.get(i).unwrap(); let max_send_info = self.resends.get(max_send_info_pos).unwrap(); @@ -296,6 +296,7 @@ impl RequestSendInfo { let msg = HotstuffMessage::SyncRequest(self.min_bound, self.max_bound); let remote = resend_info.cmd.2; + let sender = sender.clone(); async_std::task::spawn(async move { sender.post_package(msg, rpath, &remote).await }); if resend_info.send_times >= SYNCHRONIZER_TRY_TIMES { diff --git a/src/component/cyfs-group/src/consensus/timer.rs b/src/component/cyfs-group/src/consensus/timer.rs index 57230ccb7..022c4b5e4 100644 --- a/src/component/cyfs-group/src/consensus/timer.rs +++ b/src/component/cyfs-group/src/consensus/timer.rs @@ -9,7 +9,7 @@ pub struct Timer { impl Timer { pub fn new(duration: u64) -> Self { - let sleep = Box::pin(async { + let sleep = Box::pin(async move { async_std::future::timeout( Duration::from_millis(duration), std::future::pending::<()>(), @@ -23,7 +23,7 @@ impl Timer { } pub fn reset(&mut self, duration: u64) { - let sleep = Box::pin(async { + let sleep = Box::pin(async move { async_std::future::timeout( Duration::from_millis(duration), std::future::pending::<()>(), diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index e00824f02..42edff9b6 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -6,7 +6,7 @@ use cyfs_core::{GroupConsensusBlock, HotstuffTimeout}; use crate::{HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] -pub struct Committee {} +pub(crate) struct Committee {} impl Committee { pub fn spawn() {} diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 3554ce5dd..e0a177ea7 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -10,7 +10,7 @@ use cyfs_core::{ use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; -pub struct VoteMgr { +pub(crate) struct VoteMgr { committee: Committee, round: u64, blocks: HashMap, @@ -19,7 +19,7 @@ pub struct VoteMgr { waiting_timeouts: HashMap>>, // >> } -pub enum VoteThresholded { +pub(crate) enum VoteThresholded { QC(HotstuffBlockQC), TC(HotstuffTimeout, Option), None, @@ -111,7 +111,7 @@ impl VoteMgr { VoteThresholded::None } - pub async fn add_vote( + pub(crate) async fn add_vote( &mut self, vote: HotstuffBlockQCVote, block: Option, @@ -139,7 +139,7 @@ impl VoteMgr { .map(|vote| vote.map(|v| (v, block.unwrap().clone()))) } - pub async fn add_timeout( + pub(crate) async fn add_timeout( &mut self, timeout: HotstuffTimeoutVote, block: Option<&GroupConsensusBlock>, @@ -172,8 +172,13 @@ impl VoteMgr { .map(|vote| vote.map(|v| (v, max_block.cloned()))) } - pub fn add_waiting_timeout(&mut self, timeout: HotstuffTimeoutVote) { - let block_id = timeout.high_qc.unwrap().block_id; + pub(crate) fn add_waiting_timeout(&mut self, timeout: HotstuffTimeoutVote) { + let block_id = timeout + .high_qc + .as_ref() + .expect("pre-block is empty") + .block_id; + self.waiting_timeouts .entry(block_id) .or_insert_with(HashMap::new) @@ -188,7 +193,7 @@ impl VoteMgr { self.timeouts.retain(|k, _| k >= &round); self.blocks.retain(|_, block| block.round() >= round); self.waiting_timeouts.retain(|_, timeouts| { - timeouts.retain(|k, timeouts| k >= &round); + timeouts.retain(|k, _| k >= &round); !timeouts.is_empty() }); self.round = round; diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index d70d0843f..5f040397d 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -5,7 +5,7 @@ use cyfs_core::{DecAppId, GroupRPath}; use crate::{DelegateFactory, IsCreateRPath, RPathClient, RPathControl}; -type ByRPath = HashMap; +type ByRPath = HashMap; type ByDec = HashMap; type ByGroup = HashMap; diff --git a/src/component/cyfs-group/src/manager/group_manager.rs b/src/component/cyfs-group/src/manager/group_manager.rs index 307a26d11..003f65c7f 100644 --- a/src/component/cyfs-group/src/manager/group_manager.rs +++ b/src/component/cyfs-group/src/manager/group_manager.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, GroupId}; use cyfs_core::DecAppId; -use crate::GroupDecControl; +use crate::RPathControl; pub struct GroupManager {} @@ -11,7 +11,7 @@ impl GroupManager { group_id: GroupId, dec_id: DecAppId, r_path: &str, - ) -> BuckyResult { + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 5f790057f..f26829c84 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -5,12 +5,19 @@ use cyfs_core::GroupRPath; use crate::HotstuffMessage; #[derive(Clone)] -pub(crate) struct Sender {} +pub struct Sender {} impl Sender { pub fn new(vport: u16, bdt_stack: Stack) {} - pub async fn post_package(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &ObjectId) {} + pub(crate) async fn post_package( + &self, + msg: HotstuffMessage, + rpath: GroupRPath, + to: &ObjectId, + ) { + } - pub async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[ObjectId]) {} + pub(crate) async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[ObjectId]) { + } } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 9509a1043..84822b570 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -234,7 +234,7 @@ impl ProtobufTransform for HotstuffTimeoutVo impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc { + high_qc: match value.high_qc.as_ref() { Some(qc) => Some(qc.to_vec()?), None => None, }, From 96043c9e868811ddef8b609f1ac8a54b3abfcfd9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 11 Jan 2023 20:53:03 +0800 Subject: [PATCH 023/553] update the interface to app --- src/component/cyfs-base/src/objects/group.rs | 14 +++++ .../cyfs-core/protos/core_objects.proto | 5 +- .../src/group/group_consensus_block.rs | 1 + .../cyfs-core/src/group/group_rpath_status.rs | 1 + .../protos/group_bft_protocol.proto | 3 +- .../cyfs-group/src/consensus/block.rs | 5 -- .../cyfs-group/src/consensus/consensus.rs | 23 -------- src/component/cyfs-group/src/consensus/mod.rs | 6 +-- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 13 +++-- .../cyfs-group/src/dec/rpath_client.rs | 2 - .../cyfs-group/src/dec/rpath_control.rs | 4 +- src/component/cyfs-group/src/dec/rpath_mgr.rs | 18 +++++-- src/component/cyfs-group/src/group_dec_mgr.rs | 29 +++++++++++ src/component/cyfs-group/src/lib.rs | 4 +- .../cyfs-group/src/manager/group_manager.rs | 52 ------------------- src/component/cyfs-group/src/manager/mod.rs | 5 -- .../cyfs-group/src/objects/protocol.rs | 34 ++++++++++-- .../cyfs-group/src/statepath/design.md | 11 ++++ 19 files changed, 122 insertions(+), 109 deletions(-) delete mode 100644 src/component/cyfs-group/src/consensus/block.rs delete mode 100644 src/component/cyfs-group/src/consensus/consensus.rs create mode 100644 src/component/cyfs-group/src/group_dec_mgr.rs delete mode 100644 src/component/cyfs-group/src/manager/group_manager.rs delete mode 100644 src/component/cyfs-group/src/manager/mod.rs diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 7e7b390d2..001af4ae8 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -4,6 +4,12 @@ use crate::*; use std::collections::HashSet; use std::convert::TryFrom; +pub enum GroupMemberScope { + Admin, + Member, + All, +} + #[derive(Clone, Debug, RawEncode, RawDecode)] pub enum GroupDescContent { SimpleGroup(SimpleGroupDescContent), @@ -311,6 +317,14 @@ impl Group { } } + pub fn select_members_with_distance( + &self, + target: &ObjectId, + scope: GroupMemberScope, + ) -> Vec<&ObjectId> { + unimplemented!() + } + // pub fn group_hash(&self) -> ObjectId { // let mut without_sign = self.clone(); // without_sign.common_mut().join_signatures = vec![]; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 1e3faac20..e987df99c 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -362,14 +362,15 @@ message GroupPropsalDecideParam { message HotstuffBlockQc { bytes block_id = 1; - uint64 round = 2; + optional bytes prev_block_id = 2; // + uint64 round = 3; message VoteSignature { bytes voter = 1; bytes signature = 2; } - repeated VoteSignature votes = 3; + repeated VoteSignature votes = 4; } message HotstuffTimeout { diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 82eee45e2..811230f3d 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -75,6 +75,7 @@ impl ProtobufTransform<&HotstuffBlockQCSign> #[cyfs_protobuf_type(crate::codec::protos::HotstuffBlockQc)] pub struct HotstuffBlockQC { pub block_id: ObjectId, + pub prev_block_id: Option, pub round: u64, pub votes: Vec, } diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs index 9159adcb5..fafe663ef 100644 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ b/src/component/cyfs-core/src/group/group_rpath_status.rs @@ -6,6 +6,7 @@ use serde::Serialize; use sha2::Digest; // TODO: 后面再封装这个对象 +#[derive(Clone, RawEncode, RawDecode)] pub struct GroupRPathStatus {} #[cfg(test)] diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 590c827b8..6ed8c3afe 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -3,7 +3,8 @@ syntax = "proto3"; message HotstuffBlockQCVote { bytes block_id = 1; - uint64 round = 2; + optional bytes prev_block_id = 2; + uint64 round = 3; bytes voter = 4; bytes signature = 5; } diff --git a/src/component/cyfs-group/src/consensus/block.rs b/src/component/cyfs-group/src/consensus/block.rs deleted file mode 100644 index a4be3c4da..000000000 --- a/src/component/cyfs-group/src/consensus/block.rs +++ /dev/null @@ -1,5 +0,0 @@ -use cyfs_core::GroupConsensusBlock; - -pub trait AsBlock {} - -impl AsBlock for GroupConsensusBlock {} diff --git a/src/component/cyfs-group/src/consensus/consensus.rs b/src/component/cyfs-group/src/consensus/consensus.rs deleted file mode 100644 index b6fdb6535..000000000 --- a/src/component/cyfs-group/src/consensus/consensus.rs +++ /dev/null @@ -1,23 +0,0 @@ -// as miner in blockchain - -use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupProposal; - -#[async_trait::async_trait] -pub trait AsConsensus { - async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()>; - async fn get_nonce(&self, account: &ObjectId) -> BuckyResult; -} - -pub(crate) trait AsConsensusInner { - fn get_pending_proposal(&self) -> Vec; - fn remove_proposal(&self, proposal_id: &ObjectId); -} - -pub struct Consensus {} - -impl Consensus { - pub fn create() -> Self { - Self {} - } -} diff --git a/src/component/cyfs-group/src/consensus/mod.rs b/src/component/cyfs-group/src/consensus/mod.rs index f8ba322dc..d7e8bd804 100644 --- a/src/component/cyfs-group/src/consensus/mod.rs +++ b/src/component/cyfs-group/src/consensus/mod.rs @@ -1,13 +1,9 @@ -mod block; -mod consensus; mod hotstuff; -mod synchronizer; mod proposal; +mod synchronizer; mod timer; mod vote; -pub use block::*; -pub use consensus::*; pub use hotstuff::*; pub use proposal::*; pub use vote::*; diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index e0a177ea7..e03e2b314 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -251,6 +251,7 @@ impl QCMaker { if self.thresholded { return Ok(Some(HotstuffBlockQC { block_id: block.named_object().desc().object_id(), + prev_block_id: block.prev_block_id().map(|id| id.clone()), round: block.round(), votes: self .votes diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 5f5cd1a5b..377275bef 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -7,16 +7,23 @@ pub trait DelegateFactory { async fn create_rpath_delegate( &self, group: &Group, - dec_id: &ObjectId, rpath: &str, with_proposal: Option<&GroupProposal>, ) -> BuckyResult>; + + async fn on_state_changed( + &self, + group_id: &ObjectId, + rpath: &str, + state_id: ObjectId, + pre_state_id: Option, + ); } pub struct ExecuteResult { - pub result_state_id: ObjectId, // pack block + pub result_state_id: ObjectId, // pack block pub receipt: Option, // to client - pub context: Vec, // timestamp etc. + pub context: Vec, // timestamp etc. } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 768909145..807a8934a 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use cyfs_base::BuckyResult; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath, GroupRPathStatus}; use cyfs_lib::NONObjectInfo; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index a4a323cb4..8d6276da2 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -15,11 +15,11 @@ impl RPathControlRaw { unimplemented!() } - pub fn select_branch(&self, block_id: ObjectId, source: ObjectId) -> BuckyResult<()> { + async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { unimplemented!() } - async fn on_post_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + pub fn select_branch(&self, block_id: ObjectId, source: ObjectId) -> BuckyResult<()> { unimplemented!() } diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 5f040397d..8430fbc0c 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use cyfs_base::{BuckyResult, GroupId, ObjectId}; -use cyfs_core::{DecAppId, GroupRPath}; +use cyfs_core::DecAppId; use crate::{DelegateFactory, IsCreateRPath, RPathClient, RPathControl}; @@ -9,12 +9,12 @@ type ByRPath = HashMap; type ByDec = HashMap; type ByGroup = HashMap; -pub struct RPathControlMgr { +pub struct GroupRPathMgr { dec_id: DecAppId, by_group: ByGroup, } -impl RPathControlMgr { +impl GroupRPathMgr { pub fn new(dec_id: DecAppId) -> Self { Self { by_group: ByGroup::default(), @@ -47,6 +47,18 @@ impl RPathControlMgr { unimplemented!() } + pub async fn rpath_control( + &self, + group_id: &GroupId, + rpath: &str, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn set_sync_path(&self, path: String) -> BuckyResult<()> { + unimplemented!() + } + // return Vec pub async fn enum_group(&self) -> BuckyResult> { unimplemented!() diff --git a/src/component/cyfs-group/src/group_dec_mgr.rs b/src/component/cyfs-group/src/group_dec_mgr.rs new file mode 100644 index 000000000..b78a6f801 --- /dev/null +++ b/src/component/cyfs-group/src/group_dec_mgr.rs @@ -0,0 +1,29 @@ +use std::collections::HashMap; + +use cyfs_base::BuckyResult; +use cyfs_core::DecAppId; + +use crate::GroupRPathMgr; + +type ByDec = HashMap>; + +pub struct RPathControlMgr { + by_dec: ByDec, +} + +impl RPathControlMgr { + pub async fn start(&self) -> BuckyResult { + unimplemented!() + } + + pub async fn close(&self) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn create_rpath_mgr_with_dec_id( + &self, + dec_id: &DecAppId, + ) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index 0b4cfc980..c47829954 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -2,7 +2,7 @@ mod consensus; mod constant; mod crypto; mod dec; -mod manager; +mod group_dec_mgr; mod network; mod objects; mod statepath; @@ -13,7 +13,7 @@ pub use consensus::*; pub use constant::*; pub(crate) use crypto::*; pub use dec::*; -pub use manager::*; +pub use group_dec_mgr::*; pub(crate) use network::*; pub use objects::*; pub use statepath::*; diff --git a/src/component/cyfs-group/src/manager/group_manager.rs b/src/component/cyfs-group/src/manager/group_manager.rs deleted file mode 100644 index 003f65c7f..000000000 --- a/src/component/cyfs-group/src/manager/group_manager.rs +++ /dev/null @@ -1,52 +0,0 @@ -use cyfs_base::{BuckyResult, GroupId}; -use cyfs_core::DecAppId; - -use crate::RPathControl; - -pub struct GroupManager {} - -impl GroupManager { - pub fn get_group_dec_control( - &self, - group_id: GroupId, - dec_id: DecAppId, - r_path: &str, - ) -> BuckyResult { - unimplemented!() - } -} - -// pub struct GroupMemberState { -// None, -// Joined, -// Crave(CraveObject), -// Invite(InviteObject), -// Reject(RejectCraveObject | RejectInviteObject), -// Removed(RemoveMemberObject) -// } - -// pub struct GroupControl { -// pub fn member_state(member_id: ObjectId) -> BuckyResult { - -// } - -// pub fn invite(target: ObjectId) -> BuckyResult { - -// } - -// pub fn crave() -> BuckyResult { - -// } - -// pub fn remove_member(target: ObjectId) -> BuckyResult { - -// } - -// pub fn add_invite_handle(() -> GroupMemberState) { - -// } - -// pub fn add_crave_handle(() -> GroupMemberState) { - -// } -// } diff --git a/src/component/cyfs-group/src/manager/mod.rs b/src/component/cyfs-group/src/manager/mod.rs deleted file mode 100644 index 5d2af2270..000000000 --- a/src/component/cyfs-group/src/manager/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// the manager for the groups - -mod group_manager; - -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 84822b570..c99bd1220 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -3,7 +3,10 @@ pub mod protos { } use cyfs_base::*; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, +}; +use cyfs_lib::NONObjectInfo; use sha2::Digest; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone)] @@ -88,6 +91,11 @@ pub(crate) enum HotstuffMessage { Timeout(cyfs_core::HotstuffTimeout), SyncRequest(SyncBound, SyncBound), + + StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + ProposalResult(ObjectId, NONObjectInfo), // (proposal-id, ExecuteResult) + QueryState(String), + VerifiableState(GroupRPathStatus), } #[derive(Clone, RawEncode, RawDecode)] @@ -96,6 +104,7 @@ pub(crate) enum HotstuffPackage { BlockVote(ProtocolAddress, HotstuffBlockQCVote), TimeoutVote(ProtocolAddress, HotstuffTimeoutVote), Timeout(ProtocolAddress, cyfs_core::HotstuffTimeout), + SyncRequest(ProtocolAddress, SyncBound, SyncBound), } #[derive(Clone, RawEncode, RawDecode)] @@ -108,6 +117,7 @@ pub(crate) enum ProtocolAddress { #[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] pub(crate) struct HotstuffBlockQCVote { pub block_id: ObjectId, + pub prev_block_id: Option, pub round: u64, pub voter: ObjectId, pub signature: Signature, @@ -123,7 +133,7 @@ impl HotstuffBlockQCVote { let round = block.round(); let signature = signer .sign( - Self::hash_content(&block_id, round).as_slice(), + Self::hash_content(&block_id, block.prev_block_id(), round).as_slice(), &SignatureSource::RefIndex(0), ) .await?; @@ -133,17 +143,25 @@ impl HotstuffBlockQCVote { round, voter: local_id, signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), }) } fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.round) + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) } - fn hash_content(block_id: &ObjectId, round: u64) -> HashValue { + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { let mut sha256 = sha2::Sha256::new(); sha256.input(block_id.as_slice()); sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } sha256.result().into() } } @@ -155,6 +173,10 @@ impl ProtobufTransform for HotstuffBlockQCVo signature: Signature::raw_decode(value.signature.as_slice())?.0, block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, }) } } @@ -166,6 +188,10 @@ impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcV round: value.round, voter: value.voter.to_vec()?, signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, }; Ok(ret) diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 6143d36bc..1cfd7483f 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -60,3 +60,14 @@ |--str(version-seq)-->GroupUpdateProposal // Chunk(Encode(group)) |--str(group-hash)-->GroupUpdateProposal ``` + +member 同步结构 + +``` +|--${/} // config by the DecAPP + |--${group-id} + |--${r-path} + |--state-->ObjectId // the latest state + |--block-->Block // the hightest block + |--qc-->qc-block // the qc for the ${block} +``` From da42b452465bdce532aead6aa21d6b833350cdeb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 12 Jan 2023 18:44:36 +0800 Subject: [PATCH 024/553] post proposal --- src/component/cyfs-base/src/base/error.rs | 12 ++ .../cyfs-core/protos/core_objects.proto | 4 +- .../src/group/group_consensus_block.rs | 10 +- .../cyfs-core/src/group/group_proposal.rs | 3 + .../src/consensus/hotstuff/hotstuff.rs | 126 ++++++++++++++---- .../consensus/synchronizer/synchronizer.rs | 8 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 4 +- .../cyfs-group/src/dec/rpath_client.rs | 103 ++++++++++++-- src/component/cyfs-group/src/dec/rpath_mgr.rs | 25 +++- src/component/cyfs-group/src/group_dec_mgr.rs | 29 ---- src/component/cyfs-group/src/lib.rs | 2 - .../cyfs-group/src/network/listener.rs | 41 +++++- .../cyfs-group/src/network/non_driver.rs | 24 +++- .../cyfs-group/src/network/sender.rs | 2 +- .../src/objects/group_decide_proposal.rs | 1 + .../src/objects/group_update_proposal.rs | 8 ++ .../cyfs-group/src/objects/protocol.rs | 14 +- 18 files changed, 325 insertions(+), 92 deletions(-) delete mode 100644 src/component/cyfs-group/src/group_dec_mgr.rs diff --git a/src/component/cyfs-base/src/base/error.rs b/src/component/cyfs-base/src/base/error.rs index bfa27d314..3ddfd518b 100644 --- a/src/component/cyfs-base/src/base/error.rs +++ b/src/component/cyfs-base/src/base/error.rs @@ -124,6 +124,9 @@ pub enum BuckySystemErrorCode { ParseError = 261, NotHandled = 262, + InvalidTarget = 263, + ErrorTimestamp = 264, + // 在system error code里面,meta_error默认值都取值5000 MetaError = 5000, @@ -237,6 +240,9 @@ pub enum BuckyErrorCode { ParseError, NotHandled, + InvalidTarget, + ErrorTimestamp, + // meta chain的error段,取值范围是[0, BUCKY_META_ERROR_CODE_MAX) MetaError(u16), @@ -326,6 +332,9 @@ impl Into for BuckyErrorCode { Self::ParseError => BuckySystemErrorCode::ParseError, Self::NotHandled => BuckySystemErrorCode::NotHandled, + Self::InvalidTarget => BuckySystemErrorCode::InvalidTarget, + Self::ErrorTimestamp => BuckySystemErrorCode::ErrorTimestamp, + Self::MetaError(_) => BuckySystemErrorCode::MetaError, Self::DecError(_) => BuckySystemErrorCode::DecError, } @@ -415,6 +424,9 @@ impl Into for BuckySystemErrorCode { Self::ParseError => BuckyErrorCode::ParseError, Self::NotHandled => BuckyErrorCode::NotHandled, + Self::InvalidTarget => BuckyErrorCode::InvalidTarget, + Self::ErrorTimestamp => BuckyErrorCode::ErrorTimestamp, + Self::MetaError => BuckyErrorCode::MetaError(0), Self::DecError => BuckyErrorCode::DecError(0), } diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index e987df99c..4bde48310 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -408,8 +408,8 @@ message GroupConsensusBlockBodyContent { message Proposal { bytes proposal_id = 1; bytes proposal_result_state = 2; - bytes proposal_receipt = 3; - bytes context = 4; + optional bytes proposal_receipt = 3; + optional bytes context = 4; } repeated Proposal proposals = 1; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 811230f3d..bd1d46ecb 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -126,21 +126,21 @@ pub struct HotstuffTimeout { pub struct GroupConsensusBlockProposal { pub proposal: ObjectId, pub result_state: ObjectId, - pub receipt: Vec, - pub context: Vec, + pub receipt: Option>, + pub context: Option>, } impl ProtobufTransform for GroupConsensusBlockProposal { fn transform( - value: crate::codec::protos::group_consensus_block_body_content::Proposal, + mut value: crate::codec::protos::group_consensus_block_body_content::Proposal, ) -> BuckyResult { Ok(Self { proposal: ObjectId::raw_decode(value.proposal_id.as_slice())?.0, result_state: ObjectId::raw_decode(&value.proposal_result_state.as_slice())?.0, - receipt: value.proposal_receipt.clone(), - context: value.context.clone(), + receipt: value.proposal_receipt.take(), + context: value.context.take(), }) } } diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 748b0ee8c..c09eb7e40 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -165,6 +165,7 @@ pub trait GroupProposalObject { params: Option>, payload: Option>, timestamp: Option, + owner: ObjectId, meta_block_id: Option, effective_begining: Option, effective_ending: Option, @@ -213,6 +214,7 @@ impl GroupProposalObject for GroupProposal { params: Option>, payload: Option>, timestamp: Option, + owner: ObjectId, meta_block_id: Option, effective_begining: Option, effective_ending: Option, @@ -234,6 +236,7 @@ impl GroupProposalObject for GroupProposal { }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) + .owner(owner) } fn r_path(&self) -> &GroupRPath { diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 04d8ad245..e0f058697 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, RsaCPUObjectSigner, + ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, RsaCPUObjectSigner, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -14,14 +14,15 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, timer::Timer}, - AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, + consensus::{proposal, synchronizer::Synchronizer, timer::Timer}, + network, AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * TODO: use admins instead ood_list */ pub(crate) struct Hotstuff { @@ -266,12 +267,9 @@ impl Hotstuff { for proposal_exe_info in block.proposals() { // TODO: 去重 let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); - let receipt = if proposal_exe_info.receipt.len() > 0 { - Some(NONObjectInfo::new_from_object_raw( - proposal_exe_info.receipt.clone(), - )?) - } else { - None + let receipt = match proposal_exe_info.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, }; let exe_result = ExecuteResult { @@ -325,9 +323,7 @@ impl Hotstuff { * */ self.cleanup_proposal(&header_block).await; - if block.owner() == &self.local_id { - self.notify_proposal_result_for_block(&header_block); - } + self.notify_proposal_result_for_block(&header_block); } match self.vote_mgr.add_voting_block(block).await { @@ -352,7 +348,7 @@ impl Hotstuff { self.handle_vote(&vote, Some(block), remote).await?; } else { self.network_sender - .post_package( + .post_message( HotstuffMessage::BlockVote(vote), self.rpath.clone(), &next_leader, @@ -398,13 +394,82 @@ impl Hotstuff { PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, proposals).await } - fn notify_proposal_result(&self, proposal: &GroupProposal, result: &NONObjectInfo) { - // 通知客户端proposal执行结果 - unimplemented!() + fn notify_proposal_result( + &self, + proposal: &GroupProposal, + result: BuckyResult>, + ) { + // notify to the proposer + let proposal_id = proposal.desc().object_id(); + match proposal.desc().owner() { + Some(proposer) => { + let network_sender = self.network_sender.clone(); + let proposer = proposer.clone(); + let rpath = self.rpath.clone(); + + async_std::task::spawn(async move { + network_sender + .post_message( + HotstuffMessage::ProposalResult(proposal_id, result), + rpath.clone(), + &proposer, + ) + .await + }); + } + None => log::warn!("proposal({}) without owner", proposal_id), + } } fn notify_proposal_result_for_block(&self, block: &GroupConsensusBlock) { - unimplemented!() + if block.owner() == &self.local_id { + return; + } + + let network_sender = self.network_sender.clone(); + let rpath = self.rpath.clone(); + let non_driver = self.non_driver.clone(); + let proposal_exe_infos = block.proposals().clone(); + + async_std::task::spawn(async move { + let proposals = futures::future::join_all( + proposal_exe_infos + .iter() + .map(|proposal| non_driver.get_proposal(&proposal.proposal, None)), + ) + .await; + + for i in 0..proposal_exe_infos.len() { + let proposal = proposals.get(i).unwrap(); + if proposal.is_err() { + continue; + } + let proposal = proposal.as_ref().unwrap(); + let proposer = proposal.desc().owner(); + if proposer.is_none() { + continue; + } + + let proposer = proposer.as_ref().unwrap(); + let exe_info = proposal_exe_infos.get(i).unwrap(); + + let receipt = match exe_info.receipt.as_ref() { + Some(receipt) => match NONObjectInfo::raw_decode(receipt.as_slice()) { + Ok((obj, _)) => Some(obj), + _ => continue, + }, + None => None, + }; + + network_sender + .post_message( + HotstuffMessage::ProposalResult(exe_info.proposal, Ok(receipt)), + rpath.clone(), + &proposer, + ) + .await + } + }); } async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { @@ -711,18 +776,27 @@ impl Hotstuff { } for proposal in time_adjust_proposals { - // TODO: 矫正系统时间 - // self.notify_proposal_result(&proposal, result); + // timestamp is error + self.notify_proposal_result( + &proposal, + Err(BuckyError::new( + BuckyErrorCode::ErrorTimestamp, + "error timestamp", + )), + ); } for proposal in timeout_proposals { - // TODO: 超时 - // self.notify_proposal_result(&proposal, result); + // has timeout + self.notify_proposal_result( + &proposal, + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + ); } - for proposal in failed_proposals { - // TODO: 执行失败 - // self.notify_proposal_result(&proposal, result) + for (proposal, err) in failed_proposals { + // failed + self.notify_proposal_result(&proposal, Err(err)) } PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, remove_proposals).await; @@ -739,9 +813,7 @@ impl Hotstuff { .map(|(proposal, exe_result)| GroupConsensusBlockProposal { proposal: proposal.id(), result_state: exe_result.result_state_id, - receipt: exe_result - .receipt - .map_or(vec![], |receipt| receipt.object_raw), + receipt: exe_result.receipt.map(|receipt| receipt.to_vec().unwrap()), context: exe_result.context, }) .collect(); diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 58ea4d39f..94a40aab7 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -199,7 +199,7 @@ impl Synchronizer { let rpath = self.rpath.clone(); async_std::task::spawn(async move { futures::future::join_all(blocks.into_iter().map(|block| { - network_sender.post_package(HotstuffMessage::Block(block), rpath.clone(), &remote) + network_sender.post_message(HotstuffMessage::Block(block), rpath.clone(), &remote) })) .await; }); @@ -297,7 +297,7 @@ impl RequestSendInfo { let msg = HotstuffMessage::SyncRequest(self.min_bound, self.max_bound); let remote = resend_info.cmd.2; let sender = sender.clone(); - async_std::task::spawn(async move { sender.post_package(msg, rpath, &remote).await }); + async_std::task::spawn(async move { sender.post_message(msg, rpath, &remote).await }); if resend_info.send_times >= SYNCHRONIZER_TRY_TIMES { self.resends.remove(max_send_info_pos); @@ -438,8 +438,8 @@ impl SynchronizerRunner { fn filter_outorder_blocks( &self, - mut min_height: u64, - mut max_bound: SyncBound, + min_height: u64, + max_bound: SyncBound, ) -> Vec<(u64, SyncBound)> { // TODO: limit the lenght of per range let mut last_range = Some((SyncBound::Height(min_height), max_bound)); diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 451044820..fbee051a5 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -16,3 +16,4 @@ pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 377275bef..f476b915c 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -3,7 +3,7 @@ use cyfs_core::GroupProposal; use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] -pub trait DelegateFactory { +pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( &self, group: &Group, @@ -23,7 +23,7 @@ pub trait DelegateFactory { pub struct ExecuteResult { pub result_state_id: ObjectId, // pack block pub receipt: Option, // to client - pub context: Vec, // timestamp etc. + pub context: Option>, // timestamp etc. } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 807a8934a..46f641b90 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -1,23 +1,110 @@ -use cyfs_base::BuckyResult; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath, GroupRPathStatus}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{ + GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath, GroupRPathStatus, +}; use cyfs_lib::NONObjectInfo; -pub struct RPathClient {} +use crate::CLIENT_POLL_TIMEOUT; + +pub struct RPathClient { + rpath: GroupRPath, + local_id: ObjectId, + non_driver: crate::network::NonDriver, + network_sender: crate::network::Sender, + network_listener: crate::network::Listener, +} impl RPathClient { - pub fn new() -> Self { - Self {} + pub fn new( + rpath: GroupRPath, + local_id: ObjectId, + non_driver: crate::network::NonDriver, + network_sender: crate::network::Sender, + network_listener: crate::network::Listener, + ) -> Self { + Self { + rpath, + non_driver, + network_sender, + network_listener, + local_id, + } } pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.rpath } pub async fn post_proposal( &self, - proposal: GroupProposal, + proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + // TODO: signature + let group = self + .non_driver + .get_group(proposal.r_path().group_id(), None) + .await?; + let admins = group.select_members_with_distance(&self.local_id, GroupMemberScope::Admin); + let proposal_id = proposal.desc().object_id(); + let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); + + let waiter = self + .network_listener + .wait_proposal_result(proposal_id) + .await?; + let mut waiter_future = Some(waiter.wait()); + + let mut post_result = None; // Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")); + let mut exe_result = None; + + for admin in admins { + match self + .non_driver + .post_object(non_proposal.clone(), admin) + .await + { + Ok(r) => post_result = Some(Ok(())), + Err(e) => { + if post_result.is_none() { + post_result = Some(Err(e)); + } + continue; + } + } + + match futures::future::select( + waiter_future.take().unwrap(), + Box::pin(async_std::task::sleep(CLIENT_POLL_TIMEOUT)), + ) + .await + { + futures::future::Either::Left((result, _)) => match result { + Err(_) => return Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown")), + Ok(result) => match result { + Ok(result) => return Ok(result), + Err(e) => exe_result = Some(e), + }, + }, + futures::future::Either::Right((_, waiter)) => { + waiter_future = Some(waiter); + } + } + } + + post_result.map_or( + Err(BuckyError::new(BuckyErrorCode::InvalidTarget, "no admin")), + |result| match result { + Ok(_) => { + let err = exe_result + .map_or(BuckyError::new(BuckyErrorCode::Timeout, "timeout"), |e| e); + Err(err) + } + Err(e) => Err(e), + }, + ) } pub async fn get_field(&self, sub_path: &str) -> BuckyResult { diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 8430fbc0c..dede06f77 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -10,15 +10,13 @@ type ByDec = HashMap; type ByGroup = HashMap; pub struct GroupRPathMgr { - dec_id: DecAppId, by_group: ByGroup, } impl GroupRPathMgr { - pub fn new(dec_id: DecAppId) -> Self { + pub fn new() -> Self { Self { by_group: ByGroup::default(), - dec_id, } } @@ -30,32 +28,47 @@ impl GroupRPathMgr { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn register( + &self, + dec_id: DecAppId, + delegate_factory: Box, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { unimplemented!() } pub async fn find_rpath_control( &self, group_id: &GroupId, + dec_id: &DecAppId, rpath: &str, is_auto_create: IsCreateRPath, ) -> BuckyResult { unimplemented!() } - pub async fn rpath_client(&self, group_id: &GroupId, rpath: &str) -> BuckyResult { + pub async fn rpath_client( + &self, + group_id: &GroupId, + dec_id: &DecAppId, + rpath: &str, + ) -> BuckyResult { unimplemented!() } pub async fn rpath_control( &self, group_id: &GroupId, + dec_id: &DecAppId, rpath: &str, ) -> BuckyResult { unimplemented!() } - pub async fn set_sync_path(&self, path: String) -> BuckyResult<()> { + pub async fn set_sync_path(&self, dec_id: &str, path: String) -> BuckyResult<()> { unimplemented!() } diff --git a/src/component/cyfs-group/src/group_dec_mgr.rs b/src/component/cyfs-group/src/group_dec_mgr.rs deleted file mode 100644 index b78a6f801..000000000 --- a/src/component/cyfs-group/src/group_dec_mgr.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::collections::HashMap; - -use cyfs_base::BuckyResult; -use cyfs_core::DecAppId; - -use crate::GroupRPathMgr; - -type ByDec = HashMap>; - -pub struct RPathControlMgr { - by_dec: ByDec, -} - -impl RPathControlMgr { - pub async fn start(&self) -> BuckyResult { - unimplemented!() - } - - pub async fn close(&self) -> BuckyResult<()> { - unimplemented!() - } - - pub async fn create_rpath_mgr_with_dec_id( - &self, - dec_id: &DecAppId, - ) -> BuckyResult { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index c47829954..1607a8596 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -2,7 +2,6 @@ mod consensus; mod constant; mod crypto; mod dec; -mod group_dec_mgr; mod network; mod objects; mod statepath; @@ -13,7 +12,6 @@ pub use consensus::*; pub use constant::*; pub(crate) use crypto::*; pub use dec::*; -pub use group_dec_mgr::*; pub(crate) use network::*; pub use objects::*; pub use statepath::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index badd0969e..0bc3e67b1 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -1,9 +1,46 @@ +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_bdt::Stack; +use cyfs_core::GroupRPath; +use cyfs_lib::NONObjectInfo; -pub struct Listener {} +use crate::CHANNEL_CAPACITY; + +pub struct ReplyWaiter { + rx: async_std::channel::Receiver, + seq: u64, +} + +impl ReplyWaiter { + pub fn wait(&self) -> async_std::channel::Recv<'_, T> { + self.rx.recv() + } +} + +impl Drop for ReplyWaiter { + fn drop(&mut self) { + todo!("distach the tx") + } +} + +pub struct Listener { + wait_seq: u64, +} impl Listener { pub fn new(vport: u16, bdt_stack: Stack) {} pub fn listen(&self) {} -} \ No newline at end of file + + pub async fn wait_proposal_result( + &self, + proposal_id: ObjectId, + ) -> BuckyResult>>> { + let (tx_proposal_result, rx_proposal_result) = + async_std::channel::bounded::>>(CHANNEL_CAPACITY); + unimplemented!() + } + + pub async fn wait_query_state(&self, rpath: GroupRPath) -> BuckyResult<()> { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 6bf32917e..34a928f6e 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,7 +1,8 @@ -use cyfs_base::{BuckyResult, ObjectId, RawDecode}; -use cyfs_core::GroupConsensusBlock; +use cyfs_base::{BuckyResult, Group, ObjectId, RawDecode}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; +#[derive(Clone)] pub struct NonDriver {} impl NonDriver { @@ -31,4 +32,23 @@ impl NonDriver { assert_eq!(remain.len(), 0); Ok(block) } + + pub async fn get_proposal( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupProposal::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn get_group( + &self, + group_id: &ObjectId, + group_chunk_id: Option<&ObjectId>, + ) -> BuckyResult { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index f26829c84..d721670cc 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -10,7 +10,7 @@ pub struct Sender {} impl Sender { pub fn new(vport: u16, bdt_stack: Stack) {} - pub(crate) async fn post_package( + pub(crate) async fn post_message( &self, msg: HotstuffMessage, rpath: GroupRPath, diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group/src/objects/group_decide_proposal.rs index 4b6c7c62b..6eb9b9027 100644 --- a/src/component/cyfs-group/src/objects/group_decide_proposal.rs +++ b/src/component/cyfs-group/src/objects/group_decide_proposal.rs @@ -80,6 +80,7 @@ impl GroupDecideProposalBuilder { Some(param_vec), None, None, + owner, None, None, None, diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group/src/objects/group_update_proposal.rs index c7aaebabe..f06d876b9 100644 --- a/src/component/cyfs-group/src/objects/group_update_proposal.rs +++ b/src/component/cyfs-group/src/objects/group_update_proposal.rs @@ -21,6 +21,7 @@ impl GroupUpdateProposal { pub fn create( from_group_chunk_id: Option, to_group: Group, + owner: ObjectId, target_dec_id: Vec, meta_block_id: Option, effective_begining: Option, @@ -29,6 +30,7 @@ impl GroupUpdateProposal { GroupUpdateProposalBuilder::create( from_group_chunk_id, to_group, + owner, target_dec_id, meta_block_id, effective_begining, @@ -38,6 +40,7 @@ impl GroupUpdateProposal { pub fn create_new_group( to_group: Group, + owner: ObjectId, target_dec_id: Vec, meta_block_id: Option, effective_begining: Option, @@ -46,6 +49,7 @@ impl GroupUpdateProposal { GroupUpdateProposalBuilder::create( None, to_group, + owner, target_dec_id, meta_block_id, effective_begining, @@ -157,6 +161,7 @@ impl GroupUpdateProposalBuilder { pub fn create( from_group_chunk_id: Option, to_group: Group, + owner: ObjectId, target_dec_id: Vec, meta_block_id: Option, effective_begining: Option, @@ -193,6 +198,7 @@ impl GroupUpdateProposalBuilder { Some(param_vec), Some(group_chunk_vec), None, + owner, meta_block_id, effective_begining, effective_ending, @@ -208,6 +214,7 @@ impl GroupUpdateProposalBuilder { pub fn create_new_group( to_group: Group, + owner: ObjectId, target_dec_id: Vec, meta_block_id: Option, effective_begining: Option, @@ -216,6 +223,7 @@ impl GroupUpdateProposalBuilder { Self::create( None, to_group, + owner, target_dec_id, meta_block_id, effective_begining, diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index c99bd1220..0d04df1fa 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -93,7 +93,7 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) - ProposalResult(ObjectId, NONObjectInfo), // (proposal-id, ExecuteResult) + ProposalResult(ObjectId, BuckyResult>), // (proposal-id, ExecuteResult) QueryState(String), VerifiableState(GroupRPathStatus), } @@ -104,7 +104,17 @@ pub(crate) enum HotstuffPackage { BlockVote(ProtocolAddress, HotstuffBlockQCVote), TimeoutVote(ProtocolAddress, HotstuffTimeoutVote), Timeout(ProtocolAddress, cyfs_core::HotstuffTimeout), - SyncRequest(ProtocolAddress, SyncBound, SyncBound), + + SyncRequest(SyncBound, SyncBound), + + StateChangeNotify(ProtocolAddress, GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + ProposalResult( + ProtocolAddress, + ObjectId, + BuckyResult>, + ), // (proposal-id, ExecuteResult) + QueryState(ProtocolAddress, String), + VerifiableState(ProtocolAddress, GroupRPathStatus), } #[derive(Clone, RawEncode, RawDecode)] From 405d740a1dde05ab33cf2fc5351af1fbc4356725 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 12 Jan 2023 21:32:51 +0800 Subject: [PATCH 025/553] state change notify --- .../src/consensus/hotstuff/hotstuff.rs | 3 +- src/component/cyfs-group/src/consensus/mod.rs | 1 - .../consensus/synchronizer/synchronizer.rs | 2 +- src/component/cyfs-group/src/constant.rs | 1 + .../src/dec_state/change_notifier.rs | 319 ++++++++++++++++++ .../cyfs-group/src/dec_state/dec_state_mgr.rs | 1 + src/component/cyfs-group/src/dec_state/mod.rs | 5 + src/component/cyfs-group/src/helper/mod.rs | 3 + .../src/{consensus => helper}/timer.rs | 0 src/component/cyfs-group/src/lib.rs | 4 + 10 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-group/src/dec_state/change_notifier.rs create mode 100644 src/component/cyfs-group/src/dec_state/dec_state_mgr.rs create mode 100644 src/component/cyfs-group/src/dec_state/mod.rs create mode 100644 src/component/cyfs-group/src/helper/mod.rs rename src/component/cyfs-group/src/{consensus => helper}/timer.rs (100%) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e0f058697..dd93a4f8d 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -14,7 +14,8 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{proposal, synchronizer::Synchronizer, timer::Timer}, + consensus::{proposal, synchronizer::Synchronizer}, + helper::Timer, network, AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, diff --git a/src/component/cyfs-group/src/consensus/mod.rs b/src/component/cyfs-group/src/consensus/mod.rs index d7e8bd804..15810090f 100644 --- a/src/component/cyfs-group/src/consensus/mod.rs +++ b/src/component/cyfs-group/src/consensus/mod.rs @@ -1,7 +1,6 @@ mod hotstuff; mod proposal; mod synchronizer; -mod timer; mod vote; pub use hotstuff::*; diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 94a40aab7..179d1b149 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -11,7 +11,7 @@ use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; use crate::{ - consensus::timer::Timer, storage::Storage, HotstuffMessage, SyncBound, CHANNEL_CAPACITY, + helper::Timer, storage::Storage, HotstuffMessage, SyncBound, CHANNEL_CAPACITY, SYNCHRONIZER_TIMEOUT, SYNCHRONIZER_TRY_TIMES, }; diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index fbee051a5..b2acf3b33 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,3 +17,4 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const STATE_NOTIFY_CYCLE: u64 = 8000; diff --git a/src/component/cyfs-group/src/dec_state/change_notifier.rs b/src/component/cyfs-group/src/dec_state/change_notifier.rs new file mode 100644 index 000000000..23b90d1df --- /dev/null +++ b/src/component/cyfs-group/src/dec_state/change_notifier.rs @@ -0,0 +1,319 @@ +// notify the members when the state of rpath changed + +use cyfs_base::{ + BuckyResult, Group, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawDecode, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; +use cyfs_lib::NONObjectInfo; +use futures::FutureExt; + +use crate::{ + helper::Timer, HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_CYCLE, SYNCHRONIZER_TIMEOUT, +}; + +enum StateChangeNotifyMessage { + ProposalResult(GroupProposal, BuckyResult>), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), +} + +pub struct StateChangeNotifier { + local_id: ObjectId, + tx_notifier: async_std::channel::Sender, +} + +impl StateChangeNotifier { + pub fn new( + local_id: ObjectId, + network_sender: crate::network::Sender, + rpath: GroupRPath, + non_driver: crate::network::NonDriver, + ) -> Self { + let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); + + let mut runner = StateChanggeRunner::new(local_id, network_sender, rpath, non_driver, rx); + + async_std::task::spawn(async move { runner.run().await }); + + Self { + local_id, + tx_notifier: tx, + } + } + + pub async fn notify_proposal_result( + &self, + proposal: GroupProposal, + result: BuckyResult>, + ) { + self.tx_notifier + .send(StateChangeNotifyMessage::ProposalResult(proposal, result)) + .await; + } + + pub async fn notify_block_commit( + &self, + block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + ) { + let block_id = block.named_object().desc().object_id(); + if qc_block.height() != block.height() + 1 + || qc_block.round() <= block.round() + || qc_block.prev_block_id().unwrap() != &block_id + { + log::error!( + "the qc-block({}) should be next block({})", + qc_block.named_object().desc().object_id(), + block_id + ); + return; + } + + if block.owner() != &self.local_id { + return; + } + + self.tx_notifier + .send(StateChangeNotifyMessage::BlockCommit(block, qc_block)) + .await; + } +} + +struct HeaderBlockNotifyProgress { + header_block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + group_chunk_id: ObjectId, + members: Vec, + total_notify_times: usize, + cur_block_notify_times: usize, +} + +struct StateChanggeRunner { + local_id: ObjectId, + network_sender: crate::network::Sender, + rpath: GroupRPath, + non_driver: crate::network::NonDriver, + rx_notifier: async_std::channel::Receiver, + timer: Timer, + + notify_progress: Option, +} + +impl StateChanggeRunner { + fn new( + local_id: ObjectId, + network_sender: crate::network::Sender, + rpath: GroupRPath, + non_driver: crate::network::NonDriver, + rx_notifier: async_std::channel::Receiver, + ) -> Self { + Self { + network_sender, + rpath, + non_driver, + rx_notifier, + timer: Timer::new(SYNCHRONIZER_TIMEOUT), + notify_progress: None, + local_id, + } + } + pub async fn notify_proposal_result( + &self, + proposal: GroupProposal, + result: BuckyResult>, + ) { + // notify to the proposer + let proposal_id = proposal.desc().object_id(); + match proposal.desc().owner() { + Some(proposer) => { + let network_sender = self.network_sender.clone(); + let proposer = proposer.clone(); + let rpath = self.rpath.clone(); + + network_sender + .post_message( + HotstuffMessage::ProposalResult(proposal_id, result), + rpath.clone(), + &proposer, + ) + .await + } + None => log::warn!("proposal({}) without owner", proposal_id), + } + } + + pub async fn notify_proposal_result_for_block(&self, block: GroupConsensusBlock) { + let network_sender = self.network_sender.clone(); + let rpath = self.rpath.clone(); + let non_driver = self.non_driver.clone(); + let proposal_exe_infos = block.proposals().clone(); + + let proposals = futures::future::join_all( + proposal_exe_infos + .iter() + .map(|proposal| non_driver.get_proposal(&proposal.proposal, None)), + ) + .await; + + for i in 0..proposal_exe_infos.len() { + let proposal = proposals.get(i).unwrap(); + if proposal.is_err() { + continue; + } + let proposal = proposal.as_ref().unwrap(); + let proposer = proposal.desc().owner(); + if proposer.is_none() { + continue; + } + + let proposer = proposer.as_ref().unwrap(); + let exe_info = proposal_exe_infos.get(i).unwrap(); + + let receipt = match exe_info.receipt.as_ref() { + Some(receipt) => match NONObjectInfo::raw_decode(receipt.as_slice()) { + Ok((obj, _)) => Some(obj), + _ => continue, + }, + None => None, + }; + + network_sender + .post_message( + HotstuffMessage::ProposalResult(exe_info.proposal, Ok(receipt)), + rpath.clone(), + &proposer, + ) + .await + } + } + + async fn update_commit_block( + &mut self, + block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + ) { + match self.notify_progress.as_mut() { + Some(progress) => { + if progress.header_block.height() >= block.height() { + return; + } + + if block.group_chunk_id() != progress.header_block.group_chunk_id() { + let group = self + .non_driver + .get_group(block.r_path().group_id(), Some(block.group_chunk_id())) + .await; + if group.is_err() { + return; + } + progress.members = group + .unwrap() + .select_members_with_distance(&self.local_id, GroupMemberScope::All) + .into_iter() + .map(|id| id.clone()) + .collect(); + } + + progress.group_chunk_id = block.group_chunk_id().clone(); + progress.total_notify_times += progress.cur_block_notify_times; + progress.cur_block_notify_times = 0; + progress.header_block = block; + progress.qc_block = qc_block; + } + None => { + let group = self + .non_driver + .get_group(block.r_path().group_id(), Some(block.group_chunk_id())) + .await; + if group.is_err() { + return; + } + + let members: Vec = group + .unwrap() + .select_members_with_distance(&self.local_id, GroupMemberScope::All) + .into_iter() + .map(|id| id.clone()) + .collect(); + let total_notify_times = match members.iter().position(|id| id == &self.local_id) { + Some(pos) => pos, + None => return, + }; + + let group_chunk_id = block.group_chunk_id().clone(); + + self.notify_progress = Some(HeaderBlockNotifyProgress { + header_block: block, + qc_block, + group_chunk_id, + members, + total_notify_times, + cur_block_notify_times: 0, + }); + } + } + } + + async fn try_notify_block_commit(&mut self) { + match self.notify_progress.as_mut() { + Some(progress) if progress.cur_block_notify_times < progress.members.len() => { + let notify_count = (progress.members.len() * SYNCHRONIZER_TIMEOUT as usize + / STATE_NOTIFY_CYCLE as usize) + .max(1) + .min(progress.members.len() - progress.cur_block_notify_times); + + progress.cur_block_notify_times += notify_count; + + let start_pos = progress.cur_block_notify_times % progress.members.len(); + let notify_targets = &progress.members.as_slice() + [start_pos..progress.members.len().min(start_pos + notify_count)]; + + self.network_sender + .broadcast( + HotstuffMessage::StateChangeNotify( + progress.header_block.clone(), + progress.qc_block.clone(), + ), + self.rpath.clone(), + notify_targets, + ) + .await; + + if notify_targets.len() < notify_count { + let notify_targets = + &progress.members.as_slice()[0..notify_count - notify_targets.len()]; + + self.network_sender + .broadcast( + HotstuffMessage::StateChangeNotify( + progress.header_block.clone(), + progress.qc_block.clone(), + ), + self.rpath.clone(), + notify_targets, + ) + .await; + } + } + _ => return, + } + } + + async fn run(&mut self) { + loop { + futures::select! { + message = self.rx_notifier.recv().fuse() => match message { + Ok(StateChangeNotifyMessage::ProposalResult(proposal, result)) => self.notify_proposal_result(proposal, result).await, + Ok(StateChangeNotifyMessage::BlockCommit(block, qc_block)) => { + self.notify_proposal_result_for_block(block.clone()).await; + self.update_commit_block(block, qc_block).await; + }, + Err(e) => { + log::warn!("[change-notifier] rx_notifier closed.") + }, + }, + () = self.timer.wait_next().fuse() => self.try_notify_block_commit().await, + }; + } + } +} diff --git a/src/component/cyfs-group/src/dec_state/dec_state_mgr.rs b/src/component/cyfs-group/src/dec_state/dec_state_mgr.rs new file mode 100644 index 000000000..1f0c995a4 --- /dev/null +++ b/src/component/cyfs-group/src/dec_state/dec_state_mgr.rs @@ -0,0 +1 @@ +// the manager of the DEC's state that synchronized from the group's rpath diff --git a/src/component/cyfs-group/src/dec_state/mod.rs b/src/component/cyfs-group/src/dec_state/mod.rs new file mode 100644 index 000000000..0e29b9ecd --- /dev/null +++ b/src/component/cyfs-group/src/dec_state/mod.rs @@ -0,0 +1,5 @@ +mod change_notifier; +mod dec_state_mgr; + +pub(crate) use change_notifier::*; +pub(crate) use dec_state_mgr::*; diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs new file mode 100644 index 000000000..4d3f1b1c6 --- /dev/null +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -0,0 +1,3 @@ +mod timer; + +pub use timer::*; diff --git a/src/component/cyfs-group/src/consensus/timer.rs b/src/component/cyfs-group/src/helper/timer.rs similarity index 100% rename from src/component/cyfs-group/src/consensus/timer.rs rename to src/component/cyfs-group/src/helper/timer.rs diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index 1607a8596..85b39d9c9 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -2,6 +2,8 @@ mod consensus; mod constant; mod crypto; mod dec; +mod dec_state; +mod helper; mod network; mod objects; mod statepath; @@ -12,6 +14,8 @@ pub use consensus::*; pub use constant::*; pub(crate) use crypto::*; pub use dec::*; +pub(crate) use dec_state::*; +pub(crate) use helper::*; pub(crate) use network::*; pub use objects::*; pub use statepath::*; From e4a62739448b2963bb768351bce76539b20ee183 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 13 Jan 2023 15:36:07 +0800 Subject: [PATCH 026/553] request last state --- .../src/consensus/hotstuff/hotstuff.rs | 111 +++++------------- src/component/cyfs-group/src/dec_state/mod.rs | 4 +- .../{change_notifier.rs => state_pusher.rs} | 87 ++++++++------ .../cyfs-group/src/objects/protocol.rs | 1 + 4 files changed, 85 insertions(+), 118 deletions(-) rename src/component/cyfs-group/src/dec_state/{change_notifier.rs => state_pusher.rs} (79%) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index dd93a4f8d..57c7d245f 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -14,11 +14,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{proposal, synchronizer::Synchronizer}, - helper::Timer, - network, AsProposal, Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, - HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, - VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + consensus::synchronizer::Synchronizer, dec_state::StatePusher, helper::Timer, AsProposal, + Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, + CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; /** @@ -46,6 +45,7 @@ pub(crate) struct Hotstuff { tx_message_inner: Sender<(GroupConsensusBlock, ObjectId)>, rx_message_inner: Receiver<(GroupConsensusBlock, ObjectId)>, rx_proposal_waiter: Option<(Receiver, u64)>, + state_pusher: StatePusher, } impl Hotstuff { @@ -83,6 +83,13 @@ impl Hotstuff { tx_message_inner.clone(), ); + let state_pusher = StatePusher::new( + local_id, + network_sender.clone(), + rpath.clone(), + non_driver.clone(), + ); + let mut hotstuff = Self { local_id, committee, @@ -103,6 +110,7 @@ impl Hotstuff { rx_message_inner, rx_proposal_waiter: None, tc: None, + state_pusher, }; async_std::task::spawn(async move { hotstuff.run().await }); @@ -324,7 +332,16 @@ impl Hotstuff { * */ self.cleanup_proposal(&header_block).await; - self.notify_proposal_result_for_block(&header_block); + let (_, qc_block) = self + .store + .pre_commits() + .iter() + .next() + .expect("the pre-commit block must exist."); + + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await } match self.vote_mgr.add_voting_block(block).await { @@ -395,82 +412,14 @@ impl Hotstuff { PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, proposals).await } - fn notify_proposal_result( + async fn notify_proposal_result( &self, proposal: &GroupProposal, result: BuckyResult>, ) { - // notify to the proposer - let proposal_id = proposal.desc().object_id(); - match proposal.desc().owner() { - Some(proposer) => { - let network_sender = self.network_sender.clone(); - let proposer = proposer.clone(); - let rpath = self.rpath.clone(); - - async_std::task::spawn(async move { - network_sender - .post_message( - HotstuffMessage::ProposalResult(proposal_id, result), - rpath.clone(), - &proposer, - ) - .await - }); - } - None => log::warn!("proposal({}) without owner", proposal_id), - } - } - - fn notify_proposal_result_for_block(&self, block: &GroupConsensusBlock) { - if block.owner() == &self.local_id { - return; - } - - let network_sender = self.network_sender.clone(); - let rpath = self.rpath.clone(); - let non_driver = self.non_driver.clone(); - let proposal_exe_infos = block.proposals().clone(); - - async_std::task::spawn(async move { - let proposals = futures::future::join_all( - proposal_exe_infos - .iter() - .map(|proposal| non_driver.get_proposal(&proposal.proposal, None)), - ) + self.state_pusher + .notify_proposal_result(proposal.clone(), result) .await; - - for i in 0..proposal_exe_infos.len() { - let proposal = proposals.get(i).unwrap(); - if proposal.is_err() { - continue; - } - let proposal = proposal.as_ref().unwrap(); - let proposer = proposal.desc().owner(); - if proposer.is_none() { - continue; - } - - let proposer = proposer.as_ref().unwrap(); - let exe_info = proposal_exe_infos.get(i).unwrap(); - - let receipt = match exe_info.receipt.as_ref() { - Some(receipt) => match NONObjectInfo::raw_decode(receipt.as_slice()) { - Ok((obj, _)) => Some(obj), - _ => continue, - }, - None => None, - }; - - network_sender - .post_message( - HotstuffMessage::ProposalResult(exe_info.proposal, Ok(receipt)), - rpath.clone(), - &proposer, - ) - .await - } - }); } async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { @@ -784,7 +733,8 @@ impl Hotstuff { BuckyErrorCode::ErrorTimestamp, "error timestamp", )), - ); + ) + .await; } for proposal in timeout_proposals { @@ -792,12 +742,13 @@ impl Hotstuff { self.notify_proposal_result( &proposal, Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), - ); + ) + .await; } for (proposal, err) in failed_proposals { // failed - self.notify_proposal_result(&proposal, Err(err)) + self.notify_proposal_result(&proposal, Err(err)).await; } PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, remove_proposals).await; diff --git a/src/component/cyfs-group/src/dec_state/mod.rs b/src/component/cyfs-group/src/dec_state/mod.rs index 0e29b9ecd..410e8244f 100644 --- a/src/component/cyfs-group/src/dec_state/mod.rs +++ b/src/component/cyfs-group/src/dec_state/mod.rs @@ -1,5 +1,5 @@ -mod change_notifier; +mod state_pusher; mod dec_state_mgr; -pub(crate) use change_notifier::*; +pub(crate) use state_pusher::*; pub(crate) use dec_state_mgr::*; diff --git a/src/component/cyfs-group/src/dec_state/change_notifier.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs similarity index 79% rename from src/component/cyfs-group/src/dec_state/change_notifier.rs rename to src/component/cyfs-group/src/dec_state/state_pusher.rs index 23b90d1df..222856a01 100644 --- a/src/component/cyfs-group/src/dec_state/change_notifier.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -1,8 +1,9 @@ // notify the members when the state of rpath changed +use std::collections::HashSet; + use cyfs_base::{ - BuckyResult, Group, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawDecode, + BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; use cyfs_lib::NONObjectInfo; @@ -12,17 +13,18 @@ use crate::{ helper::Timer, HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_CYCLE, SYNCHRONIZER_TIMEOUT, }; -enum StateChangeNotifyMessage { +enum StatePushMessage { ProposalResult(GroupProposal, BuckyResult>), BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + LastStateRequest(ObjectId), } -pub struct StateChangeNotifier { +pub struct StatePusher { local_id: ObjectId, - tx_notifier: async_std::channel::Sender, + tx_notifier: async_std::channel::Sender, } -impl StateChangeNotifier { +impl StatePusher { pub fn new( local_id: ObjectId, network_sender: crate::network::Sender, @@ -47,7 +49,7 @@ impl StateChangeNotifier { result: BuckyResult>, ) { self.tx_notifier - .send(StateChangeNotifyMessage::ProposalResult(proposal, result)) + .send(StatePushMessage::ProposalResult(proposal, result)) .await; } @@ -74,7 +76,13 @@ impl StateChangeNotifier { } self.tx_notifier - .send(StateChangeNotifyMessage::BlockCommit(block, qc_block)) + .send(StatePushMessage::BlockCommit(block, qc_block)) + .await; + } + + pub async fn last_state_request(&self, remote: ObjectId) { + self.tx_notifier + .send(StatePushMessage::LastStateRequest(remote)) .await; } } @@ -93,9 +101,10 @@ struct StateChanggeRunner { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NonDriver, - rx_notifier: async_std::channel::Receiver, + rx_notifier: async_std::channel::Receiver, timer: Timer, + last_state_request_remotes: HashSet, notify_progress: Option, } @@ -105,7 +114,7 @@ impl StateChanggeRunner { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NonDriver, - rx_notifier: async_std::channel::Receiver, + rx_notifier: async_std::channel::Receiver, ) -> Self { Self { network_sender, @@ -115,6 +124,7 @@ impl StateChanggeRunner { timer: Timer::new(SYNCHRONIZER_TIMEOUT), notify_progress: None, local_id, + last_state_request_remotes: HashSet::new(), } } pub async fn notify_proposal_result( @@ -254,6 +264,10 @@ impl StateChanggeRunner { } } + fn last_state_request(&mut self, remote: ObjectId) { + self.last_state_request_remotes.insert(remote); + } + async fn try_notify_block_commit(&mut self) { match self.notify_progress.as_mut() { Some(progress) if progress.cur_block_notify_times < progress.members.len() => { @@ -264,36 +278,35 @@ impl StateChanggeRunner { progress.cur_block_notify_times += notify_count; + let mut notify_targets = HashSet::new(); + std::mem::swap(&mut self.last_state_request_remotes, &mut notify_targets); + let start_pos = progress.cur_block_notify_times % progress.members.len(); - let notify_targets = &progress.members.as_slice() + let notify_targets_1 = &progress.members.as_slice() [start_pos..progress.members.len().min(start_pos + notify_count)]; - self.network_sender - .broadcast( - HotstuffMessage::StateChangeNotify( - progress.header_block.clone(), - progress.qc_block.clone(), - ), - self.rpath.clone(), - notify_targets, - ) - .await; + notify_targets_1.iter().for_each(|remote| { + notify_targets.insert(remote.clone()); + }); - if notify_targets.len() < notify_count { - let notify_targets = + if notify_targets_1.len() < notify_count { + let notify_targets_2 = &progress.members.as_slice()[0..notify_count - notify_targets.len()]; - self.network_sender - .broadcast( - HotstuffMessage::StateChangeNotify( - progress.header_block.clone(), - progress.qc_block.clone(), - ), - self.rpath.clone(), - notify_targets, - ) - .await; + notify_targets_2.iter().for_each(|remote| { + notify_targets.insert(remote.clone()); + }); } + + let msg = HotstuffMessage::StateChangeNotify( + progress.header_block.clone(), + progress.qc_block.clone(), + ); + + let notify_targets: Vec = notify_targets.into_iter().collect(); + self.network_sender + .broadcast(msg.clone(), self.rpath.clone(), notify_targets.as_slice()) + .await; } _ => return, } @@ -303,12 +316,14 @@ impl StateChanggeRunner { loop { futures::select! { message = self.rx_notifier.recv().fuse() => match message { - Ok(StateChangeNotifyMessage::ProposalResult(proposal, result)) => self.notify_proposal_result(proposal, result).await, - Ok(StateChangeNotifyMessage::BlockCommit(block, qc_block)) => { + Ok(StatePushMessage::ProposalResult(proposal, result)) => self.notify_proposal_result(proposal, result).await, + Ok(StatePushMessage::BlockCommit(block, qc_block)) => { self.notify_proposal_result_for_block(block.clone()).await; self.update_commit_block(block, qc_block).await; }, - Err(e) => { + Ok(StatePushMessage::LastStateRequest(remote)) => { + self.last_state_request(remote); + }, Err(e) => { log::warn!("[change-notifier] rx_notifier closed.") }, }, diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 0d04df1fa..8f21c38ec 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -92,6 +92,7 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), + LastStateRequest, StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) ProposalResult(ObjectId, BuckyResult>), // (proposal-id, ExecuteResult) QueryState(String), From e779cc39916606f2a4326b198629d983164cc793 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 13 Jan 2023 16:03:42 +0800 Subject: [PATCH 027/553] request last state --- src/Cargo.lock | 1 + src/component/cyfs-group/Cargo.toml | 1 + .../cyfs-group/src/dec/rpath_client.rs | 20 ++++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 026e4b4ed..a8bda21b4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1966,6 +1966,7 @@ dependencies = [ "protobuf", "protoc-bin-vendored", "protoc-rust", + "rand 0.8.5", "serde", "serde_json", "sha2 0.8.2", diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 1a2820c21..b22452ce8 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -25,6 +25,7 @@ protobuf = { version = '2', features = ['with-bytes'] } lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' +rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 46f641b90..64a3fa685 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -6,8 +6,9 @@ use cyfs_core::{ GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath, GroupRPathStatus, }; use cyfs_lib::NONObjectInfo; +use rand::Rng; -use crate::CLIENT_POLL_TIMEOUT; +use crate::{HotstuffMessage, CLIENT_POLL_TIMEOUT}; pub struct RPathClient { rpath: GroupRPath, @@ -107,6 +108,23 @@ impl RPathClient { ) } + // request last state from random admin + pub async fn refresh_state(&self) -> BuckyResult<()> { + let group = self + .non_driver + .get_group(&self.rpath.group_id(), None) + .await?; + + let admins = group.select_members_with_distance(&self.local_id, GroupMemberScope::Admin); + let random = rand::thread_rng().gen_range(0..admins.len()); + let admin = admins.get(random).unwrap().clone(); + + self.network_sender + .post_message(HotstuffMessage::LastStateRequest, self.rpath.clone(), admin) + .await; + Ok(()) + } + pub async fn get_field(&self, sub_path: &str) -> BuckyResult { unimplemented!() } From 67e88998f9b8fcd887aa21501115a133c72bb9bb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 13 Jan 2023 16:58:43 +0800 Subject: [PATCH 028/553] get_by_path(client) --- .../cyfs-core/src/group/group_rpath.rs | 2 +- .../cyfs-group/src/dec/rpath_client.rs | 49 +++++++++++++++++-- .../cyfs-group/src/network/listener.rs | 6 ++- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index a59aff5e3..b7a43bfc3 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,7 +1,7 @@ use cyfs_base::*; use serde::Serialize; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[derive(Clone, Debug, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize, PartialEq)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 64a3fa685..54cb8793d 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -43,6 +43,8 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { + assert_eq!(proposal.r_path(), &self.rpath); + // TODO: signature let group = self .non_driver @@ -58,7 +60,7 @@ impl RPathClient { .await?; let mut waiter_future = Some(waiter.wait()); - let mut post_result = None; // Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")); + let mut post_result = None; let mut exe_result = None; for admin in admins { @@ -125,8 +127,49 @@ impl RPathClient { Ok(()) } - pub async fn get_field(&self, sub_path: &str) -> BuckyResult { - unimplemented!() + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let group = self + .non_driver + .get_group(self.rpath().group_id(), None) + .await?; + + let members = group.select_members_with_distance(&self.local_id, GroupMemberScope::All); + let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); + + let waiter = self + .network_listener + .wait_query_state(sub_path.to_string(), self.rpath.clone()) + .await?; + let mut waiter_future = Some(waiter.wait()); + + let mut exe_result = None; + + for member in members { + self.network_sender + .post_message(req_msg.clone(), self.rpath.clone(), member) + .await; + + match futures::future::select( + waiter_future.take().unwrap(), + Box::pin(async_std::task::sleep(CLIENT_POLL_TIMEOUT)), + ) + .await + { + futures::future::Either::Left((result, _)) => match result { + Err(_) => return Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown")), + Ok(result) => match result { + Ok(result) => return Ok(result), + Err(e) => exe_result = Some(e), + }, + }, + futures::future::Either::Right((_, waiter)) => { + waiter_future = Some(waiter); + } + } + } + + let err = exe_result.map_or(BuckyError::new(BuckyErrorCode::Timeout, "timeout"), |e| e); + Err(err) } pub async fn get_block(&self, height: Option) -> BuckyResult { diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 0bc3e67b1..851c3c7c3 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -40,7 +40,11 @@ impl Listener { unimplemented!() } - pub async fn wait_query_state(&self, rpath: GroupRPath) -> BuckyResult<()> { + pub async fn wait_query_state( + &self, + sub_path: String, + rpath: GroupRPath, + ) -> BuckyResult>> { unimplemented!() } } From 6a4230bf03a1181291b252c132391ded292268e3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 13 Jan 2023 17:13:44 +0800 Subject: [PATCH 029/553] distinguish the state between group and dec --- .../cyfs-group/src/consensus/hotstuff/hotstuff.rs | 10 +++++----- .../src/consensus/synchronizer/synchronizer.rs | 4 ++-- .../cyfs-group/src/dec_state/dec_state_requestor.rs | 0 .../{dec_state_mgr.rs => dec_state_synchronizer.rs} | 2 ++ src/component/cyfs-group/src/dec_state/mod.rs | 6 ++++-- .../cyfs-group/src/statepath/dec_statepath.rs | 0 .../statepath/{statepath.rs => group_statepath.rs} | 0 src/component/cyfs-group/src/statepath/mod.rs | 6 ++++-- src/component/cyfs-group/src/storage/dec_storage.rs | 0 .../src/storage/{storage.rs => group_storage.rs} | 12 ++++++++---- src/component/cyfs-group/src/storage/mod.rs | 6 ++++-- 11 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 src/component/cyfs-group/src/dec_state/dec_state_requestor.rs rename src/component/cyfs-group/src/dec_state/{dec_state_mgr.rs => dec_state_synchronizer.rs} (67%) create mode 100644 src/component/cyfs-group/src/statepath/dec_statepath.rs rename src/component/cyfs-group/src/statepath/{statepath.rs => group_statepath.rs} (100%) create mode 100644 src/component/cyfs-group/src/storage/dec_storage.rs rename src/component/cyfs-group/src/storage/{storage.rs => group_storage.rs} (96%) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 57c7d245f..5336485e6 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -15,9 +15,9 @@ use futures::FutureExt; use crate::{ consensus::synchronizer::Synchronizer, dec_state::StatePusher, helper::Timer, AsProposal, - Committee, ExecuteResult, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, Storage, VoteMgr, VoteThresholded, - CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, + HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, VoteMgr, + VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; /** @@ -28,7 +28,7 @@ use crate::{ pub(crate) struct Hotstuff { local_id: ObjectId, committee: Committee, - store: Storage, + store: GroupStorage, signer: RsaCPUObjectSigner, round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 @@ -53,7 +53,7 @@ impl Hotstuff { pub async fn spawn( local_id: ObjectId, committee: Committee, - store: Storage, + store: GroupStorage, signer: RsaCPUObjectSigner, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 179d1b149..c9a3f4216 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -11,7 +11,7 @@ use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; use crate::{ - helper::Timer, storage::Storage, HotstuffMessage, SyncBound, CHANNEL_CAPACITY, + helper::Timer, storage::GroupStorage, HotstuffMessage, SyncBound, CHANNEL_CAPACITY, SYNCHRONIZER_TIMEOUT, SYNCHRONIZER_TRY_TIMES, }; @@ -119,7 +119,7 @@ impl Synchronizer { min_bound: SyncBound, max_bound: SyncBound, remote: ObjectId, - store: &Storage, + store: &GroupStorage, ) -> BuckyResult<()> { // TODO: combine the requests diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group/src/dec_state/dec_state_mgr.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs similarity index 67% rename from src/component/cyfs-group/src/dec_state/dec_state_mgr.rs rename to src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f0c995a4..6c37144ec 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_mgr.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -1 +1,3 @@ // the manager of the DEC's state that synchronized from the group's rpath + +pub struct DecStateSynchronizer {} diff --git a/src/component/cyfs-group/src/dec_state/mod.rs b/src/component/cyfs-group/src/dec_state/mod.rs index 410e8244f..4e009798e 100644 --- a/src/component/cyfs-group/src/dec_state/mod.rs +++ b/src/component/cyfs-group/src/dec_state/mod.rs @@ -1,5 +1,7 @@ +mod dec_state_requestor; +mod dec_state_synchronizer; mod state_pusher; -mod dec_state_mgr; +pub(crate) use dec_state_requestor::*; +pub(crate) use dec_state_synchronizer::*; pub(crate) use state_pusher::*; -pub(crate) use dec_state_mgr::*; diff --git a/src/component/cyfs-group/src/statepath/dec_statepath.rs b/src/component/cyfs-group/src/statepath/dec_statepath.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group/src/statepath/statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs similarity index 100% rename from src/component/cyfs-group/src/statepath/statepath.rs rename to src/component/cyfs-group/src/statepath/group_statepath.rs diff --git a/src/component/cyfs-group/src/statepath/mod.rs b/src/component/cyfs-group/src/statepath/mod.rs index 20219f092..8c56d3d82 100644 --- a/src/component/cyfs-group/src/statepath/mod.rs +++ b/src/component/cyfs-group/src/statepath/mod.rs @@ -1,3 +1,5 @@ -mod statepath; +mod dec_statepath; +mod group_statepath; -pub use statepath::*; +pub(crate) use dec_statepath::*; +pub(crate) use group_statepath::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group/src/storage/storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs similarity index 96% rename from src/component/cyfs-group/src/storage/storage.rs rename to src/component/cyfs-group/src/storage/group_storage.rs index daab2fc2c..4a88dc933 100644 --- a/src/component/cyfs-group/src/storage/storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,7 +15,7 @@ pub enum BlockLinkState { InvalidBranch, } -pub struct Storage { +pub struct GroupStorage { group: Group, group_id: ObjectId, dec_id: ObjectId, @@ -31,8 +31,12 @@ pub struct Storage { pre_commits: HashMap, } -impl Storage { - pub async fn load(group_id: &ObjectId, dec_id: &ObjectId, rpath: &str) -> BuckyResult { +impl GroupStorage { + pub async fn load( + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group unimplemented!() @@ -42,7 +46,7 @@ impl Storage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - ) -> BuckyResult { + ) -> BuckyResult { unimplemented!() } diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index 21ee2dffa..44de74436 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,3 +1,5 @@ -mod storage; +mod dec_storage; +mod group_storage; -pub use storage::*; +pub use dec_storage::*; +pub use group_storage::*; From d2b7a6207d988900a545f162f58f9e347c9d2f8c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 13 Jan 2023 20:53:44 +0800 Subject: [PATCH 030/553] sync state from group to dec, part1 --- .../src/consensus/hotstuff/hotstuff.rs | 21 +- .../src/dec_state/dec_state_requestor.rs | 1 + .../src/dec_state/dec_state_synchronizer.rs | 285 +++++++++++++++++- .../cyfs-group/src/dec_state/state_pusher.rs | 55 ++-- src/component/cyfs-group/src/helper/mod.rs | 2 + src/component/cyfs-group/src/helper/verify.rs | 35 +++ .../cyfs-group/src/objects/protocol.rs | 9 +- .../cyfs-group/src/storage/dec_storage.rs | 47 +++ 8 files changed, 413 insertions(+), 42 deletions(-) create mode 100644 src/component/cyfs-group/src/helper/verify.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 5336485e6..9378549e3 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -412,13 +412,9 @@ impl Hotstuff { PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, proposals).await } - async fn notify_proposal_result( - &self, - proposal: &GroupProposal, - result: BuckyResult>, - ) { + async fn notify_proposal_err(&self, proposal: &GroupProposal, err: BuckyError) { self.state_pusher - .notify_proposal_result(proposal.clone(), result) + .notify_proposal_err(proposal.clone(), err) .await; } @@ -727,28 +723,25 @@ impl Hotstuff { for proposal in time_adjust_proposals { // timestamp is error - self.notify_proposal_result( + self.notify_proposal_err( &proposal, - Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )), + BuckyError::new(BuckyErrorCode::ErrorTimestamp, "error timestamp"), ) .await; } for proposal in timeout_proposals { // has timeout - self.notify_proposal_result( + self.notify_proposal_err( &proposal, - Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + BuckyError::new(BuckyErrorCode::Timeout, "timeout"), ) .await; } for (proposal, err) in failed_proposals { // failed - self.notify_proposal_result(&proposal, Err(err)).await; + self.notify_proposal_err(&proposal, err).await; } PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, remove_proposals).await; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e69de29bb..e31c48bd5 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -0,0 +1 @@ +pub struct DecStateRequestor {} diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 6c37144ec..0182585a0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -1,3 +1,286 @@ // the manager of the DEC's state that synchronized from the group's rpath -pub struct DecStateSynchronizer {} +use std::collections::HashSet; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; +use futures::FutureExt; + +use crate::{ + helper::{verify_block, Timer}, + network::NonDriver, + storage::{DecStorage, DecStorageCache}, + CHANNEL_CAPACITY, SYNCHRONIZER_TIMEOUT, +}; + +enum DecStateSynchronizerMessage { + ProposalResult( + ObjectId, + BuckyResult<( + Option, + GroupConsensusBlock, + GroupConsensusBlock, + )>, + ), + StateChange(GroupConsensusBlock, GroupConsensusBlock), +} + +pub struct DecStateSynchronizer { + local_id: ObjectId, + tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, +} + +impl DecStateSynchronizer { + pub fn new( + local_id: ObjectId, + network_sender: crate::network::Sender, + rpath: GroupRPath, + non_driver: crate::network::NonDriver, + store: DecStorage, + ) -> Self { + let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); + + let mut runner = DecStateSynchronizerRunner::new(local_id, rx, store); + + async_std::task::spawn(async move { runner.run().await }); + + Self { + local_id, + tx_dec_state_sync_message: tx, + } + } + + pub async fn on_proposal_complete( + &self, + proposal_id: ObjectId, + result: BuckyResult<( + Option, + GroupConsensusBlock, + GroupConsensusBlock, + )>, + remote: ObjectId, + ) { + } + + pub async fn on_state_change( + &self, + header_block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + remote: ObjectId, + ) { + } +} + +struct DecStateSynchronizerCache { + state_cache: DecStorageCache, + group_chunk_id: ObjectId, + group: Group, +} + +struct UpdateNotifyInfo { + header_block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + remotes: HashSet, + group_chunk_id: ObjectId, + group: Group, +} + +struct DecStateSynchronizerRunner { + local_id: ObjectId, + rpath: GroupRPath, + rx_dec_state_sync_message: + async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, + timer: Timer, + store: DecStorage, + state_cache: Option, + update_notifies: Option, + + non_driver: NonDriver, +} + +impl DecStateSynchronizerRunner { + fn new( + local_id: ObjectId, + rpath: GroupRPath, + rx_dec_state_sync_message: async_std::channel::Receiver<( + DecStateSynchronizerMessage, + ObjectId, + )>, + store: DecStorage, + non_driver: NonDriver, + ) -> Self { + Self { + local_id, + rpath, + rx_dec_state_sync_message, + timer: Timer::new(SYNCHRONIZER_TIMEOUT), + store, + state_cache: None, + update_notifies: None, + non_driver, + } + } + + async fn handle_proposal_complete( + &mut self, + proposal_id: ObjectId, + result: BuckyResult<( + Option, + GroupConsensusBlock, + GroupConsensusBlock, + )>, + remote: ObjectId, + ) { + let exe_result = match result { + Ok((result, header_block, qc_block)) => { + if header_block + .proposals() + .iter() + .find(|p| p.proposal == proposal_id) + .is_none() + { + return; + } + if !header_block.check() { + return; + } + + if self + .push_update_notify(header_block, qc_block, remote) + .await + .is_err() + { + return; + } + + if self.sync_state().await.is_err() { + return; + } + Ok(result) + } + Err(e) => Err(e), + }; + + // TODO: notify the app + } + + async fn handle_state_change( + &mut self, + header_block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + remote: ObjectId, + ) { + self.push_update_notify(header_block, qc_block, remote) + .await; + } + + async fn sync_state(&mut self) -> BuckyResult<()> { + unimplemented!() + } + + async fn check_cache(&mut self) -> &Option { + if self.state_cache.is_none() { + let state_cache = self.store.cur_state().await; + if let Some(state_cache) = state_cache { + let group_chunk_id = state_cache.header_block.group_chunk_id().clone(); + let group = self + .non_driver + .get_group(self.rpath.group_id(), Some(&group_chunk_id)) + .await; + if let Ok(group) = group { + self.state_cache = Some(DecStateSynchronizerCache { + state_cache, + group_chunk_id, + group, + }); + } + } + } + + &self.state_cache + } + + async fn push_update_notify( + &mut self, + header_block: GroupConsensusBlock, + qc_block: GroupConsensusBlock, + remote: ObjectId, + ) -> BuckyResult<()> { + if qc_block.qc().is_none() { + log::warn!( + "the qc is none for qc-block({})", + qc_block.named_object().desc().object_id() + ); + return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); + } + + if let Some(notify) = self.update_notifies.as_mut() { + match notify.header_block.height().cmp(&header_block.height()) { + std::cmp::Ordering::Less => {} + std::cmp::Ordering::Equal => { + notify.remotes.insert(remote); + return Ok(()); + } + std::cmp::Ordering::Greater => return Ok(()), + } + } + + let group = match self.update_notifies.as_ref() { + Some(n) => Some((n.group_chunk_id, n.group.clone())), + None => self + .check_cache() + .await + .as_ref() + .map(|c| (c.group_chunk_id, c.group.clone())), + } + .map_or(None, |(chunk_id, group)| { + if &chunk_id == header_block.group_chunk_id() { + Some((chunk_id, group)) + } else { + None + } + }); + + // group changed + let group = match group { + Some(group) => group, + None => { + let group = self + .non_driver + .get_group(self.rpath.group_id(), Some(header_block.group_chunk_id())) + .await?; + (header_block.group_chunk_id().clone(), group) + } + }; + + if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + self.update_notifies = Some(UpdateNotifyInfo { + header_block: header_block, + qc_block: qc_block, + remotes: HashSet::from([remote]), + group_chunk_id: group.0, + group: group.1, + }); + }; + + Ok(()) + } + + async fn run(&mut self) { + loop { + futures::select! { + message = self.rx_dec_state_sync_message.recv().fuse() => match message { + Ok((DecStateSynchronizerMessage::ProposalResult(proposal, result), remote)) => self.handle_proposal_complete(proposal, result, remote).await, + Ok((DecStateSynchronizerMessage::StateChange(block, qc_block), remote)) => self.handle_state_change(block, qc_block, remote).await, + Err(e) => { + log::warn!("[dec-state-sync] rx closed.") + }, + }, + () = self.timer.wait_next().fuse() => {self.sync_state().await;}, + }; + } + } +} diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 222856a01..6e78cb8ed 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -3,7 +3,8 @@ use std::collections::HashSet; use cyfs_base::{ - BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawDecode, + BuckyError, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; use cyfs_lib::NONObjectInfo; @@ -14,7 +15,7 @@ use crate::{ }; enum StatePushMessage { - ProposalResult(GroupProposal, BuckyResult>), + ProposalResult(GroupProposal, BuckyError), BlockCommit(GroupConsensusBlock, GroupConsensusBlock), LastStateRequest(ObjectId), } @@ -43,13 +44,9 @@ impl StatePusher { } } - pub async fn notify_proposal_result( - &self, - proposal: GroupProposal, - result: BuckyResult>, - ) { + pub async fn notify_proposal_err(&self, proposal: GroupProposal, err: BuckyError) { self.tx_notifier - .send(StatePushMessage::ProposalResult(proposal, result)) + .send(StatePushMessage::ProposalResult(proposal, err)) .await; } @@ -60,6 +57,7 @@ impl StatePusher { ) { let block_id = block.named_object().desc().object_id(); if qc_block.height() != block.height() + 1 + || qc_block.qc().as_ref().expect("qc should not empty").round != block.round() || qc_block.round() <= block.round() || qc_block.prev_block_id().unwrap() != &block_id { @@ -80,7 +78,7 @@ impl StatePusher { .await; } - pub async fn last_state_request(&self, remote: ObjectId) { + pub async fn request_last_state(&self, remote: ObjectId) { self.tx_notifier .send(StatePushMessage::LastStateRequest(remote)) .await; @@ -104,7 +102,7 @@ struct StateChanggeRunner { rx_notifier: async_std::channel::Receiver, timer: Timer, - last_state_request_remotes: HashSet, + request_last_state_remotes: HashSet, notify_progress: Option, } @@ -124,14 +122,11 @@ impl StateChanggeRunner { timer: Timer::new(SYNCHRONIZER_TIMEOUT), notify_progress: None, local_id, - last_state_request_remotes: HashSet::new(), + request_last_state_remotes: HashSet::new(), } } - pub async fn notify_proposal_result( - &self, - proposal: GroupProposal, - result: BuckyResult>, - ) { + + pub async fn notify_proposal_err(&self, proposal: GroupProposal, err: BuckyError) { // notify to the proposer let proposal_id = proposal.desc().object_id(); match proposal.desc().owner() { @@ -142,7 +137,7 @@ impl StateChanggeRunner { network_sender .post_message( - HotstuffMessage::ProposalResult(proposal_id, result), + HotstuffMessage::ProposalResult(proposal_id, Err(err)), rpath.clone(), &proposer, ) @@ -152,7 +147,11 @@ impl StateChanggeRunner { } } - pub async fn notify_proposal_result_for_block(&self, block: GroupConsensusBlock) { + pub async fn notify_proposal_result_for_block( + &self, + block: &GroupConsensusBlock, + qc_block: &GroupConsensusBlock, + ) { let network_sender = self.network_sender.clone(); let rpath = self.rpath.clone(); let non_driver = self.non_driver.clone(); @@ -189,7 +188,10 @@ impl StateChanggeRunner { network_sender .post_message( - HotstuffMessage::ProposalResult(exe_info.proposal, Ok(receipt)), + HotstuffMessage::ProposalResult( + exe_info.proposal, + Ok((receipt, block.clone(), qc_block.clone())), + ), rpath.clone(), &proposer, ) @@ -264,8 +266,8 @@ impl StateChanggeRunner { } } - fn last_state_request(&mut self, remote: ObjectId) { - self.last_state_request_remotes.insert(remote); + fn request_last_state(&mut self, remote: ObjectId) { + self.request_last_state_remotes.insert(remote); } async fn try_notify_block_commit(&mut self) { @@ -279,7 +281,7 @@ impl StateChanggeRunner { progress.cur_block_notify_times += notify_count; let mut notify_targets = HashSet::new(); - std::mem::swap(&mut self.last_state_request_remotes, &mut notify_targets); + std::mem::swap(&mut self.request_last_state_remotes, &mut notify_targets); let start_pos = progress.cur_block_notify_times % progress.members.len(); let notify_targets_1 = &progress.members.as_slice() @@ -316,14 +318,15 @@ impl StateChanggeRunner { loop { futures::select! { message = self.rx_notifier.recv().fuse() => match message { - Ok(StatePushMessage::ProposalResult(proposal, result)) => self.notify_proposal_result(proposal, result).await, + Ok(StatePushMessage::ProposalResult(proposal, err)) => self.notify_proposal_err(proposal, err).await, Ok(StatePushMessage::BlockCommit(block, qc_block)) => { - self.notify_proposal_result_for_block(block.clone()).await; + self.notify_proposal_result_for_block(&block, &qc_block).await; self.update_commit_block(block, qc_block).await; }, Ok(StatePushMessage::LastStateRequest(remote)) => { - self.last_state_request(remote); - }, Err(e) => { + self.request_last_state(remote); + }, + Err(e) => { log::warn!("[change-notifier] rx_notifier closed.") }, }, diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index 4d3f1b1c6..ce36043a3 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,3 +1,5 @@ mod timer; +mod verify; pub use timer::*; +pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs new file mode 100644 index 000000000..31c6fa756 --- /dev/null +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -0,0 +1,35 @@ +use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, +}; + +pub async fn verify_block( + block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, + group: &Group, +) -> BuckyResult { + let block_id = block.named_object().desc().object_id(); + if qc.round != block.round() || qc.block_id != block_id { + log::error!( + "the qc-block({}) should be next block({})", + qc.round, + block_id + ); + return Ok(false); + } + + if !block.check() { + return Ok(false); + } + + unimplemented!() +} + +pub async fn verify_rpath_value( + value: &GroupRPathStatus, + block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, + group: &Group, +) -> BuckyResult { + unimplemented!() +} diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 8f21c38ec..56facdb4b 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -94,7 +94,14 @@ pub(crate) enum HotstuffMessage { LastStateRequest, StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) - ProposalResult(ObjectId, BuckyResult>), // (proposal-id, ExecuteResult) + ProposalResult( + ObjectId, + BuckyResult<( + Option, + GroupConsensusBlock, + GroupConsensusBlock, + )>, + ), // (proposal-id, (ExecuteResult, block, qc-block)) QueryState(String), VerifiableState(GroupRPathStatus), } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index e69de29bb..92ac688af 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -0,0 +1,47 @@ +use std::sync::Arc; + +use async_std::sync::RwLock; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; + +#[derive(Clone)] +pub struct DecStorageCache { + pub state: ObjectId, + pub header_block: GroupConsensusBlock, + pub qc_block: GroupConsensusBlock, +} + +// TODO: storage + +#[derive(Clone)] +pub struct DecStorage { + cache: Arc>>, +} + +impl DecStorage { + pub async fn load() -> BuckyResult { + let obj = Self { + cache: Arc::new(RwLock::new(None)), + }; + + Ok(obj) + } + + pub async fn cur_state(&self) -> Option { + let cur = self.cache.read().await; + (*cur).clone() + } + + pub async fn sync( + &self, + header_block: &GroupConsensusBlock, + qc_block: &GroupConsensusBlock, + remote: ObjectId, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn get_by_path(&self, path: String) -> BuckyResult { + unimplemented!() + } +} From 2e1db2999f46a58942dbf43d22dd7b7462730c2a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 14 Jan 2023 11:44:49 +0800 Subject: [PATCH 031/553] notify immediately --- .../cyfs-group/src/dec_state/state_pusher.rs | 77 ++++++++++++------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 6e78cb8ed..a67ea359f 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -3,21 +3,19 @@ use std::collections::HashSet; use cyfs_base::{ - BuckyError, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawDecode, + BuckyError, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::Timer, HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_CYCLE, SYNCHRONIZER_TIMEOUT, -}; +use crate::{helper::Timer, HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), BlockCommit(GroupConsensusBlock, GroupConsensusBlock), LastStateRequest(ObjectId), + DelayBroadcast, } pub struct StatePusher { @@ -34,7 +32,8 @@ impl StatePusher { ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); - let mut runner = StateChanggeRunner::new(local_id, network_sender, rpath, non_driver, rx); + let mut runner = + StateChanggeRunner::new(local_id, network_sender, rpath, non_driver, tx.clone(), rx); async_std::task::spawn(async move { runner.run().await }); @@ -99,9 +98,10 @@ struct StateChanggeRunner { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NonDriver, + tx_notifier: async_std::channel::Sender, rx_notifier: async_std::channel::Receiver, - timer: Timer, - + delay_notify_times: usize, + // timer: Timer, request_last_state_remotes: HashSet, notify_progress: Option, } @@ -112,14 +112,17 @@ impl StateChanggeRunner { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NonDriver, + tx_notifier: async_std::channel::Sender, rx_notifier: async_std::channel::Receiver, ) -> Self { Self { network_sender, rpath, non_driver, + tx_notifier, rx_notifier, - timer: Timer::new(SYNCHRONIZER_TIMEOUT), + delay_notify_times: 0, + // timer: Timer::new(SYNCHRONIZER_TIMEOUT), notify_progress: None, local_id, request_last_state_remotes: HashSet::new(), @@ -264,26 +267,31 @@ impl StateChanggeRunner { }); } } + + self.delay_notify(true).await; } - fn request_last_state(&mut self, remote: ObjectId) { - self.request_last_state_remotes.insert(remote); + async fn request_last_state(&mut self, remote: ObjectId) { + if self.request_last_state_remotes.insert(remote) { + self.delay_notify(true).await; + } } async fn try_notify_block_commit(&mut self) { - match self.notify_progress.as_mut() { - Some(progress) if progress.cur_block_notify_times < progress.members.len() => { - let notify_count = (progress.members.len() * SYNCHRONIZER_TIMEOUT as usize - / STATE_NOTIFY_CYCLE as usize) - .max(1) + self.delay_notify_times -= 1; + + if let Some(progress) = self.notify_progress.as_mut() { + let mut notify_targets = HashSet::new(); + std::mem::swap(&mut self.request_last_state_remotes, &mut notify_targets); + + if progress.cur_block_notify_times < progress.members.len() { + let notify_count = STATE_NOTIFY_COUNT_PER_ROUND .min(progress.members.len() - progress.cur_block_notify_times); progress.cur_block_notify_times += notify_count; - let mut notify_targets = HashSet::new(); - std::mem::swap(&mut self.request_last_state_remotes, &mut notify_targets); - - let start_pos = progress.cur_block_notify_times % progress.members.len(); + let start_pos = (progress.total_notify_times + progress.cur_block_notify_times) + % progress.members.len(); let notify_targets_1 = &progress.members.as_slice() [start_pos..progress.members.len().min(start_pos + notify_count)]; @@ -299,18 +307,32 @@ impl StateChanggeRunner { notify_targets.insert(remote.clone()); }); } + } - let msg = HotstuffMessage::StateChangeNotify( - progress.header_block.clone(), - progress.qc_block.clone(), - ); + let msg = HotstuffMessage::StateChangeNotify( + progress.header_block.clone(), + progress.qc_block.clone(), + ); + if notify_targets.len() > 0 { let notify_targets: Vec = notify_targets.into_iter().collect(); self.network_sender .broadcast(msg.clone(), self.rpath.clone(), notify_targets.as_slice()) .await; } - _ => return, + + if progress.cur_block_notify_times < progress.members.len() { + self.delay_notify(false).await; + } + } + } + + async fn delay_notify(&mut self, is_force: bool) { + if is_force || self.delay_notify_times == 0 { + self.tx_notifier + .send(StatePushMessage::DelayBroadcast) + .await; + self.delay_notify_times += 1; } } @@ -326,11 +348,14 @@ impl StateChanggeRunner { Ok(StatePushMessage::LastStateRequest(remote)) => { self.request_last_state(remote); }, + Ok(StatePushMessage::DelayBroadcast) => { + self.try_notify_block_commit(); + }, Err(e) => { log::warn!("[change-notifier] rx_notifier closed.") }, }, - () = self.timer.wait_next().fuse() => self.try_notify_block_commit().await, + // () = self.timer.wait_next().fuse() => self.try_notify_block_commit().await, }; } } From 5c06b67beaf3fc966bdc6c7776e2b358d4dc7d51 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 14 Jan 2023 16:20:08 +0800 Subject: [PATCH 032/553] sync state from group to dec, part2 --- src/component/cyfs-group/src/constant.rs | 2 +- .../cyfs-group/src/dec/rpath_client.rs | 19 ++- .../cyfs-group/src/dec_state/call_reply.rs | 101 ++++++++++++ .../src/dec_state/dec_state_synchronizer.rs | 151 +++++++++++++++--- src/component/cyfs-group/src/dec_state/mod.rs | 2 + .../cyfs-group/src/network/listener.rs | 30 +--- 6 files changed, 250 insertions(+), 55 deletions(-) create mode 100644 src/component/cyfs-group/src/dec_state/call_reply.rs diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index b2acf3b33..0ecaa7802 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,4 +17,4 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); -pub const STATE_NOTIFY_CYCLE: u64 = 8000; +pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 54cb8793d..dd70267dd 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -8,7 +8,9 @@ use cyfs_core::{ use cyfs_lib::NONObjectInfo; use rand::Rng; -use crate::{HotstuffMessage, CLIENT_POLL_TIMEOUT}; +use crate::{ + dec_state::DecStateSynchronizer, storage::DecStorage, HotstuffMessage, CLIENT_POLL_TIMEOUT, +}; pub struct RPathClient { rpath: GroupRPath, @@ -16,6 +18,7 @@ pub struct RPathClient { non_driver: crate::network::NonDriver, network_sender: crate::network::Sender, network_listener: crate::network::Listener, + state_sync: DecStateSynchronizer, } impl RPathClient { @@ -25,13 +28,22 @@ impl RPathClient { non_driver: crate::network::NonDriver, network_sender: crate::network::Sender, network_listener: crate::network::Listener, + dec_store: DecStorage, ) -> Self { + let state_sync = DecStateSynchronizer::new( + local_id, + rpath.clone(), + non_driver.clone(), + dec_store.clone(), + ); + Self { rpath, non_driver, network_sender, network_listener, local_id, + state_sync, } } @@ -54,10 +66,7 @@ impl RPathClient { let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); - let waiter = self - .network_listener - .wait_proposal_result(proposal_id) - .await?; + let waiter = self.state_sync.wait_proposal_result(proposal_id).await; let mut waiter_future = Some(waiter.wait()); let mut post_result = None; diff --git a/src/component/cyfs-group/src/dec_state/call_reply.rs b/src/component/cyfs-group/src/dec_state/call_reply.rs new file mode 100644 index 000000000..d73b5196e --- /dev/null +++ b/src/component/cyfs-group/src/dec_state/call_reply.rs @@ -0,0 +1,101 @@ +use std::{collections::HashMap, sync::Arc}; + +use async_std::sync::{Mutex, RwLock}; + +use crate::CHANNEL_CAPACITY; + +type CallSeq = u64; + +pub struct CallReplyWaiter { + rx: async_std::channel::Receiver, + seq: CallSeq, + container: Arc>>>, +} + +impl CallReplyWaiter { + pub fn wait(&self) -> async_std::channel::Recv<'_, T> { + self.rx.recv() + } +} + +impl Drop for CallReplyWaiter { + fn drop(&mut self) { + let container = self.container.clone(); + async_std::task::block_on(async move { + let mut container = container.lock().await; + container.remove(&self.seq); + }); + } +} + +struct CallReplyNotifierRaw { + next_seq: CallSeq, + senders: Arc>>>, + call_keys: HashMap>, +} + +#[derive(Clone)] +pub struct CallReplyNotifier( + Arc>>, +); + +impl CallReplyNotifier { + pub fn new() -> Self { + Self(Arc::new(RwLock::new(CallReplyNotifierRaw { + next_seq: 1, + senders: Arc::new(Mutex::new(HashMap::new())), + call_keys: HashMap::new(), + }))) + } + + pub async fn prepare(&self, k: K) -> CallReplyWaiter { + let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); + let mut mgr = self.0.write().await; + let seq = mgr.next_seq; + mgr.next_seq += 1; + mgr.senders.lock().await.insert(seq, tx); + mgr.call_keys.entry(k).or_insert_with(Vec::new).push(seq); + + CallReplyWaiter { + rx, + seq, + container: mgr.senders.clone(), + } + } + + pub async fn reply(&self, key: &K, value: T) { + let (abort_calls, senders) = { + let mgr = self.0.read().await; + let senders = mgr.senders.lock().await; + match mgr.call_keys.get(key) { + Some(call_seqs) => { + let mut valid_senders = vec![]; + let mut abort_calls = vec![]; + for call_seq in call_seqs { + match senders.get(call_seq) { + Some(sender) => valid_senders.push(sender.clone()), + None => abort_calls.push(*call_seq), + } + } + + (abort_calls, valid_senders) + } + None => return, + } + }; + + if abort_calls.len() > 0 { + let mut mgr = self.0.write().await; + if let Some(call_seqs) = mgr.call_keys.get_mut(key) { + call_seqs.retain(|seq| !abort_calls.contains(seq)); + if call_seqs.len() == 0 { + mgr.call_keys.remove(key); + } + } + } + + for sender in senders { + sender.send(value.clone()).await; + } + } +} diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 0182585a0..fac9281df 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -1,6 +1,9 @@ // the manager of the DEC's state that synchronized from the group's rpath -use std::collections::HashSet; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, @@ -16,6 +19,8 @@ use crate::{ CHANNEL_CAPACITY, SYNCHRONIZER_TIMEOUT, }; +use super::{CallReplyNotifier, CallReplyWaiter}; + enum DecStateSynchronizerMessage { ProposalResult( ObjectId, @@ -26,31 +31,52 @@ enum DecStateSynchronizerMessage { )>, ), StateChange(GroupConsensusBlock, GroupConsensusBlock), + DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } -pub struct DecStateSynchronizer { +struct DecStateSynchronizerRaw { local_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, + proposal_result_notifier: CallReplyNotifier>>, } +#[derive(Clone)] +pub struct DecStateSynchronizer(Arc); + impl DecStateSynchronizer { pub fn new( local_id: ObjectId, - network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NonDriver, store: DecStorage, ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); + let notifier = CallReplyNotifier::new(); - let mut runner = DecStateSynchronizerRunner::new(local_id, rx, store); + let mut runner = DecStateSynchronizerRunner::new( + local_id, + rpath, + tx.clone(), + rx, + store, + non_driver, + notifier.clone(), + ); async_std::task::spawn(async move { runner.run().await }); - Self { + Self(Arc::new(DecStateSynchronizerRaw { local_id, tx_dec_state_sync_message: tx, - } + proposal_result_notifier: notifier, + })) + } + + pub async fn wait_proposal_result( + &self, + proposal_id: ObjectId, + ) -> CallReplyWaiter>> { + self.0.proposal_result_notifier.prepare(proposal_id).await } pub async fn on_proposal_complete( @@ -63,6 +89,13 @@ impl DecStateSynchronizer { )>, remote: ObjectId, ) { + self.0 + .tx_dec_state_sync_message + .send(( + DecStateSynchronizerMessage::ProposalResult(proposal_id, result), + remote, + )) + .await; } pub async fn on_state_change( @@ -71,6 +104,13 @@ impl DecStateSynchronizer { qc_block: GroupConsensusBlock, remote: ObjectId, ) { + self.0 + .tx_dec_state_sync_message + .send(( + DecStateSynchronizerMessage::StateChange(header_block, qc_block), + remote, + )) + .await; } } @@ -91,36 +131,45 @@ struct UpdateNotifyInfo { struct DecStateSynchronizerRunner { local_id: ObjectId, rpath: GroupRPath, + tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, - timer: Timer, + // timer: Timer, store: DecStorage, state_cache: Option, update_notifies: Option, non_driver: NonDriver, + proposal_result_notifier: CallReplyNotifier>>, } impl DecStateSynchronizerRunner { fn new( local_id: ObjectId, rpath: GroupRPath, + tx_dec_state_sync_message: async_std::channel::Sender<( + DecStateSynchronizerMessage, + ObjectId, + )>, rx_dec_state_sync_message: async_std::channel::Receiver<( DecStateSynchronizerMessage, ObjectId, )>, store: DecStorage, non_driver: NonDriver, + proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { local_id, rpath, + tx_dec_state_sync_message, rx_dec_state_sync_message, - timer: Timer::new(SYNCHRONIZER_TIMEOUT), + // timer: Timer::new(SYNCHRONIZER_TIMEOUT), store, state_cache: None, update_notifies: None, non_driver, + proposal_result_notifier, } } @@ -134,7 +183,7 @@ impl DecStateSynchronizerRunner { )>, remote: ObjectId, ) { - let exe_result = match result { + match result { Ok((result, header_block, qc_block)) => { if header_block .proposals() @@ -156,15 +205,20 @@ impl DecStateSynchronizerRunner { return; } - if self.sync_state().await.is_err() { - return; - } - Ok(result) + self.tx_dec_state_sync_message + .send(( + DecStateSynchronizerMessage::DelaySync(Some((proposal_id, result))), + remote, + )) + .await; + } + Err(e) => { + // notify the app + self.proposal_result_notifier + .reply(&proposal_id, Err(e)) + .await; } - Err(e) => Err(e), }; - - // TODO: notify the app } async fn handle_state_change( @@ -173,12 +227,66 @@ impl DecStateSynchronizerRunner { qc_block: GroupConsensusBlock, remote: ObjectId, ) { - self.push_update_notify(header_block, qc_block, remote) - .await; + if self + .push_update_notify(header_block, qc_block, remote) + .await + .is_ok() + { + self.tx_dec_state_sync_message + .send((DecStateSynchronizerMessage::DelaySync(None), remote)) + .await; + } } - async fn sync_state(&mut self) -> BuckyResult<()> { - unimplemented!() + async fn sync_state( + &mut self, + proposal_result: Option<(ObjectId, Option)>, + remote: ObjectId, + ) { + let result = match self.update_notifies.as_ref() { + Some(notify_info) => { + let mut err = None; + for remote in notify_info.remotes.iter() { + match self + .store + .sync( + ¬ify_info.header_block, + ¬ify_info.qc_block, + remote.clone(), + ) + .await + { + Ok(_) => { + err = None; + self.state_cache = Some(DecStateSynchronizerCache { + state_cache: DecStorageCache { + state: notify_info.header_block.result_state_id().clone(), + header_block: notify_info.header_block.clone(), + qc_block: notify_info.qc_block.clone(), + }, + group_chunk_id: notify_info.group_chunk_id, + group: notify_info.group.clone(), + }); + self.update_notifies = None; + break; + } + Err(e) => { + err = err.or(Some(e)); + } + } + } + err.map_or(Ok(()), |e| Err(e)) + } + None => Ok(()), + }; + + if let Some((proposal_id, proposal_result)) = proposal_result { + let proposal_result = result.map(|_| proposal_result); + // notify app dec + self.proposal_result_notifier + .reply(&proposal_id, proposal_result) + .await; + } } async fn check_cache(&mut self) -> &Option { @@ -275,11 +383,12 @@ impl DecStateSynchronizerRunner { message = self.rx_dec_state_sync_message.recv().fuse() => match message { Ok((DecStateSynchronizerMessage::ProposalResult(proposal, result), remote)) => self.handle_proposal_complete(proposal, result, remote).await, Ok((DecStateSynchronizerMessage::StateChange(block, qc_block), remote)) => self.handle_state_change(block, qc_block, remote).await, + Ok((DecStateSynchronizerMessage::DelaySync(proposal_result), remote)) => self.sync_state(proposal_result, remote).await, Err(e) => { log::warn!("[dec-state-sync] rx closed.") }, }, - () = self.timer.wait_next().fuse() => {self.sync_state().await;}, + // () = self.timer.wait_next().fuse() => {self.sync_state().await;}, }; } } diff --git a/src/component/cyfs-group/src/dec_state/mod.rs b/src/component/cyfs-group/src/dec_state/mod.rs index 4e009798e..18162d16a 100644 --- a/src/component/cyfs-group/src/dec_state/mod.rs +++ b/src/component/cyfs-group/src/dec_state/mod.rs @@ -1,7 +1,9 @@ +mod call_reply; mod dec_state_requestor; mod dec_state_synchronizer; mod state_pusher; +pub(crate) use call_reply::*; pub(crate) use dec_state_requestor::*; pub(crate) use dec_state_synchronizer::*; pub(crate) use state_pusher::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 851c3c7c3..3b2745e36 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,24 +3,7 @@ use cyfs_bdt::Stack; use cyfs_core::GroupRPath; use cyfs_lib::NONObjectInfo; -use crate::CHANNEL_CAPACITY; - -pub struct ReplyWaiter { - rx: async_std::channel::Receiver, - seq: u64, -} - -impl ReplyWaiter { - pub fn wait(&self) -> async_std::channel::Recv<'_, T> { - self.rx.recv() - } -} - -impl Drop for ReplyWaiter { - fn drop(&mut self) { - todo!("distach the tx") - } -} +use crate::{dec_state::CallReplyWaiter, CHANNEL_CAPACITY}; pub struct Listener { wait_seq: u64, @@ -31,20 +14,11 @@ impl Listener { pub fn listen(&self) {} - pub async fn wait_proposal_result( - &self, - proposal_id: ObjectId, - ) -> BuckyResult>>> { - let (tx_proposal_result, rx_proposal_result) = - async_std::channel::bounded::>>(CHANNEL_CAPACITY); - unimplemented!() - } - pub async fn wait_query_state( &self, sub_path: String, rpath: GroupRPath, - ) -> BuckyResult>> { + ) -> BuckyResult>> { unimplemented!() } } From 125bb4ad2d7abc4f3c6aa75920f988d05bb2814c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 14 Jan 2023 19:03:08 +0800 Subject: [PATCH 033/553] get by path part1 --- .../cyfs-core/src/group/group_rpath_status.rs | 6 +- .../src/consensus/hotstuff/hotstuff.rs | 7 +- .../cyfs-group/src/dec/rpath_client.rs | 33 +-- .../src/dec_state/dec_state_requestor.rs | 208 +++++++++++++++++- .../src/dec_state/dec_state_synchronizer.rs | 15 +- .../cyfs-group/src/dec_state/state_pusher.rs | 12 +- src/component/cyfs-group/src/helper/verify.rs | 1 + .../cyfs-group/src/network/non_driver.rs | 1 + .../cyfs-group/src/objects/protocol.rs | 2 +- .../cyfs-group/src/storage/dec_storage.rs | 2 +- 10 files changed, 260 insertions(+), 27 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs index fafe663ef..c55c41243 100644 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ b/src/component/cyfs-core/src/group/group_rpath_status.rs @@ -7,7 +7,11 @@ use sha2::Digest; // TODO: 后面再封装这个对象 #[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus {} +pub struct GroupRPathStatus { + pub value_object_id: ObjectId, + pub block_id: ObjectId, + pub qc_block_id: ObjectId, +} #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 9378549e3..81847819f 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -920,11 +920,16 @@ impl Hotstuff { Ok((HotstuffMessage::BlockVote(vote), remote)) => self.handle_vote(&vote, None, remote).await, Ok((HotstuffMessage::TimeoutVote(timeout), remote)) => self.handle_timeout(&timeout, remote).await, Ok((HotstuffMessage::Timeout(tc), remote)) => self.handle_tc(&tc, remote).await, + Ok((HotstuffMessage::SyncRequest(min_bound, max_bound), remote)) => self.synchronizer.process_sync_request(min_bound, max_bound, remote, &self.store).await, + Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), + Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), + Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), + Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); Ok(()) }, - Ok((HotstuffMessage::SyncRequest(min_bound, max_bound), remote)) => self.synchronizer.process_sync_request(min_bound, max_bound, remote, &self.store).await }, message = self.rx_message_inner.recv().fuse() => match message { Ok((block, remote)) => { diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index dd70267dd..f13ea938f 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -2,14 +2,14 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, RawConvertTo, }; -use cyfs_core::{ - GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath, GroupRPathStatus, -}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::NONObjectInfo; use rand::Rng; use crate::{ - dec_state::DecStateSynchronizer, storage::DecStorage, HotstuffMessage, CLIENT_POLL_TIMEOUT, + dec_state::{DecStateRequestor, DecStateSynchronizer}, + storage::DecStorage, + HotstuffMessage, CLIENT_POLL_TIMEOUT, }; pub struct RPathClient { @@ -17,8 +17,8 @@ pub struct RPathClient { local_id: ObjectId, non_driver: crate::network::NonDriver, network_sender: crate::network::Sender, - network_listener: crate::network::Listener, state_sync: DecStateSynchronizer, + state_requestor: DecStateRequestor, } impl RPathClient { @@ -27,7 +27,6 @@ impl RPathClient { local_id: ObjectId, non_driver: crate::network::NonDriver, network_sender: crate::network::Sender, - network_listener: crate::network::Listener, dec_store: DecStorage, ) -> Self { let state_sync = DecStateSynchronizer::new( @@ -37,13 +36,21 @@ impl RPathClient { dec_store.clone(), ); + let state_requestor = DecStateRequestor::new( + local_id, + rpath.clone(), + network_sender.clone(), + non_driver.clone(), + dec_store.clone(), + ); + Self { rpath, non_driver, network_sender, - network_listener, local_id, state_sync, + state_requestor, } } @@ -60,7 +67,7 @@ impl RPathClient { // TODO: signature let group = self .non_driver - .get_group(proposal.r_path().group_id(), None) + .get_group(proposal.r_path().group_id(), None, None) .await?; let admins = group.select_members_with_distance(&self.local_id, GroupMemberScope::Admin); let proposal_id = proposal.desc().object_id(); @@ -123,7 +130,7 @@ impl RPathClient { pub async fn refresh_state(&self) -> BuckyResult<()> { let group = self .non_driver - .get_group(&self.rpath.group_id(), None) + .get_group(&self.rpath.group_id(), None, None) .await?; let admins = group.select_members_with_distance(&self.local_id, GroupMemberScope::Admin); @@ -139,16 +146,16 @@ impl RPathClient { pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { let group = self .non_driver - .get_group(self.rpath().group_id(), None) + .get_group(self.rpath().group_id(), None, None) .await?; let members = group.select_members_with_distance(&self.local_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self - .network_listener - .wait_query_state(sub_path.to_string(), self.rpath.clone()) - .await?; + .state_requestor + .wait_query_state(sub_path.to_string()) + .await; let mut waiter_future = Some(waiter.wait()); let mut exe_result = None; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e31c48bd5..13951dddc 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -1 +1,207 @@ -pub struct DecStateRequestor {} +// the manager of the DEC's state that synchronized from the group's rpath + +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use futures::FutureExt; + +use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; + +use super::{CallReplyNotifier, CallReplyWaiter}; + +enum DecStateRequestorMessage { + QueryState(String), // sub-path + VerifiableState(String, BuckyResult), // (sub-path, result) +} + +struct DecStateRequestorRaw { + local_id: ObjectId, + tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, + query_state_notifier: CallReplyNotifier>, +} + +#[derive(Clone)] +pub struct DecStateRequestor(Arc); + +impl DecStateRequestor { + pub fn new( + local_id: ObjectId, + rpath: GroupRPath, + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, + store: DecStorage, + ) -> Self { + let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); + let notifier = CallReplyNotifier::new(); + + let mut runner = DecStateRequestorRunner::new( + local_id, + rpath, + rx, + store, + network_sender, + non_driver, + notifier.clone(), + ); + + async_std::task::spawn(async move { runner.run().await }); + + Self(Arc::new(DecStateRequestorRaw { + local_id, + tx_dec_state_req_message: tx, + query_state_notifier: notifier, + })) + } + + pub async fn wait_query_state( + &self, + sub_path: String, + ) -> CallReplyWaiter> { + self.0.query_state_notifier.prepare(sub_path).await + } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + self.0 + .tx_dec_state_req_message + .send((DecStateRequestorMessage::QueryState(sub_path), remote)) + .await; + } + + pub async fn on_verifiable_state( + &self, + sub_path: String, + result: BuckyResult, + remote: ObjectId, + ) { + self.0 + .tx_dec_state_req_message + .send(( + DecStateRequestorMessage::VerifiableState(sub_path, result), + remote, + )) + .await; + } +} + +struct DecStateRequestorRunner { + local_id: ObjectId, + rpath: GroupRPath, + rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, + // timer: Timer, + store: DecStorage, + + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, + query_state_notifier: CallReplyNotifier>, +} + +impl DecStateRequestorRunner { + fn new( + local_id: ObjectId, + rpath: GroupRPath, + rx_dec_state_req_message: async_std::channel::Receiver<( + DecStateRequestorMessage, + ObjectId, + )>, + store: DecStorage, + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, + query_state_notifier: CallReplyNotifier>, + ) -> Self { + Self { + local_id, + rpath, + rx_dec_state_req_message, + // timer: Timer::new(SYNCHRONIZER_TIMEOUT), + store, + query_state_notifier, + network_sender, + non_driver, + } + } + + async fn handle_query_state(&mut self, sub_path: String, remote: ObjectId) { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + } + + async fn handle_verifiable_state( + &mut self, + sub_path: String, + result: BuckyResult, + remote: ObjectId, + ) { + match result { + Ok(result) => { + let result = self + .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .await + .map(|_| result.value_object_id); + + self.query_state_notifier.reply(&sub_path, result).await + } + Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, + } + } + + async fn verify_verifiable_state( + &self, + sub_path: &str, + result: &GroupRPathStatus, + remote: &ObjectId, + ) -> BuckyResult<()> { + let header_block = self + .non_driver + .get_block(&result.block_id, Some(remote)) + .await?; + let qc_block = self + .non_driver + .get_block(&result.qc_block_id, Some(remote)) + .await?; + + let qc = match qc_block.qc() { + Some(qc) => qc, + None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), + }; + + let group = self + .non_driver + .get_group( + self.rpath.group_id(), + Some(header_block.group_chunk_id()), + Some(&remote), + ) + .await?; + + if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "verify failed", + )) + } else { + Ok(()) + } + } + + async fn run(&mut self) { + loop { + futures::select! { + message = self.rx_dec_state_req_message.recv().fuse() => match message { + Ok((DecStateRequestorMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, + Ok((DecStateRequestorMessage::VerifiableState(sub_path, result), remote)) => self.handle_verifiable_state(sub_path, result, remote).await, + Err(e) => { + log::warn!("[dec-state-sync] rx closed.") + }, + }, + // () = self.timer.wait_next().fuse() => {self.sync_state().await;}, + }; + } + } +} diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index fac9281df..ffbd2838f 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -1,9 +1,6 @@ // the manager of the DEC's state that synchronized from the group's rpath -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; +use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, @@ -16,7 +13,7 @@ use crate::{ helper::{verify_block, Timer}, network::NonDriver, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, SYNCHRONIZER_TIMEOUT, + CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -296,7 +293,7 @@ impl DecStateSynchronizerRunner { let group_chunk_id = state_cache.header_block.group_chunk_id().clone(); let group = self .non_driver - .get_group(self.rpath.group_id(), Some(&group_chunk_id)) + .get_group(self.rpath.group_id(), Some(&group_chunk_id), None) .await; if let Ok(group) = group { self.state_cache = Some(DecStateSynchronizerCache { @@ -358,7 +355,11 @@ impl DecStateSynchronizerRunner { None => { let group = self .non_driver - .get_group(self.rpath.group_id(), Some(header_block.group_chunk_id())) + .get_group( + self.rpath.group_id(), + Some(header_block.group_chunk_id()), + Some(&remote), + ) .await?; (header_block.group_chunk_id().clone(), group) } diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index a67ea359f..66c3167bd 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -216,7 +216,11 @@ impl StateChanggeRunner { if block.group_chunk_id() != progress.header_block.group_chunk_id() { let group = self .non_driver - .get_group(block.r_path().group_id(), Some(block.group_chunk_id())) + .get_group( + block.r_path().group_id(), + Some(block.group_chunk_id()), + None, + ) .await; if group.is_err() { return; @@ -238,7 +242,11 @@ impl StateChanggeRunner { None => { let group = self .non_driver - .get_group(block.r_path().group_id(), Some(block.group_chunk_id())) + .get_group( + block.r_path().group_id(), + Some(block.group_chunk_id()), + None, + ) .await; if group.is_err() { return; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 31c6fa756..268101c56 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -27,6 +27,7 @@ pub async fn verify_block( pub async fn verify_rpath_value( value: &GroupRPathStatus, + sub_path: &str, block: &GroupConsensusBlock, qc: &HotstuffBlockQC, group: &Group, diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 34a928f6e..517985a86 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -48,6 +48,7 @@ impl NonDriver { &self, group_id: &ObjectId, group_chunk_id: Option<&ObjectId>, + from: Option<&ObjectId>, ) -> BuckyResult { unimplemented!() } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 56facdb4b..12dd7615a 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -103,7 +103,7 @@ pub(crate) enum HotstuffMessage { )>, ), // (proposal-id, (ExecuteResult, block, qc-block)) QueryState(String), - VerifiableState(GroupRPathStatus), + VerifiableState(String, BuckyResult), } #[derive(Clone, RawEncode, RawDecode)] diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 92ac688af..dcf3aca8f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -41,7 +41,7 @@ impl DecStorage { unimplemented!() } - pub async fn get_by_path(&self, path: String) -> BuckyResult { + pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } } From 8ab2175b132c13794c3b61c9b73a251d708cae80 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 16 Jan 2023 15:48:57 +0800 Subject: [PATCH 034/553] optimize sturcture --- .../src/consensus/hotstuff/hotstuff.rs | 148 +++++++++++++----- .../proposal/pending_proposal_mgr.rs | 70 ++++++--- .../consensus/synchronizer/synchronizer.rs | 19 ++- .../cyfs-group/src/dec/rpath_client.rs | 1 + .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../cyfs-group/src/network/listener.rs | 8 - 6 files changed, 169 insertions(+), 81 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 81847819f..882d2b64a 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, RsaCPUObjectSigner, + ObjectDesc, ObjectId, RawConvertTo, RawDecode, RsaCPUObjectSigner, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -16,7 +16,7 @@ use futures::FutureExt; use crate::{ consensus::synchronizer::Synchronizer, dec_state::StatePusher, helper::Timer, AsProposal, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, - HotstuffTimeoutVote, PendingProposalMgr, ProposalConsumeMessage, RPathDelegate, VoteMgr, + HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; @@ -26,6 +26,82 @@ use crate::{ */ pub(crate) struct Hotstuff { + tx_message: Sender<(HotstuffMessage, ObjectId)>, +} + +impl Hotstuff { + pub fn new( + local_id: ObjectId, + committee: Committee, + store: GroupStorage, + signer: RsaCPUObjectSigner, + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, + proposal_consumer: PendingProposalConsumer, + delegate: Arc>, + rpath: GroupRPath, + ) -> Self { + let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); + + let tx_message_runner = tx_message.clone(); + async_std::task::spawn(async move { + HotstuffRunner::new( + local_id, + committee, + store, + signer, + network_sender, + non_driver, + tx_message_runner, + rx_message, + proposal_consumer, + delegate, + rpath, + ) + .run() + .await + }); + + Self { tx_message } + } + + pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { + self.tx_message + .send((HotstuffMessage::Block(block), remote)) + .await; + } + + pub async fn on_block_vote(&self, vote: HotstuffBlockQCVote, remote: ObjectId) { + self.tx_message + .send((HotstuffMessage::BlockVote(vote), remote)) + .await; + } + + pub async fn on_timeout_vote(&self, vote: HotstuffTimeoutVote, remote: ObjectId) { + self.tx_message + .send((HotstuffMessage::TimeoutVote(vote), remote)) + .await; + } + + pub async fn on_timeout(&self, tc: HotstuffTimeout, remote: ObjectId) { + self.tx_message + .send((HotstuffMessage::Timeout(tc), remote)) + .await; + } + + pub async fn on_sync_request( + &self, + min_bound: SyncBound, + max_bound: SyncBound, + remote: ObjectId, + ) { + self.tx_message + .send((HotstuffMessage::SyncRequest(min_bound, max_bound), remote)) + .await; + } +} + +struct HotstuffRunner { local_id: ObjectId, committee: Committee, store: GroupStorage, @@ -37,31 +113,31 @@ pub(crate) struct Hotstuff { vote_mgr: VoteMgr, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, + tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, - tx_proposal_consume: Sender, + proposal_consumer: PendingProposalConsumer, delegate: Arc>, synchronizer: Synchronizer, rpath: GroupRPath, - tx_message_inner: Sender<(GroupConsensusBlock, ObjectId)>, - rx_message_inner: Receiver<(GroupConsensusBlock, ObjectId)>, rx_proposal_waiter: Option<(Receiver, u64)>, state_pusher: StatePusher, } -impl Hotstuff { +impl HotstuffRunner { #[allow(clippy::too_many_arguments)] - pub async fn spawn( + pub fn new( local_id: ObjectId, committee: Committee, store: GroupStorage, signer: RsaCPUObjectSigner, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, + tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, - tx_proposal_consume: Sender, + proposal_consumer: PendingProposalConsumer, delegate: Arc>, rpath: GroupRPath, - ) { + ) -> Self { let max_round_block = store.block_with_max_round(); let round = store @@ -69,18 +145,16 @@ impl Hotstuff { .max(max_round_block.as_ref().map_or(1, |block| block.round())); let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); - let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); - let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; - let synchronizer = Synchronizer::spawn( + let synchronizer = Synchronizer::new( network_sender.clone(), rpath.clone(), max_height, round, - tx_message_inner.clone(), + tx_message.clone(), ); let state_pusher = StatePusher::new( @@ -90,7 +164,7 @@ impl Hotstuff { non_driver.clone(), ); - let mut hotstuff = Self { + Self { local_id, committee, store, @@ -100,20 +174,17 @@ impl Hotstuff { timer: Timer::new(init_timer_interval), vote_mgr, network_sender, + tx_message, rx_message, delegate, synchronizer, non_driver, rpath, - tx_proposal_consume, - tx_message_inner, - rx_message_inner, + proposal_consumer, rx_proposal_waiter: None, tc: None, state_pusher, - }; - - async_std::task::spawn(async move { hotstuff.run().await }); + } } async fn handle_block( @@ -409,7 +480,7 @@ impl Hotstuff { .iter() .map(|proposal| proposal.proposal) .collect(); - PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, proposals).await + self.proposal_consumer.remove_proposals(proposals).await } async fn notify_proposal_err(&self, proposal: &GroupProposal, err: BuckyError) { @@ -650,7 +721,7 @@ impl Hotstuff { } async fn generate_proposal(&mut self, tc: Option) -> BuckyResult<()> { - let mut proposals = PendingProposalMgr::query_proposals(&self.tx_proposal_consume).await?; + let mut proposals = self.proposal_consumer.query_proposals().await?; proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let now = SystemTime::now(); @@ -744,7 +815,9 @@ impl Hotstuff { self.notify_proposal_err(&proposal, err).await; } - PendingProposalMgr::remove_proposals(&self.tx_proposal_consume, remove_proposals).await; + self.proposal_consumer + .remove_proposals(remove_proposals) + .await; if self .try_wait_proposals(executed_proposals.as_slice(), &pre_block) @@ -782,8 +855,8 @@ impl Hotstuff { self.local_id, ); - self.tx_message_inner - .send((block.clone(), self.local_id)) + self.tx_message + .send((HotstuffMessage::Block(block.clone()), self.local_id)) .await; self.broadcast(HotstuffMessage::Block(block), &latest_group) @@ -849,7 +922,9 @@ impl Hotstuff { async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { let block = self.non_driver.get_block(block_id, Some(&remote)).await?; - self.tx_message_inner.send((block, remote)).await; + self.tx_message + .send((HotstuffMessage::Block(block), remote)) + .await; Ok(()) } @@ -916,7 +991,13 @@ impl Hotstuff { loop { let result = futures::select! { message = self.rx_message.recv().fuse() => match message { - Ok((HotstuffMessage::Block(block), remote)) => self.handle_block(&block, remote).await, + Ok((HotstuffMessage::Block(block), remote)) => { + if remote == self.local_id { + self.process_block(&block, remote).await + } else { + self.handle_block(&block, remote).await + } + }, Ok((HotstuffMessage::BlockVote(vote), remote)) => self.handle_vote(&vote, None, remote).await, Ok((HotstuffMessage::TimeoutVote(timeout), remote)) => self.handle_timeout(&timeout, remote).await, Ok((HotstuffMessage::Timeout(tc), remote)) => self.handle_tc(&tc, remote).await, @@ -931,19 +1012,6 @@ impl Hotstuff { Ok(()) }, }, - message = self.rx_message_inner.recv().fuse() => match message { - Ok((block, remote)) => { - if remote == self.local_id { - self.process_block(&block, remote).await - } else { - self.handle_block(&block, remote).await - } - } - Err(e) => { - log::warn!("[hotstuff] rx_message_inner closed."); - Ok(()) - } - }, () = self.timer.wait_next().fuse() => self.local_timeout_round().await, wait_round = Self::proposal_waiter(self.rx_proposal_waiter.clone()).fuse() => { if wait_round == self.round { diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs index 83f10275c..c3abf3c81 100644 --- a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -5,7 +5,7 @@ use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::GroupProposal; use futures::FutureExt; -use crate::AsProposal; +use crate::{AsProposal, CHANNEL_CAPACITY}; pub enum ProposalConsumeMessage { Query(Sender>), @@ -17,36 +17,58 @@ pub struct PendingProposalMgr { rx_product: Receiver, rx_consume: Receiver, tx_proposal_waker: Option>, - network_sender: crate::network::Sender, // TODO: 需要设计一个结构便于按时间或数量拆分 buffer: HashMap, } impl PendingProposalMgr { - pub fn spawn( - rx_product: Receiver, - rx_consume: Receiver, - network_sender: crate::network::Sender, - ) { + pub fn new() -> (PendingProposalHandler, PendingProposalConsumer) { + let (tx_product, rx_product) = async_std::channel::bounded(CHANNEL_CAPACITY); + let (tx_consume, rx_consume) = async_std::channel::bounded(CHANNEL_CAPACITY); + async_std::task::spawn(async move { - Self { + PendingProposalMgrRunner { rx_product, rx_consume, buffer: HashMap::new(), - network_sender, tx_proposal_waker: None, } .run() .await }); + + ( + PendingProposalHandler { tx_product }, + PendingProposalConsumer { tx_consume }, + ) } +} - pub async fn query_proposals( - tx_consume: &Sender, - ) -> BuckyResult> { +pub struct PendingProposalHandler { + tx_product: Sender, +} + +impl PendingProposalHandler { + pub async fn on_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + self.tx_product.send(proposal).await.map_err(|e| { + log::error!( + "[pending_proposal_mgr] send message(on_proposal) faield: {}", + e + ); + BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") + }) + } +} + +pub struct PendingProposalConsumer { + tx_consume: Sender, +} + +impl PendingProposalConsumer { + pub async fn query_proposals(&self) -> BuckyResult> { let (sender, receiver) = async_std::channel::bounded(1); - tx_consume + self.tx_consume .send(ProposalConsumeMessage::Query(sender)) .await .map_err(|e| { @@ -60,11 +82,8 @@ impl PendingProposalMgr { }) } - pub async fn remove_proposals( - tx_consume: &Sender, - proposal_ids: Vec, - ) -> BuckyResult<()> { - tx_consume + pub async fn remove_proposals(&self, proposal_ids: Vec) -> BuckyResult<()> { + self.tx_consume .send(ProposalConsumeMessage::Remove(proposal_ids)) .await .map_err(|e| { @@ -72,8 +91,19 @@ impl PendingProposalMgr { BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") }) } +} + +struct PendingProposalMgrRunner { + rx_product: Receiver, + rx_consume: Receiver, + tx_proposal_waker: Option>, + + // TODO: 需要设计一个结构便于按时间或数量拆分 + buffer: HashMap, +} - async fn query_proposals_impl(&mut self) -> Vec { +impl PendingProposalMgrRunner { + async fn handle_query_proposals(&mut self) -> Vec { self.buffer.iter().map(|(_, p)| p.clone()).collect() } @@ -92,7 +122,7 @@ impl PendingProposalMgr { if let Ok(message) = message { match message { ProposalConsumeMessage::Query(sender) => { - let proposals = self.query_proposals_impl().await; + let proposals = self.handle_query_proposals().await; sender.send(proposals).await; }, ProposalConsumeMessage::Remove(proposal_ids) => { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index c9a3f4216..0da84181e 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -21,19 +21,19 @@ enum SynchronizerMessage { PopBlock(u64, u64, ObjectId), // (new-height, new-round, blockid) } -pub struct Synchronizer { +pub(crate) struct Synchronizer { tx_sync_message: Sender, network_sender: crate::network::Sender, rpath: GroupRPath, } impl Synchronizer { - pub fn spawn( + pub fn new( network_sender: crate::network::Sender, rpath: GroupRPath, height: u64, round: u64, - tx_block: Sender<(GroupConsensusBlock, ObjectId)>, + tx_block: Sender<(HotstuffMessage, ObjectId)>, ) -> Self { let (tx_sync_message, rx_sync_message) = async_std::channel::bounded(CHANNEL_CAPACITY); let mut runner = SynchronizerRunner::new( @@ -317,7 +317,7 @@ impl RequestSendInfo { struct SynchronizerRunner { network_sender: crate::network::Sender, rpath: GroupRPath, - tx_block: Sender<(GroupConsensusBlock, ObjectId)>, + tx_block: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver, timer: Timer, height: u64, @@ -331,7 +331,7 @@ impl SynchronizerRunner { fn new( network_sender: crate::network::Sender, rpath: GroupRPath, - tx_block: Sender<(GroupConsensusBlock, ObjectId)>, + tx_block: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver, height: u64, round: u64, @@ -643,11 +643,10 @@ impl SynchronizerRunner { self.sync_requests.splice(0..(remove_request_pos + 1), []); } - futures::future::join_all( - order_blocks - .into_iter() - .map(|(order_block, remote)| self.tx_block.send((order_block, remote))), - ) + futures::future::join_all(order_blocks.into_iter().map(|(order_block, remote)| { + self.tx_block + .send((HotstuffMessage::Block(order_block), remote)) + })) .await; } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index f13ea938f..2c2479893 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -12,6 +12,7 @@ use crate::{ HotstuffMessage, CLIENT_POLL_TIMEOUT, }; +#[derive(Clone)] pub struct RPathClient { rpath: GroupRPath, local_id: ObjectId, diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 8d6276da2..b06956e56 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -8,6 +8,7 @@ use cyfs_lib::NONObjectInfo; struct RPathControlRaw { network: crate::network::Sender, + } impl RPathControlRaw { @@ -23,9 +24,6 @@ impl RPathControlRaw { unimplemented!() } - async fn on_get_field(&self, sub_path: &str) -> BuckyResult { - unimplemented!() - } } pub struct RPathControl { diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 3b2745e36..9ff10be25 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -13,12 +13,4 @@ impl Listener { pub fn new(vport: u16, bdt_stack: Stack) {} pub fn listen(&self) {} - - pub async fn wait_query_state( - &self, - sub_path: String, - rpath: GroupRPath, - ) -> BuckyResult>> { - unimplemented!() - } } From fdb238976e1d8598873c06a2f0737c1494b03c7c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 16 Jan 2023 21:17:21 +0800 Subject: [PATCH 035/553] interface impl --- src/component/cyfs-base/src/base/error.rs | 4 + .../src/consensus/hotstuff/hotstuff.rs | 34 +- .../src/consensus/vote/committee.rs | 4 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 4 +- .../cyfs-group/src/dec/rpath_client.rs | 92 +++- .../cyfs-group/src/dec/rpath_control.rs | 86 +++- src/component/cyfs-group/src/dec/rpath_mgr.rs | 408 ++++++++++++++++-- .../cyfs-group/src/dec_state/state_pusher.rs | 1 + .../cyfs-group/src/network/non_driver.rs | 4 + .../cyfs-group/src/network/sender.rs | 6 +- .../cyfs-group/src/objects/protocol.rs | 20 +- .../cyfs-group/src/storage/dec_storage.rs | 1 + .../cyfs-group/src/storage/group_storage.rs | 3 + src/component/cyfs-group/src/utils.rs | 2 +- 15 files changed, 584 insertions(+), 86 deletions(-) diff --git a/src/component/cyfs-base/src/base/error.rs b/src/component/cyfs-base/src/base/error.rs index 3ddfd518b..7f158d0dc 100644 --- a/src/component/cyfs-base/src/base/error.rs +++ b/src/component/cyfs-base/src/base/error.rs @@ -126,6 +126,7 @@ pub enum BuckySystemErrorCode { InvalidTarget = 263, ErrorTimestamp = 264, + DecNotRunning = 265, // 在system error code里面,meta_error默认值都取值5000 MetaError = 5000, @@ -242,6 +243,7 @@ pub enum BuckyErrorCode { InvalidTarget, ErrorTimestamp, + DecNotRunning, // meta chain的error段,取值范围是[0, BUCKY_META_ERROR_CODE_MAX) MetaError(u16), @@ -334,6 +336,7 @@ impl Into for BuckyErrorCode { Self::InvalidTarget => BuckySystemErrorCode::InvalidTarget, Self::ErrorTimestamp => BuckySystemErrorCode::ErrorTimestamp, + Self::DecNotRunning => BuckySystemErrorCode::DecNotRunning, Self::MetaError(_) => BuckySystemErrorCode::MetaError, Self::DecError(_) => BuckySystemErrorCode::DecError, @@ -426,6 +429,7 @@ impl Into for BuckySystemErrorCode { Self::InvalidTarget => BuckyErrorCode::InvalidTarget, Self::ErrorTimestamp => BuckyErrorCode::ErrorTimestamp, + Self::DecNotRunning => BuckyErrorCode::DecNotRunning, Self::MetaError => BuckyErrorCode::MetaError(0), Self::DecError => BuckyErrorCode::DecError(0), diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 882d2b64a..4b8e30d2d 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -27,6 +27,7 @@ use crate::{ pub(crate) struct Hotstuff { tx_message: Sender<(HotstuffMessage, ObjectId)>, + state_pusher: StatePusher, } impl Hotstuff { @@ -34,7 +35,7 @@ impl Hotstuff { local_id: ObjectId, committee: Committee, store: GroupStorage, - signer: RsaCPUObjectSigner, + signer: Arc, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, proposal_consumer: PendingProposalConsumer, @@ -43,7 +44,16 @@ impl Hotstuff { ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); + let state_pusher = StatePusher::new( + local_id, + network_sender.clone(), + rpath.clone(), + non_driver.clone(), + ); + let tx_message_runner = tx_message.clone(); + let state_pusher_runner = state_pusher.clone(); + async_std::task::spawn(async move { HotstuffRunner::new( local_id, @@ -55,6 +65,7 @@ impl Hotstuff { tx_message_runner, rx_message, proposal_consumer, + state_pusher_runner, delegate, rpath, ) @@ -62,7 +73,10 @@ impl Hotstuff { .await }); - Self { tx_message } + Self { + tx_message, + state_pusher, + } } pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { @@ -99,13 +113,17 @@ impl Hotstuff { .send((HotstuffMessage::SyncRequest(min_bound, max_bound), remote)) .await; } + + pub async fn request_last_state(&self, remote: ObjectId) { + self.state_pusher.request_last_state(remote).await; + } } struct HotstuffRunner { local_id: ObjectId, committee: Committee, store: GroupStorage, - signer: RsaCPUObjectSigner, + signer: Arc, round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, @@ -129,12 +147,13 @@ impl HotstuffRunner { local_id: ObjectId, committee: Committee, store: GroupStorage, - signer: RsaCPUObjectSigner, + signer: Arc, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, + state_pusher: StatePusher, delegate: Arc>, rpath: GroupRPath, ) -> Self { @@ -157,13 +176,6 @@ impl HotstuffRunner { tx_message.clone(), ); - let state_pusher = StatePusher::new( - local_id, - network_sender.clone(), - rpath.clone(), - non_driver.clone(), - ); - Self { local_id, committee, diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 42edff9b6..56f046c55 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -9,7 +9,9 @@ use crate::{HotstuffBlockQCVote, HotstuffTimeoutVote}; pub(crate) struct Committee {} impl Committee { - pub fn spawn() {} + pub fn new() -> Self { + Committee {} + } pub async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { unimplemented!() diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 0ecaa7802..726d0623a 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -18,3 +18,4 @@ pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; +pub const NET_PROTOCOL_VPORT: u16 = 20; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index f476b915c..9e85ec3a8 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,5 +1,5 @@ use cyfs_base::{BuckyResult, Group, ObjectId}; -use cyfs_core::GroupProposal; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] @@ -8,7 +8,7 @@ pub trait DelegateFactory: Send + Sync { &self, group: &Group, rpath: &str, - with_proposal: Option<&GroupProposal>, + with_block: Option<&GroupConsensusBlock>, ) -> BuckyResult>; async fn on_state_changed( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 2c2479893..058b5ebc7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, RawConvertTo, @@ -12,8 +14,7 @@ use crate::{ HotstuffMessage, CLIENT_POLL_TIMEOUT, }; -#[derive(Clone)] -pub struct RPathClient { +struct RPathClientRaw { rpath: GroupRPath, local_id: ObjectId, non_driver: crate::network::NonDriver, @@ -22,14 +23,17 @@ pub struct RPathClient { state_requestor: DecStateRequestor, } +#[derive(Clone)] +pub struct RPathClient(Arc); + impl RPathClient { - pub fn new( - rpath: GroupRPath, + pub async fn load( local_id: ObjectId, + rpath: GroupRPath, non_driver: crate::network::NonDriver, network_sender: crate::network::Sender, - dec_store: DecStorage, - ) -> Self { + ) -> BuckyResult { + let dec_store = DecStorage::load().await?; let state_sync = DecStateSynchronizer::new( local_id, rpath.clone(), @@ -45,36 +49,39 @@ impl RPathClient { dec_store.clone(), ); - Self { + let raw = RPathClientRaw { rpath, non_driver, network_sender, local_id, state_sync, state_requestor, - } + }; + + Ok(Self(Arc::new(raw))) } pub fn rpath(&self) -> &GroupRPath { - &self.rpath + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.rpath); + assert_eq!(proposal.r_path(), &self.0.rpath); // TODO: signature let group = self + .0 .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let admins = group.select_members_with_distance(&self.local_id, GroupMemberScope::Admin); + let admins = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::Admin); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); - let waiter = self.state_sync.wait_proposal_result(proposal_id).await; + let waiter = self.0.state_sync.wait_proposal_result(proposal_id).await; let mut waiter_future = Some(waiter.wait()); let mut post_result = None; @@ -82,6 +89,7 @@ impl RPathClient { for admin in admins { match self + .0 .non_driver .post_object(non_proposal.clone(), admin) .await @@ -130,30 +138,38 @@ impl RPathClient { // request last state from random admin pub async fn refresh_state(&self) -> BuckyResult<()> { let group = self + .0 .non_driver - .get_group(&self.rpath.group_id(), None, None) + .get_group(&self.0.rpath.group_id(), None, None) .await?; - let admins = group.select_members_with_distance(&self.local_id, GroupMemberScope::Admin); + let admins = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::Admin); let random = rand::thread_rng().gen_range(0..admins.len()); let admin = admins.get(random).unwrap().clone(); - self.network_sender - .post_message(HotstuffMessage::LastStateRequest, self.rpath.clone(), admin) + self.0 + .network_sender + .post_message( + HotstuffMessage::LastStateRequest, + self.0.rpath.clone(), + admin, + ) .await; Ok(()) } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { let group = self + .0 .non_driver - .get_group(self.rpath().group_id(), None, None) + .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.local_id, GroupMemberScope::All); + let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self + .0 .state_requestor .wait_query_state(sub_path.to_string()) .await; @@ -162,8 +178,9 @@ impl RPathClient { let mut exe_result = None; for member in members { - self.network_sender - .post_message(req_msg.clone(), self.rpath.clone(), member) + self.0 + .network_sender + .post_message(req_msg.clone(), self.0.rpath.clone(), member) .await; match futures::future::select( @@ -192,4 +209,39 @@ impl RPathClient { pub async fn get_block(&self, height: Option) -> BuckyResult { unimplemented!() } + + pub(crate) async fn on_message(&self, msg: HotstuffMessage, remote: ObjectId) { + match msg { + HotstuffMessage::Block(block) => unreachable!(), + HotstuffMessage::BlockVote(vote) => unreachable!(), + HotstuffMessage::TimeoutVote(vote) => unreachable!(), + HotstuffMessage::Timeout(tc) => unreachable!(), + HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), + HotstuffMessage::LastStateRequest => unreachable!(), + HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + self.0 + .state_sync + .on_state_change(header_block, qc_block, remote) + .await + } + HotstuffMessage::ProposalResult(proposal_id, result) => { + self.0 + .state_sync + .on_proposal_complete(proposal_id, result, remote) + .await + } + HotstuffMessage::QueryState(sub_path) => { + self.0 + .state_requestor + .on_query_state(sub_path, remote) + .await + } + HotstuffMessage::VerifiableState(sub_path, result) => { + self.0 + .state_requestor + .on_verifiable_state(sub_path, result, remote) + .await + } + } + } } diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index b06956e56..c8033e285 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -1,31 +1,95 @@ use std::sync::Arc; use async_std::sync::Mutex; -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc, ObjectId}; +use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupProposal, GroupRPath, GroupRPathStatus}; use cyfs_lib::NONObjectInfo; +use crate::{ + network::{self, NonDriver}, + storage::GroupStorage, + Committee, Hotstuff, HotstuffMessage, IsCreateRPath, PendingProposalHandler, + PendingProposalMgr, RPathDelegate, +}; + struct RPathControlRaw { - network: crate::network::Sender, - + local_id: ObjectId, + rpath: GroupRPath, + network_sender: crate::network::Sender, + pending_proposal_handle: PendingProposalHandler, + hotstuff: Hotstuff, } -impl RPathControlRaw { +#[derive(Clone)] +pub struct RPathControl(Arc); + +impl RPathControl { + pub(crate) async fn load( + local_id: ObjectId, + rpath: GroupRPath, + signer: Arc, + delegate: Arc>, + network_sender: crate::network::Sender, + non_driver: NonDriver, + store: GroupStorage, + ) -> BuckyResult { + let (pending_proposal_handle, pending_proposal_consumer) = PendingProposalMgr::new(); + let committee = Committee::new(); + let hotstuff = Hotstuff::new( + local_id, + committee.clone(), + store, + signer, + network_sender.clone(), + non_driver, + pending_proposal_consumer, + delegate, + rpath.clone(), + ); + + let raw = RPathControlRaw { + network_sender, + pending_proposal_handle, + local_id, + rpath, + hotstuff, + }; + + Ok(Self(Arc::new(raw))) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } - async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { - unimplemented!() + pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + self.0.pending_proposal_handle.on_proposal(proposal).await } pub fn select_branch(&self, block_id: ObjectId, source: ObjectId) -> BuckyResult<()> { unimplemented!() } -} - -pub struct RPathControl { - raw: Arc, + pub(crate) async fn on_message(&self, msg: HotstuffMessage, remote: ObjectId) { + match msg { + HotstuffMessage::Block(block) => self.0.hotstuff.on_block(block, remote).await, + HotstuffMessage::BlockVote(vote) => self.0.hotstuff.on_block_vote(vote, remote).await, + HotstuffMessage::TimeoutVote(vote) => { + self.0.hotstuff.on_timeout_vote(vote, remote).await + } + HotstuffMessage::Timeout(tc) => self.0.hotstuff.on_timeout(tc, remote).await, + HotstuffMessage::SyncRequest(min_bound, max_bound) => { + self.0 + .hotstuff + .on_sync_request(min_bound, max_bound, remote) + .await + } + HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, + HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), + HotstuffMessage::ProposalResult(_, _) => unreachable!(), + HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::VerifiableState(_, _) => unreachable!(), + } + } } diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index dede06f77..446a10baf 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -1,31 +1,62 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; -use cyfs_base::{BuckyResult, GroupId, ObjectId}; -use cyfs_core::DecAppId; +use async_std::sync::RwLock; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, RsaCPUObjectSigner}; +use cyfs_bdt::Stack; +use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use crate::{DelegateFactory, IsCreateRPath, RPathClient, RPathControl}; +use crate::{ + storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, + RPathClient, RPathControl, NET_PROTOCOL_VPORT, +}; -type ByRPath = HashMap; -type ByDec = HashMap; -type ByGroup = HashMap; +use super::delegate_factory; -pub struct GroupRPathMgr { - by_group: ByGroup, +type ControlByRPath = HashMap; +type ControlByDec = HashMap; +type ControlByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupRPathMgrRaw { + delegate_by_dec: HashMap>, + control_by_group: ControlByGroup, + client_by_group: ClientByGroup, +} + +struct LocalInfo { + local_id: ObjectId, + signer: Arc, + network_sender: crate::network::Sender, + non_driver: crate::network::NonDriver, } +pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); + impl GroupRPathMgr { - pub fn new() -> Self { - Self { - by_group: ByGroup::default(), - } - } + pub fn new( + local_id: ObjectId, + signer: RsaCPUObjectSigner, + non_driver: crate::network::NonDriver, + bdt_stack: Stack, + ) -> Self { + let network_sender = crate::network::Sender::new(NET_PROTOCOL_VPORT, bdt_stack); + let local_info = LocalInfo { + local_id, + signer: Arc::new(signer), + network_sender, + non_driver, + }; - pub async fn start(&self) -> BuckyResult<()> { - unimplemented!() - } + let raw = GroupRPathMgrRaw { + control_by_group: ControlByGroup::default(), + client_by_group: ClientByGroup::default(), + delegate_by_dec: HashMap::default(), + }; - pub async fn close(&self) -> BuckyResult<()> { - unimplemented!() + Self(Arc::new((local_info, RwLock::new(raw)))) } pub async fn register( @@ -33,39 +64,82 @@ impl GroupRPathMgr { dec_id: DecAppId, delegate_factory: Box, ) -> BuckyResult<()> { - unimplemented!() + let mut raw = self.write().await; + raw.delegate_by_dec + .insert(dec_id.object_id().clone(), delegate_factory); + Ok(()) } pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - unimplemented!() + let mut raw = self.write().await; + raw.delegate_by_dec.remove(dec_id.object_id()); + Ok(()) } pub async fn find_rpath_control( &self, - group_id: &GroupId, - dec_id: &DecAppId, + group_id: &ObjectId, + dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: &IsCreateRPath, ) -> BuckyResult { - unimplemented!() + self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + .await } pub async fn rpath_client( &self, - group_id: &GroupId, - dec_id: &DecAppId, + group_id: &ObjectId, + dec_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() - } + { + // read + let raw = self.read().await; + let found = raw + .client_by_group + .get(group_id) + .map_or(None, |by_dec| by_dec.get(dec_id)) + .map_or(None, |by_rpath| by_rpath.get(rpath)); - pub async fn rpath_control( - &self, - group_id: &GroupId, - dec_id: &DecAppId, - rpath: &str, - ) -> BuckyResult { - unimplemented!() + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + // write + + let local_info = self.local_info(); + let local_id = local_info.local_id; + let network_sender = local_info.network_sender.clone(); + let non_driver = local_info.non_driver.clone(); + + let mut raw = self.write().await; + + let found = raw + .client_by_group + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()); + + match found { + std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), + std::collections::hash_map::Entry::Vacant(entry) => { + let client = RPathClient::load( + local_id, + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + non_driver, + network_sender, + ) + .await?; + entry.insert(client.clone()); + Ok(client) + } + } + } } pub async fn set_sync_path(&self, dec_id: &str, path: String) -> BuckyResult<()> { @@ -84,4 +158,266 @@ impl GroupRPathMgr { ) -> BuckyResult> { unimplemented!() } + + fn local_info(&self) -> &LocalInfo { + &self.0 .0 + } + + async fn read(&self) -> async_std::sync::RwLockReadGuard<'_, GroupRPathMgrRaw> { + self.0 .1.read().await + } + + async fn write(&self) -> async_std::sync::RwLockWriteGuard<'_, GroupRPathMgrRaw> { + self.0 .1.write().await + } + + pub(crate) async fn on_message( + &self, + msg: HotstuffPackage, + remote: ObjectId, + ) -> BuckyResult<()> { + match msg { + HotstuffPackage::Block(block) => { + let rpath = block.r_path(); + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + &IsCreateRPath::Yes(None), + Some(&block), + Some(&remote), + ) + .await?; + control + .on_message(HotstuffMessage::Block(block), remote) + .await; + } + HotstuffPackage::BlockVote(target, vote) => { + let rpath = target.check_rpath(); + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + &IsCreateRPath::Yes(None), + None, + Some(&remote), + ) + .await?; + control + .on_message(HotstuffMessage::BlockVote(vote), remote) + .await; + } + HotstuffPackage::TimeoutVote(target, vote) => { + let rpath = target.check_rpath(); + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + &IsCreateRPath::Yes(None), + None, + Some(&remote), + ) + .await?; + control + .on_message(HotstuffMessage::TimeoutVote(vote), remote) + .await; + } + HotstuffPackage::Timeout(target, tc) => { + let rpath = target.check_rpath(); + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + &IsCreateRPath::Yes(None), + None, + Some(&remote), + ) + .await?; + control + .on_message(HotstuffMessage::Timeout(tc), remote) + .await; + } + HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { + let rpath = target.check_rpath(); + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + &IsCreateRPath::Yes(None), + None, + Some(&remote), + ) + .await?; + control + .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) + .await; + } + HotstuffPackage::LastStateRequest(target) => { + let rpath = target.check_rpath(); + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + &IsCreateRPath::Yes(None), + None, + Some(&remote), + ) + .await?; + control + .on_message(HotstuffMessage::LastStateRequest, remote) + .await; + } + HotstuffPackage::StateChangeNotify(target, header_block, qc_block) => { + let rpath = target.check_rpath(); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::StateChangeNotify(header_block, qc_block), + remote, + ) + .await; + } + HotstuffPackage::ProposalResult(target, proposal_id, result) => { + let rpath = target.check_rpath(); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::ProposalResult(proposal_id, result), remote) + .await; + } + HotstuffPackage::QueryState(target, sub_path) => { + let rpath = target.check_rpath(); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + HotstuffPackage::VerifiableState(target, sub_path, result) => { + let rpath = target.check_rpath(); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .await; + } + } + + Ok(()) + } + + async fn find_rpath_control_inner( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + is_auto_create: &IsCreateRPath, + block: Option<&GroupConsensusBlock>, + remote: Option<&ObjectId>, + ) -> BuckyResult { + { + // read + let raw = self.read().await; + let found = raw + .control_by_group + .get(group_id) + .map_or(None, |by_dec| by_dec.get(dec_id)) + .map_or(None, |by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + // write + + let local_info = self.local_info(); + let local_id = local_info.local_id; + let signer = local_info.signer.clone(); + let network_sender = local_info.network_sender.clone(); + let non_driver = local_info.non_driver.clone(); + + let store = GroupStorage::load(group_id, dec_id, rpath, &IsCreateRPath::No).await; + let store = match store { + Ok(store) => Some(store), + Err(e) => { + if let IsCreateRPath::No = is_auto_create { + return Err(e); + } + if let BuckyErrorCode::NotFound = e.code() { + None + } else { + return Err(e); + } + } + }; + + // TODO: query group + let group = self + .local_info() + .non_driver + .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) + .await?; + + let mut raw = self.write().await; + + let delegate = { + let delegate_factory = raw.delegate_by_dec.get(dec_id); + if delegate_factory.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::DecNotRunning, + "dec not running for the rpath-control", + )); + } + let delegate_factory = delegate_factory.unwrap(); + + delegate_factory + .create_rpath_delegate(&group, rpath, block) + .await? + }; + + let store = match store { + Some(store) => store, + None => GroupStorage::load(group_id, dec_id, rpath, is_auto_create).await?, + }; + + let found = raw + .control_by_group + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()); + + match found { + std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), + std::collections::hash_map::Entry::Vacant(entry) => { + let control = RPathControl::load( + local_id, + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + signer, + Arc::new(delegate), + network_sender, + non_driver, + store, + ) + .await?; + entry.insert(control.clone()); + Ok(control) + } + } + } + } } diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 66c3167bd..b3adbd9b4 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -18,6 +18,7 @@ enum StatePushMessage { DelayBroadcast, } +#[derive(Clone)] pub struct StatePusher { local_id: ObjectId, tx_notifier: async_std::channel::Sender, diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 517985a86..6ea4eca2d 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,6 +6,10 @@ use cyfs_lib::NONObjectInfo; pub struct NonDriver {} impl NonDriver { + pub fn new() -> Self { + Self {} + } + pub async fn get_object( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index d721670cc..3f9f36cf5 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -8,7 +8,9 @@ use crate::HotstuffMessage; pub struct Sender {} impl Sender { - pub fn new(vport: u16, bdt_stack: Stack) {} + pub fn new(vport: u16, bdt_stack: Stack) -> Self { + unimplemented!() + } pub(crate) async fn post_message( &self, @@ -16,8 +18,10 @@ impl Sender { rpath: GroupRPath, to: &ObjectId, ) { + unimplemented!() } pub(crate) async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[ObjectId]) { + unimplemented!() } } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 12dd7615a..432067838 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -113,16 +113,21 @@ pub(crate) enum HotstuffPackage { TimeoutVote(ProtocolAddress, HotstuffTimeoutVote), Timeout(ProtocolAddress, cyfs_core::HotstuffTimeout), - SyncRequest(SyncBound, SyncBound), + SyncRequest(ProtocolAddress, SyncBound, SyncBound), StateChangeNotify(ProtocolAddress, GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + LastStateRequest(ProtocolAddress), ProposalResult( ProtocolAddress, ObjectId, - BuckyResult>, + BuckyResult<( + Option, + GroupConsensusBlock, + GroupConsensusBlock, + )>, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, GroupRPathStatus), + VerifiableState(ProtocolAddress, String, BuckyResult), } #[derive(Clone, RawEncode, RawDecode)] @@ -131,6 +136,15 @@ pub(crate) enum ProtocolAddress { Channel(u64), } +impl ProtocolAddress { + pub fn check_rpath(self) -> GroupRPath { + match self { + ProtocolAddress::Full(rpath) => rpath, + ProtocolAddress::Channel(_) => panic!("no rpath"), + } + } +} + #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] #[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] pub(crate) struct HotstuffBlockQCVote { diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index dcf3aca8f..48a7e43a3 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -20,6 +20,7 @@ pub struct DecStorage { impl DecStorage { pub async fn load() -> BuckyResult { + unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), }; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 4a88dc933..35b7dfb5f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -3,6 +3,8 @@ use std::collections::HashMap; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; +use crate::IsCreateRPath; + pub enum BlockLinkState { Expired, DuplicateProposal, @@ -36,6 +38,7 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, + is_auto_create: &IsCreateRPath, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 635999f1e..9fbc4eb4f 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), + Yes(Option), // init state } From e7d35b041daefc4db12f3fba5e86f0e1c30751cb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 17 Jan 2023 13:11:43 +0800 Subject: [PATCH 036/553] network --- src/component/cyfs-group/src/dec/rpath_mgr.rs | 15 +++-- .../cyfs-group/src/network/listener.rs | 36 ++++++++---- .../cyfs-group/src/network/non_driver.rs | 6 +- .../cyfs-group/src/network/sender.rs | 56 ++++++++++++++++--- .../cyfs-group/src/objects/protocol.rs | 39 +++++++++++++ 5 files changed, 128 insertions(+), 24 deletions(-) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 446a10baf..97adb5c2f 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -10,8 +10,6 @@ use crate::{ RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; -use super::delegate_factory; - type ControlByRPath = HashMap; type ControlByDec = HashMap; type ControlByGroup = HashMap; @@ -33,6 +31,7 @@ struct LocalInfo { non_driver: crate::network::NonDriver, } +#[derive(Clone)] pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); impl GroupRPathMgr { @@ -41,8 +40,10 @@ impl GroupRPathMgr { signer: RsaCPUObjectSigner, non_driver: crate::network::NonDriver, bdt_stack: Stack, - ) -> Self { - let network_sender = crate::network::Sender::new(NET_PROTOCOL_VPORT, bdt_stack); + ) -> BuckyResult { + let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; + let network_sender = crate::network::Sender::new(datagram.clone(), non_driver.clone()); + let local_info = LocalInfo { local_id, signer: Arc::new(signer), @@ -56,7 +57,11 @@ impl GroupRPathMgr { delegate_by_dec: HashMap::default(), }; - Self(Arc::new((local_info, RwLock::new(raw)))) + let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); + + crate::network::Listener::spawn(datagram, mgr.clone()); + + Ok(mgr) } pub async fn register( diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 9ff10be25..6124a9cb5 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -1,16 +1,32 @@ -use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_bdt::Stack; -use cyfs_core::GroupRPath; -use cyfs_lib::NONObjectInfo; +use cyfs_base::RawDecode; +use cyfs_bdt::DatagramTunnelGuard; -use crate::{dec_state::CallReplyWaiter, CHANNEL_CAPACITY}; +use crate::{GroupRPathMgr, HotstuffPackage}; -pub struct Listener { - wait_seq: u64, -} +pub struct Listener; impl Listener { - pub fn new(vport: u16, bdt_stack: Stack) {} + pub fn spawn(datagram: DatagramTunnelGuard, processor: GroupRPathMgr) { + async_std::task::spawn(async move { + Self::run(datagram, processor).await; + }); + } - pub fn listen(&self) {} + async fn run(datagram: DatagramTunnelGuard, processor: GroupRPathMgr) { + loop { + match datagram.recv_v().await { + Ok(pkgs) => { + for pkg in pkgs { + let remote = pkg.source.remote.object_id().clone(); + if let Ok((pkg, remain)) = HotstuffPackage::raw_decode(pkg.data.as_slice()) + { + assert_eq!(remain.len(), 0); + processor.on_message(pkg, remote).await; + } + } + } + Err(e) => log::warn!("group listener failed: {:?}", e), + } + } + } } diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 6ea4eca2d..6cbe8c85d 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, RawDecode}; +use cyfs_base::{BuckyResult, DeviceId, Group, ObjectId, PeopleId, RawDecode}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -56,4 +56,8 @@ impl NonDriver { ) -> BuckyResult { unimplemented!() } + + pub async fn get_ood(&self, people_id: &PeopleId) -> BuckyResult { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 3f9f36cf5..8419b33bd 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -1,15 +1,26 @@ -use cyfs_base::ObjectId; -use cyfs_bdt::Stack; +use cyfs_base::{DeviceId, ObjectId, PeopleId, RawEncode}; +use cyfs_bdt::{DatagramOptions, DatagramTunnelGuard}; use cyfs_core::GroupRPath; -use crate::HotstuffMessage; +use crate::{HotstuffMessage, HotstuffPackage}; + +use super::{non_driver, NonDriver}; #[derive(Clone)] -pub struct Sender {} +pub struct Sender { + datagram: DatagramTunnelGuard, + vport: u16, + non_driver: NonDriver, +} impl Sender { - pub fn new(vport: u16, bdt_stack: Stack) -> Self { - unimplemented!() + pub fn new(datagram: DatagramTunnelGuard, non_driver: NonDriver) -> Self { + let vport = datagram.vport(); + Self { + datagram, + vport, + non_driver, + } } pub(crate) async fn post_message( @@ -18,10 +29,39 @@ impl Sender { rpath: GroupRPath, to: &ObjectId, ) { - unimplemented!() + let pkg = HotstuffPackage::from_msg(msg, rpath); + let len = pkg.raw_measure(&None).unwrap(); + let mut buf = Vec::with_capacity(len); + buf.resize(len, 0); + let remain = pkg.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + + let mut options = DatagramOptions::default(); + + let remote = match to.obj_type_code() { + cyfs_base::ObjectTypeCode::Device => DeviceId::try_from(to).unwrap(), + cyfs_base::ObjectTypeCode::People => { + let people_id = PeopleId::try_from(to).unwrap(); + match self.non_driver.get_ood(&people_id).await { + Ok(device_id) => device_id, + Err(e) => { + log::warn!("[group-sender] post message to {}, failed err: {:?}", to, e); + return; + } + } + } + _ => panic!("invalid remote type: {:?}", to.obj_type_code()), + }; + + self.datagram + .send_to(buf.as_slice(), &mut options, &remote, self.vport); } pub(crate) async fn broadcast(&self, msg: HotstuffMessage, rpath: GroupRPath, to: &[ObjectId]) { - unimplemented!() + futures::future::join_all( + to.iter() + .map(|remote| self.post_message(msg.clone(), rpath.clone(), remote)), + ) + .await; } } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 432067838..dbdbb176d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -130,6 +130,45 @@ pub(crate) enum HotstuffPackage { VerifiableState(ProtocolAddress, String, BuckyResult), } +impl HotstuffPackage { + pub fn from_msg(msg: HotstuffMessage, rpath: GroupRPath) -> Self { + match msg { + HotstuffMessage::Block(block) => HotstuffPackage::Block(block), + HotstuffMessage::BlockVote(vote) => { + HotstuffPackage::BlockVote(ProtocolAddress::Full(rpath), vote) + } + HotstuffMessage::TimeoutVote(vote) => { + HotstuffPackage::TimeoutVote(ProtocolAddress::Full(rpath), vote) + } + HotstuffMessage::Timeout(tc) => { + HotstuffPackage::Timeout(ProtocolAddress::Full(rpath), tc) + } + HotstuffMessage::SyncRequest(min_bound, max_bound) => { + HotstuffPackage::SyncRequest(ProtocolAddress::Full(rpath), min_bound, max_bound) + } + HotstuffMessage::LastStateRequest => { + HotstuffPackage::LastStateRequest(ProtocolAddress::Full(rpath)) + } + HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffPackage::StateChangeNotify( + ProtocolAddress::Full(rpath), + header_block, + qc_block, + ) + } + HotstuffMessage::ProposalResult(proposal_id, result) => { + HotstuffPackage::ProposalResult(ProtocolAddress::Full(rpath), proposal_id, result) + } + HotstuffMessage::QueryState(sub_path) => { + HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) + } + HotstuffMessage::VerifiableState(sub_path, result) => { + HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) + } + } + } +} + #[derive(Clone, RawEncode, RawDecode)] pub(crate) enum ProtocolAddress { Full(GroupRPath), From 1ada8d115469cd588b36cdfd2e33478830be7a8d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 17 Jan 2023 20:51:25 +0800 Subject: [PATCH 037/553] vote verify --- src/component/cyfs-base/src/objects/group.rs | 4 + .../src/group/group_consensus_block.rs | 5 + .../src/consensus/hotstuff/hotstuff.rs | 46 ++- .../src/consensus/vote/committee.rs | 332 +++++++++++++++++- .../cyfs-group/src/dec/rpath_client.rs | 20 +- .../cyfs-group/src/dec/rpath_control.rs | 17 +- src/component/cyfs-group/src/dec/rpath_mgr.rs | 30 +- .../cyfs-group/src/network/non_driver.rs | 6 +- .../cyfs-group/src/network/sender.rs | 2 +- .../cyfs-group/src/objects/protocol.rs | 24 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- 11 files changed, 431 insertions(+), 67 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 001af4ae8..bab348c55 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -325,6 +325,10 @@ impl Group { unimplemented!() } + pub fn ood_list_with_distance(&self, target: &ObjectId) -> Vec<&ObjectId> { + unimplemented!() + } + // pub fn group_hash(&self) -> ObjectId { // let mut without_sign = self.clone(); // without_sign.common_mut().join_signatures = vec![]; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index bd1d46ecb..a2f140d23 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -227,6 +227,7 @@ pub trait GroupConsensusBlockObject { fn prev_block_id(&self) -> Option<&ObjectId>; fn owner(&self) -> &ObjectId; fn named_object(&self) -> &NamedObjectBase; + fn named_object_mut(&mut self) -> &mut NamedObjectBase; fn round(&self) -> u64; fn group_chunk_id(&self) -> &ObjectId; fn qc(&self) -> &Option; @@ -323,6 +324,10 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &self.0 } + fn named_object_mut(&mut self) -> &mut NamedObjectBase { + &mut self.0 + } + fn round(&self) -> u64 { let desc = self.0.desc().content(); desc.round diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 4b8e30d2d..5d0f9c364 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -3,7 +3,8 @@ use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, RawConvertTo, RawDecode, RsaCPUObjectSigner, + ObjectDesc, ObjectId, ObjectLink, RawConvertTo, RawDecode, RawEncode, RsaCPUObjectSigner, + SignatureSource, Signer, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -33,6 +34,7 @@ pub(crate) struct Hotstuff { impl Hotstuff { pub fn new( local_id: ObjectId, + local_device_id: ObjectId, committee: Committee, store: GroupStorage, signer: Arc, @@ -57,6 +59,7 @@ impl Hotstuff { async_std::task::spawn(async move { HotstuffRunner::new( local_id, + local_device_id, committee, store, signer, @@ -121,6 +124,7 @@ impl Hotstuff { struct HotstuffRunner { local_id: ObjectId, + local_device_id: ObjectId, committee: Committee, store: GroupStorage, signer: Arc, @@ -145,6 +149,7 @@ impl HotstuffRunner { #[allow(clippy::too_many_arguments)] pub fn new( local_id: ObjectId, + local_device_id: ObjectId, committee: Committee, store: GroupStorage, signer: Arc, @@ -178,6 +183,7 @@ impl HotstuffRunner { Self { local_id, + local_device_id, committee, store, signer, @@ -286,7 +292,7 @@ impl HotstuffRunner { } }; - self.committee.verify_block(block).await?; + self.committee.verify_block(block, remote).await?; self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) .await?; @@ -521,7 +527,12 @@ impl HotstuffRunner { return None; } - let vote = match HotstuffBlockQCVote::new(block, self.local_id, &self.signer).await { + match self.check_group_is_latest(block.group_chunk_id()).await { + Ok(is_latest) if is_latest => {} + _ => return None, + } + + let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => vote, Err(e) => { log::warn!( @@ -715,7 +726,7 @@ impl HotstuffRunner { let timeout = HotstuffTimeoutVote::new( self.high_qc.clone(), self.round, - self.local_id, + self.local_device_id, &self.signer, ) .await?; @@ -854,7 +865,7 @@ impl HotstuffRunner { .unwrap() .calculate_id(); - let block = GroupConsensusBlock::create( + let mut block = GroupConsensusBlock::create( self.rpath.clone(), proposals_param, result_state_id, @@ -867,6 +878,8 @@ impl HotstuffRunner { self.local_id, ); + self.sign_block(&mut block).await?; + self.tx_message .send((HotstuffMessage::Block(block.clone()), self.local_id)) .await; @@ -878,6 +891,22 @@ impl HotstuffRunner { Ok(()) } + async fn sign_block(&self, block: &mut GroupConsensusBlock) -> BuckyResult<()> { + let sign_source = SignatureSource::Object(ObjectLink { + obj_id: self.local_device_id, + obj_owner: None, + }); + + let desc_hash = block.named_object().desc().raw_hash_encode()?; + let signature = self.signer.sign(desc_hash.as_slice(), &sign_source).await?; + block + .named_object_mut() + .signs_mut() + .set_desc_sign(signature); + + Ok(()) + } + async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { let targets: Vec = group .ood_list() @@ -940,6 +969,13 @@ impl HotstuffRunner { Ok(()) } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { + let latest_group = self.committee.get_group(None).await?; + let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; + let latest_chunk_id = group_chunk.calculate_id(); + Ok(latest_chunk_id.as_object_id() == group_chunk_id) + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 56f046c55..135256d7a 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -1,20 +1,37 @@ -use std::collections::HashSet; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; -use cyfs_base::{BuckyResult, Group, ObjectId}; -use cyfs_core::{GroupConsensusBlock, HotstuffTimeout}; +use async_std::sync::RwLock; +use cyfs_base::{ + verify_object_desc_sign, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, + ObjectDesc, ObjectId, OwnerObjectDesc, RsaCPUObjectVerifier, SignatureSource, + SingleKeyObjectDesc, Verifier, +}; +use cyfs_chunk_lib::ChunkMeta; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use crate::{HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NonDriver, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] -pub(crate) struct Committee {} +pub(crate) struct Committee { + group_id: ObjectId, + non_driver: NonDriver, + group_cache: Arc>>, // (group_chunk_id, group) +} impl Committee { - pub fn new() -> Self { - Committee {} + pub fn new(group_id: ObjectId, non_driver: NonDriver) -> Self { + Committee { + group_id, + non_driver, + group_cache: Arc::new(RwLock::new(HashMap::new())), + } } pub async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() + self.check_group(group_chunk_id, None).await } pub async fn quorum_threshold( @@ -22,7 +39,14 @@ impl Committee { voters: &HashSet, group_chunk_id: Option<&ObjectId>, ) -> BuckyResult { - unimplemented!() + let group = self.check_group(group_chunk_id, None).await?; + let voters: Vec<&ObjectId> = voters + .iter() + .filter(|id| group.admins().iter().find(|mem| mem.id == **id).is_some()) + .collect(); + + let is_enough = voters.len() >= ((group.admins().len() << 1) / 3 + 1); + Ok(is_enough) } pub async fn get_leader( @@ -30,35 +54,307 @@ impl Committee { group_chunk_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { - unimplemented!() + let group = self.check_group(group_chunk_id, None).await?; + let i = (round % (group.admins().len() as u64)) as usize; + Ok(group.admins()[i].id) } - pub async fn verify_block(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { - unimplemented!() + pub async fn verify_block( + &self, + block: &GroupConsensusBlock, + from: ObjectId, + ) -> BuckyResult<()> { /* * * 验证block下的签名是否符合对上一个block归属group的确认 */ + if !block.check() { + log::warn!( + "[group committee] error block with invalid content: {}", + block.named_object().desc().calculate_id() + ) + } + + let group = self + .check_group(Some(block.group_chunk_id()), Some(&from)) + .await?; + + if !self.check_block_sign(&block, &group).await? { + log::warn!( + "[group committee] check signature failed: {}", + block.named_object().desc().calculate_id() + ); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid signature", + )); + } + + let prev_block = if let Some(qc) = block.qc() { + let prev_block = self.non_driver.get_block(&qc.block_id, None).await?; + self.verify_qc(qc, &prev_block).await?; + Some(prev_block) + } else { + None + }; + + if let Some(tc) = block.tc() { + self.verify_tc(tc, prev_block.as_ref()).await?; + } + + Ok(()) } pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { - unimplemented!() + let hash = vote.hash(); + let device = self.non_driver.get_device(&vote.voter).await?; + let verifier = RsaCPUObjectVerifier::new(device.desc().public_key().clone()); + let is_ok = verifier.verify(hash.as_slice(), &vote.signature).await; + if !is_ok { + log::warn!("[group committee] vote with error signature"); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid signature", + )); + } + Ok(()) } pub async fn verify_timeout( &self, vote: &HotstuffTimeoutVote, - pre_block: Option<&GroupConsensusBlock>, + prev_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { // 用block验vote.high_qc - unimplemented!() + let hash = vote.hash(); + let device = self.non_driver.get_device(&vote.voter).await?; + let verifier = RsaCPUObjectVerifier::new(device.desc().public_key().clone()); + let is_ok = verifier.verify(hash.as_slice(), &vote.signature).await; + if !is_ok { + log::warn!("[group committee] vote with error signature"); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid signature", + )); + } + + if let Some(high_qc) = vote.high_qc.as_ref() { + let prev_block = prev_block.expect("no block for high-qc in timeout"); + if prev_block.round() != high_qc.round { + log::warn!("[group committee] vote with error round in timeout"); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid round", + )); + } + self.verify_qc(high_qc, prev_block).await?; + } + Ok(()) } pub async fn verify_tc( &self, tc: &HotstuffTimeout, - pre_block: Option<&GroupConsensusBlock>, + prev_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { - // 用block验vote.high_qc - unimplemented!() + let highest_round = tc.votes.iter().map(|v| v.high_qc_round).max(); + if highest_round != prev_block.map(|b| b.round()) { + log::warn!("[group committee] hightest round is not match with prev-block in tc"); + return Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "rount not match in tc", + )); + } + + let is_enough = self + .quorum_threshold( + &tc.votes.iter().map(|v| v.voter).collect(), + prev_block.map(|b| b.group_chunk_id()), + ) + .await?; + + if !is_enough { + log::warn!("[group committee] tc with vote not enough."); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "not enough", + )); + } + + let verify_vote_results = futures::future::join_all(tc.votes.iter().map(|vote| async { + let hash = HotstuffTimeoutVote::hash_content(vote.high_qc_round, tc.round); + match self.non_driver.get_device(&vote.voter).await { + Ok(device) => { + let verifier = RsaCPUObjectVerifier::new(device.desc().public_key().clone()); + let is_ok = verifier.verify(hash.as_slice(), &vote.signature).await; + if !is_ok { + log::warn!("[group committee] vote with error signature"); + Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "invalid signature", + )) + } else { + Ok(()) + } + } + Err(e) => Err(e), + } + })) + .await; + + verify_vote_results + .into_iter() + .find(|r| r.is_err()) + .map_or(Ok(()), |e| e) + } + + pub async fn verify_qc( + &self, + qc: &HotstuffBlockQC, + prev_block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + if qc.round != prev_block.round() { + log::warn!("[group committee] round is not match with prev-block in qc"); + return Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "rount not match in qc", + )); + } + + let is_enough = self + .quorum_threshold( + &qc.votes.iter().map(|v| v.voter).collect(), + Some(prev_block.group_chunk_id()), + ) + .await?; + + if !is_enough { + log::warn!("[group committee] qc with vote not enough."); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "not enough", + )); + } + + let vote_verify_results = futures::future::join_all(qc.votes.iter().map(|vote| async { + let vote = HotstuffBlockQCVote { + block_id: qc.block_id, + prev_block_id: qc.prev_block_id.clone(), + round: qc.round, + voter: vote.voter, + signature: vote.signature.clone(), + }; + self.verify_vote(&vote).await + })) + .await; + + vote_verify_results + .into_iter() + .find(|r| r.is_err()) + .map_or(Ok(()), |e| e) + } + + async fn check_group( + &self, + chunk_id: Option<&ObjectId>, + from: Option<&ObjectId>, + ) -> BuckyResult { + { + // read + let cache = self.group_cache.read().await; + if let Some(chunk_id) = chunk_id { + if let Some(group) = cache.get(chunk_id) { + return Ok(group.clone()); + } + } + } + + let group = self + .non_driver + .get_group(&self.group_id, chunk_id, from) + .await?; + + let group_chunk = ChunkMeta::from(&group).to_chunk().await?; + let calc_id = group_chunk.calculate_id().object_id(); + if let Some(id) = chunk_id { + assert_eq!(&calc_id, id); + } + + { + // write + let mut cache = self.group_cache.write().await; + match cache.entry(calc_id) { + std::collections::hash_map::Entry::Occupied(mut entry) => { + if entry.get().version() < group.version() { + entry.insert(group.clone()); + } + } + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(group.clone()); + } + } + } + + Ok(group) + } + + async fn check_block_sign( + &self, + block: &GroupConsensusBlock, + group: &Group, + ) -> BuckyResult { + let signs = match block.named_object().signs().desc_signs() { + Some(signs) if signs.len() > 0 => signs, + _ => { + log::warn!("[group committee] no signatures"); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "not signature", + )); + } + }; + + let mut sign_device = None; + + for sign in signs { + if let SignatureSource::Object(obj) = sign.sign_source() { + if let Ok(device) = self.non_driver.get_device(&obj.obj_id).await { + let device_id = device.desc().device_id(); + if group.ood_list().contains(&device_id) + && device.desc().owner().and_then(|dev_owner| { + block + .named_object() + .desc() + .owner() + .and_then(|blk_owner| Some(dev_owner == dev_owner)) + }) == Some(true) + { + sign_device = Some((device, sign)); + break; + } else { + log::warn!("[group committee] block signed by invalid object."); + } + } + } else { + log::warn!("[group committee] support the SignatureSource::Object only."); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "not SignatureSource::Object", + )); + } + } + + let sign_device = match sign_device { + Some(device) => device, + None => { + log::warn!("[group committee] not found the sign device."); + return Err(BuckyError::new( + BuckyErrorCode::InvalidSignature, + "not found device", + )); + } + }; + + let verifier = RsaCPUObjectVerifier::new(sign_device.0.desc().public_key().clone()); + verify_object_desc_sign(&verifier, block.named_object(), &sign_device.1).await } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 058b5ebc7..859461842 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -77,7 +77,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let admins = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::Admin); + let oods = group.ood_list_with_distance(&self.0.local_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -87,11 +87,11 @@ impl RPathClient { let mut post_result = None; let mut exe_result = None; - for admin in admins { + for ood in oods { match self .0 .non_driver - .post_object(non_proposal.clone(), admin) + .post_object(non_proposal.clone(), ood) .await { Ok(r) => post_result = Some(Ok(())), @@ -135,7 +135,7 @@ impl RPathClient { ) } - // request last state from random admin + // request last state from random ood in group.ood_list() pub async fn refresh_state(&self) -> BuckyResult<()> { let group = self .0 @@ -143,17 +143,13 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let admins = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::Admin); - let random = rand::thread_rng().gen_range(0..admins.len()); - let admin = admins.get(random).unwrap().clone(); + let oods = group.ood_list_with_distance(&self.0.local_id); + let random = rand::thread_rng().gen_range(0..oods.len()); + let ood = oods.get(random).unwrap().clone(); self.0 .network_sender - .post_message( - HotstuffMessage::LastStateRequest, - self.0.rpath.clone(), - admin, - ) + .post_message(HotstuffMessage::LastStateRequest, self.0.rpath.clone(), ood) .await; Ok(()) } diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c8033e285..55e844f5a 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -1,16 +1,11 @@ use std::sync::Arc; -use async_std::sync::Mutex; -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; -use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupProposal, GroupRPath, GroupRPathStatus}; -use cyfs_lib::NONObjectInfo; +use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_core::{GroupProposal, GroupRPath}; use crate::{ - network::{self, NonDriver}, - storage::GroupStorage, - Committee, Hotstuff, HotstuffMessage, IsCreateRPath, PendingProposalHandler, - PendingProposalMgr, RPathDelegate, + network::NonDriver, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, + PendingProposalHandler, PendingProposalMgr, RPathDelegate, }; struct RPathControlRaw { @@ -27,6 +22,7 @@ pub struct RPathControl(Arc); impl RPathControl { pub(crate) async fn load( local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, delegate: Arc>, @@ -35,9 +31,10 @@ impl RPathControl { store: GroupStorage, ) -> BuckyResult { let (pending_proposal_handle, pending_proposal_consumer) = PendingProposalMgr::new(); - let committee = Committee::new(); + let committee = Committee::new(rpath.group_id().clone(), non_driver.clone()); let hotstuff = Hotstuff::new( local_id, + local_device_id, committee.clone(), store, signer, diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 97adb5c2f..54530ad9b 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -29,6 +29,7 @@ struct LocalInfo { signer: Arc, network_sender: crate::network::Sender, non_driver: crate::network::NonDriver, + bdt_stack: Stack, } #[derive(Clone)] @@ -49,6 +50,7 @@ impl GroupRPathMgr { signer: Arc::new(signer), network_sender, non_driver, + bdt_stack, }; let raw = GroupRPathMgrRaw { @@ -86,7 +88,7 @@ impl GroupRPathMgr { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: &IsCreateRPath, + is_auto_create: IsCreateRPath, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -189,7 +191,7 @@ impl GroupRPathMgr { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - &IsCreateRPath::Yes(None), + IsCreateRPath::Yes(None), Some(&block), Some(&remote), ) @@ -205,7 +207,7 @@ impl GroupRPathMgr { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - &IsCreateRPath::Yes(None), + IsCreateRPath::Yes(None), None, Some(&remote), ) @@ -221,7 +223,7 @@ impl GroupRPathMgr { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - &IsCreateRPath::Yes(None), + IsCreateRPath::Yes(None), None, Some(&remote), ) @@ -237,7 +239,7 @@ impl GroupRPathMgr { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - &IsCreateRPath::Yes(None), + IsCreateRPath::Yes(None), None, Some(&remote), ) @@ -253,7 +255,7 @@ impl GroupRPathMgr { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - &IsCreateRPath::Yes(None), + IsCreateRPath::Yes(None), None, Some(&remote), ) @@ -269,7 +271,7 @@ impl GroupRPathMgr { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - &IsCreateRPath::Yes(None), + IsCreateRPath::Yes(None), None, Some(&remote), ) @@ -327,7 +329,7 @@ impl GroupRPathMgr { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: &IsCreateRPath, + is_auto_create: IsCreateRPath, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -353,8 +355,9 @@ impl GroupRPathMgr { let signer = local_info.signer.clone(); let network_sender = local_info.network_sender.clone(); let non_driver = local_info.non_driver.clone(); + let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, &IsCreateRPath::No).await; + let store = GroupStorage::load(group_id, dec_id, rpath).await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -395,7 +398,13 @@ impl GroupRPathMgr { let store = match store { Some(store) => store, - None => GroupStorage::load(group_id, dec_id, rpath, is_auto_create).await?, + None => { + let init_state = match is_auto_create { + IsCreateRPath::Yes(init_state) => init_state, + _ => unreachable!(), + }; + GroupStorage::create(group_id, dec_id, rpath, init_state).await? + } }; let found = raw @@ -411,6 +420,7 @@ impl GroupRPathMgr { std::collections::hash_map::Entry::Vacant(entry) => { let control = RPathControl::load( local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, Arc::new(delegate), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 6cbe8c85d..c62446d5d 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, DeviceId, Group, ObjectId, PeopleId, RawDecode}; +use cyfs_base::{BuckyResult, Device, DeviceId, Group, ObjectId, PeopleId, RawDecode}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -60,4 +60,8 @@ impl NonDriver { pub async fn get_ood(&self, people_id: &PeopleId) -> BuckyResult { unimplemented!() } + + pub async fn get_device(&self, device_id: &ObjectId) -> BuckyResult { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 8419b33bd..c087aa456 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -4,7 +4,7 @@ use cyfs_core::GroupRPath; use crate::{HotstuffMessage, HotstuffPackage}; -use super::{non_driver, NonDriver}; +use super::NonDriver; #[derive(Clone)] pub struct Sender { diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index dbdbb176d..a0edf1ae1 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -197,7 +197,7 @@ pub(crate) struct HotstuffBlockQCVote { impl HotstuffBlockQCVote { pub async fn new( block: &GroupConsensusBlock, - local_id: ObjectId, + local_device_id: ObjectId, signer: &RsaCPUObjectSigner, ) -> BuckyResult { let block_id = block.named_object().desc().object_id(); @@ -205,20 +205,23 @@ impl HotstuffBlockQCVote { let signature = signer .sign( Self::hash_content(&block_id, block.prev_block_id(), round).as_slice(), - &SignatureSource::RefIndex(0), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), ) .await?; Ok(Self { block_id, round, - voter: local_id, + voter: local_device_id, signature, prev_block_id: block.prev_block_id().map(|id| id.clone()), }) } - fn hash(&self) -> HashValue { + pub fn hash(&self) -> HashValue { Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) } @@ -282,29 +285,32 @@ impl HotstuffTimeoutVote { pub async fn new( high_qc: Option, round: u64, - local_id: ObjectId, + local_device_id: ObjectId, signer: &RsaCPUObjectSigner, ) -> BuckyResult { let signature = signer .sign( Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::RefIndex(0), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), ) .await?; Ok(Self { high_qc, round, - voter: local_id, + voter: local_device_id, signature, }) } - fn hash(&self) -> HashValue { + pub fn hash(&self) -> HashValue { Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) } - fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { let mut sha256 = sha2::Sha256::new(); sha256.input(high_qc_round.to_le_bytes()); sha256.input(round.to_le_bytes()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 35b7dfb5f..9d99392f1 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -34,11 +34,21 @@ pub struct GroupStorage { } impl GroupStorage { + pub async fn create( + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + init_state_id: Option, + ) -> BuckyResult { + // 用hash加载chunk + // 从chunk解析group + unimplemented!() + } + pub async fn load( group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: &IsCreateRPath, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group From b8f529ef1dd758d15fe7afe260493f740fa5b480 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 18 Jan 2023 14:15:12 +0800 Subject: [PATCH 038/553] TODO: check timestamp --- src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 5d0f9c364..064f465ef 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -512,6 +512,8 @@ impl HotstuffRunner { return None; } + // TODO: 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + // round只能逐个递增 let is_valid_round = if block.round() == block.qc().as_ref().map_or(0, |qc| qc.round) + 1 { true From a8caa8e2ad81081980d4a47d1aab0600d95e18f9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 18 Jan 2023 14:44:56 +0800 Subject: [PATCH 039/553] support the result-state is None --- .../cyfs-core/protos/core_objects.proto | 4 +-- .../src/group/group_consensus_block.rs | 21 ++++++++------ .../src/consensus/hotstuff/hotstuff.rs | 4 +-- .../cyfs-group/src/dec/delegate_factory.rs | 14 +++++----- .../cyfs-group/src/storage/group_storage.rs | 28 ++++++------------- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 4bde48310..96a378d24 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -393,7 +393,7 @@ message GroupConsensusBlockDescContent { bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) // result - bytes result_state_id = 3; + optional bytes result_state_id = 3; uint64 height = 4; // time @@ -407,7 +407,7 @@ message GroupConsensusBlockDescContent { message GroupConsensusBlockBodyContent { message Proposal { bytes proposal_id = 1; - bytes proposal_result_state = 2; + optional bytes proposal_result_state = 2; optional bytes proposal_receipt = 3; optional bytes context = 4; } diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index a2f140d23..aa1c75c03 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -13,7 +13,7 @@ use sha2::Digest; pub struct GroupConsensusBlockDescContent { r_path: GroupRPath, body_hash: HashValue, - result_state_id: ObjectId, + result_state_id: Option, height: u64, meta_block_id: ObjectId, timestamp: u64, @@ -125,7 +125,7 @@ pub struct HotstuffTimeout { #[cyfs_protobuf_type(crate::codec::protos::group_consensus_block_body_content::Proposal)] pub struct GroupConsensusBlockProposal { pub proposal: ObjectId, - pub result_state: ObjectId, + pub result_state: Option, pub receipt: Option>, pub context: Option>, } @@ -136,9 +136,14 @@ impl ProtobufTransform BuckyResult { + let result_state = match value.proposal_result_state { + Some(state_id) => Some(ObjectId::raw_decode(state_id.as_slice())?.0), + None => None, + }; + Ok(Self { proposal: ObjectId::raw_decode(value.proposal_id.as_slice())?.0, - result_state: ObjectId::raw_decode(&value.proposal_result_state.as_slice())?.0, + result_state, receipt: value.proposal_receipt.take(), context: value.context.take(), }) @@ -151,7 +156,7 @@ impl ProtobufTransform<&GroupConsensusBlockProposal> fn transform(value: &GroupConsensusBlockProposal) -> BuckyResult { Ok(Self { proposal_id: value.proposal.to_vec()?, - proposal_result_state: value.result_state.to_vec()?, + proposal_result_state: value.result_state.map(|id| id.to_vec().unwrap()), proposal_receipt: value.receipt.clone(), context: value.context.clone(), }) @@ -209,7 +214,7 @@ pub trait GroupConsensusBlockObject { fn create( r_path: GroupRPath, proposals: Vec, - result_state_id: ObjectId, + result_state_id: Option, height: u64, meta_block_id: ObjectId, round: u64, @@ -221,7 +226,7 @@ pub trait GroupConsensusBlockObject { fn check(&self) -> bool; fn r_path(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; - fn result_state_id(&self) -> &ObjectId; + fn result_state_id(&self) -> &Option; fn height(&self) -> u64; fn meta_block_id(&self) -> &ObjectId; fn prev_block_id(&self) -> Option<&ObjectId>; @@ -238,7 +243,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( r_path: GroupRPath, proposals: Vec, - result_state_id: ObjectId, + result_state_id: Option, height: u64, meta_block_id: ObjectId, round: u64, @@ -295,7 +300,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { &body.proposals } - fn result_state_id(&self) -> &ObjectId { + fn result_state_id(&self) -> &Option { let desc = self.0.desc().content(); &desc.result_state_id } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 064f465ef..7b87e8752 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -360,7 +360,7 @@ impl HotstuffRunner { ) -> BuckyResult<()> { let mut prev_state_id = prev_block .as_ref() - .map_or(ObjectId::default(), |block| block.result_state_id().clone()); + .map_or(None, |block| block.result_state_id().clone()); for proposal_exe_info in block.proposals() { // TODO: 去重 @@ -765,7 +765,7 @@ impl HotstuffRunner { let mut failed_proposals = vec![]; let mut result_state_id = match pre_block.as_ref() { Some(block) => block.result_state_id().clone(), - None => self.store.dec_state_id(), + None => self.store.dec_state_id().clone(), }; // TODO: The time may be too long for too many proposals diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 9e85ec3a8..289bfc6f7 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -15,15 +15,15 @@ pub trait DelegateFactory: Send + Sync { &self, group_id: &ObjectId, rpath: &str, - state_id: ObjectId, + state_id: Option, pre_state_id: Option, ); } pub struct ExecuteResult { - pub result_state_id: ObjectId, // pack block - pub receipt: Option, // to client - pub context: Option>, // timestamp etc. + pub result_state_id: Option, // pack block + pub receipt: Option, // to client + pub context: Option>, // timestamp etc. } #[async_trait::async_trait] @@ -33,20 +33,20 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, execute_result: &ExecuteResult, ); } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 9d99392f1..366f0d400 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -3,8 +3,6 @@ use std::collections::HashMap; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; -use crate::IsCreateRPath; - pub enum BlockLinkState { Expired, DuplicateProposal, @@ -55,36 +53,28 @@ impl GroupStorage { unimplemented!() } - pub async fn insert( - group_id: &ObjectId, - dec_id: &ObjectId, - rpath: &str, - ) -> BuckyResult { - unimplemented!() - } - pub fn header_block(&self) -> &Option { - unimplemented!() + &self.header_block } pub fn header_round(&self) -> u64 { - unimplemented!() + self.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - unimplemented!() + self.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - unimplemented!() + &self.first_block } pub fn prepares(&self) -> &HashMap { - unimplemented!() + &self.prepares } pub fn pre_commits(&self) -> &HashMap { - unimplemented!() + &self.pre_commits } pub fn group(&self) -> &Group { @@ -92,11 +82,11 @@ impl GroupStorage { } pub fn group_chunk_id(&self) -> &ObjectId { - unimplemented!() + &self.group_chunk_id } - pub fn dec_state_id(&self) -> ObjectId { - unimplemented!() + pub fn dec_state_id(&self) -> &Option { + &self.dec_state_id } async fn user_nonce(&self, user_id: &ObjectId) -> BuckyResult> { From 82d8af76cf3a534f75665690fe366225b617ea93 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 18 Jan 2023 17:11:12 +0800 Subject: [PATCH 040/553] push block in memory --- .../src/consensus/hotstuff/hotstuff.rs | 6 +- .../cyfs-group/src/storage/dec_storage.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 228 +++++++++++++++--- 3 files changed, 205 insertions(+), 31 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7b87e8752..8ae5ff496 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -311,7 +311,7 @@ impl HotstuffRunner { fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { if let Some(last_proposal) = block.proposals().last() { if &last_proposal.result_state != block.result_state_id() { - log::warn!("the result-state({}) in last-proposal is unmatch with block.result_state_id({})" + log::warn!("the result-state({:?}) in last-proposal is unmatch with block.result_state_id({:?})" , last_proposal.result_state, block.result_state_id()); return Err(BuckyError::new( BuckyErrorCode::Unmatch, @@ -330,7 +330,7 @@ impl HotstuffRunner { match prev_block.as_ref() { Some(prev_block) => { if block.result_state_id() != prev_block.result_state_id() { - log::warn!("block.result_state_id({}) is unmatch with prev_block.result_state_id({}) with no proposal." + log::warn!("block.result_state_id({:?}) is unmatch with prev_block.result_state_id({:?}) with no proposal." , block.result_state_id(), prev_block.result_state_id()); return Err(BuckyError::new( @@ -384,7 +384,7 @@ impl HotstuffRunner { prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "block verify failed by app, proposal: {}, prev_state: {}, expect-result: {}", + "block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", proposal_exe_info.proposal, prev_state_id, proposal_exe_info.result_state diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 48a7e43a3..12e3629d8 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -6,7 +6,7 @@ use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; #[derive(Clone)] pub struct DecStorageCache { - pub state: ObjectId, + pub state: Option, pub header_block: GroupConsensusBlock, pub qc_block: GroupConsensusBlock, } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 366f0d400..4695fd77f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,7 +1,9 @@ use std::collections::HashMap; -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupRPath}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; pub enum BlockLinkState { Expired, @@ -23,7 +25,6 @@ pub struct GroupStorage { dec_state_id: Option, // commited/header state id group_chunk_id: ObjectId, - height: u64, // commited/header height last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, @@ -89,35 +90,140 @@ impl GroupStorage { &self.dec_state_id } - async fn user_nonce(&self, user_id: &ObjectId) -> BuckyResult> { - unimplemented!() - } - - pub fn insert_rpath(rpath_obj: &GroupRPath) -> BuckyResult<()> { - unimplemented!() - } - pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { - unimplemented!() + let header_height = self.header_height(); + let block = match height.cmp(&header_height) { + std::cmp::Ordering::Less => { + if height == self.first_block.as_ref().map_or(0, |b| b.height()) { + self.first_block.clone() + } else { + // TODO find in storage + unimplemented!() + } + } + std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Greater => { + if height == header_height + 1 { + self.pre_commits + .iter() + .find(|(_, block)| block.height() == height) + .or(self + .prepares + .iter() + .find(|(_, block)| block.height() == height)) + .map(|(_, block)| block.clone()) + } else if height == header_height + 2 { + self.prepares + .iter() + .find(|(_, block)| block.height() == height) + .map(|(_, block)| block.clone()) + } else { + None + } + } + }; + + block.ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } pub async fn push_block( &mut self, block: GroupConsensusBlock, ) -> BuckyResult)>> { + let header_height = self.header_height(); + assert!(block.height() > header_height && block.height() <= header_height + 3); + + let block_id = block.named_object().desc().object_id(); + let prev_block_id = block.prev_block_id(); + + let mut remove_prepares = vec![]; + let mut new_pre_commit = None; + let mut new_header = None; + + // prepare update memory + if let Some(prev_block_id) = prev_block_id { + if let Some(prev_block) = self.prepares.get(prev_block_id) { + new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); + + if let Some(prev_prev_block_id) = prev_block.prev_block_id() { + if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + assert_eq!(block.height(), header_height + 3); + assert_eq!(prev_prev_block.height(), header_height + 1); + + new_header = Some(prev_prev_block.clone()); + let new_header_id = prev_prev_block.named_object().desc().object_id(); + + for (id, block) in self.prepares.iter() { + if block.prev_block_id().map(|prev_id| { + prev_id == &new_header_id || prev_id == prev_block_id + }) != Some(true) + { + remove_prepares.push(id.clone()); + } + } + } else { + assert_eq!(block.height(), header_height + 2); + } + } + } else { + assert_eq!(block.height(), header_height + 1); + } + } + /** * 1. 把block存入prepares * 2. 把block.qc.block从prepares存入pre-commits * 3. 把block.qc.block.qc.block从pre-commits存入链上 * 4. 把其他分叉block清理掉 - * 5. 追加去重proposal + * 5. 追加去重proposal, 注意翻页清理过期proposal * 6. 如果header有变更,返回新的header和被清理的分叉blocks */ - unimplemented!() + // TODO: storage + // unimplemented!() + + // update memory + if self.prepares.insert(block_id, block).is_some() { + assert!(false); + } + + match new_header { + Some(new_header) => { + self.dec_state_id = new_header.result_state_id().clone(); + self.header_block = Some(new_header); + let mut removed_blocks = + HashMap::from([new_pre_commit.expect("shoud got new pre-commit block")]); + + std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + let mut removed_blocks: Vec = + removed_blocks.into_values().collect(); + + for id in remove_prepares.iter() { + removed_blocks.push(self.prepares.remove(id).unwrap()); + } + + if self.first_block.is_none() { + self.first_block = self.header_block.clone(); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + } + None => { + if let Some(new_pre_commit) = new_pre_commit { + if self + .pre_commits + .insert(new_pre_commit.0, new_pre_commit.1) + .is_some() + { + assert!(false); + } + } + } + } + + Ok(None) } pub fn last_vote_round(&self) -> u64 { - unimplemented!() + self.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { @@ -125,7 +231,12 @@ impl GroupStorage { return Ok(()); } - unimplemented!() + // TODO: storage + unimplemented!(); + + self.last_vote_round = round; + + Ok(()) } pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { @@ -149,25 +260,88 @@ impl GroupStorage { Ok(linked_state) } - pub async fn find_block_in_cache( - &self, - block_id: &ObjectId, - ) -> BuckyResult { - unimplemented!() + pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { + if let Some(block) = self.header_block.as_ref() { + if &block.named_object().desc().object_id() == block_id { + return Ok(block.clone()); + } + } + + self.prepares + .get(block_id) + .or(self.pre_commits.get(block_id)) + .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + .map(|block| block.clone()) } - pub async fn find_block_in_cache_by_round( - &self, - round: u64, - ) -> BuckyResult { - unimplemented!() + pub fn find_block_in_cache_by_round(&self, round: u64) -> BuckyResult { + let header_round = self.header_round(); + + let found = match round.cmp(&header_round) { + std::cmp::Ordering::Less => { + return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + } + std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Greater => if round == header_round + 1 { + self.pre_commits + .iter() + .find(|(_, block)| block.round() == round) + .or(self + .prepares + .iter() + .find(|(_, block)| block.round() == round)) + } else { + self.prepares + .iter() + .find(|(_, block)| block.round() == round) + .or(self + .pre_commits + .iter() + .find(|(_, block)| block.round() == round)) + } + .map(|(_, block)| block), + }; + + found + .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + .map(|block| block.clone()) } pub async fn is_proposal_finished( &self, proposal_id: &ObjectId, - pre_block_id: &ObjectId, + prev_block_id: &ObjectId, ) -> BuckyResult { + let prev_block = self.find_block_in_cache(prev_block_id); + + // find in cache + if let Ok(prev_block) = prev_block.as_ref() { + match prev_block + .proposals() + .iter() + .find(|proposal| &proposal.proposal == proposal_id) + { + Some(_) => return Ok(true), + None => { + if let Some(prev_prev_block_id) = prev_block.prev_block_id() { + let prev_prev_block = self.find_block_in_cache(prev_prev_block_id); + if let Ok(prev_prev_block) = prev_prev_block.as_ref() { + if prev_prev_block + .proposals() + .iter() + .find(|proposal| &proposal.proposal == proposal_id) + .is_some() + { + return Ok(true); + } + } + } + } + } + } + + // TODO: find in storage + unimplemented!() } From 7dabcc8fb6ba0a574147e1e415f30e064e4f930d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 18 Jan 2023 18:55:01 +0800 Subject: [PATCH 041/553] verify the linked-block --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- src/component/cyfs-group/src/dec/rpath_mgr.rs | 5 +- .../cyfs-group/src/storage/group_storage.rs | 125 ++++++++++++++++-- 3 files changed, 120 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 8ae5ff496..73cdf366e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -570,7 +570,6 @@ impl HotstuffRunner { None => self .store .find_block_in_cache(&vote.block_id) - .await .map_or(None, |b| Some(b)), }; @@ -609,7 +608,7 @@ impl HotstuffRunner { } let block = match timeout.high_qc.as_ref() { - Some(qc) => match self.store.find_block_in_cache(&qc.block_id).await { + Some(qc) => match self.store.find_block_in_cache(&qc.block_id) { Ok(block) => Some(block), Err(_) => { self.vote_mgr.add_waiting_timeout(timeout.clone()); @@ -677,7 +676,6 @@ impl HotstuffRunner { let block = match self .store .find_block_in_cache_by_round(max_high_qc.high_qc_round) - .await { Ok(block) => block, Err(_) => { @@ -752,7 +750,7 @@ impl HotstuffRunner { let now = SystemTime::now(); let pre_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id).await?), + Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), None => None, }; let latest_group = self.committee.get_group(None).await?; @@ -939,7 +937,7 @@ impl HotstuffRunner { match pre_block.prev_block_id() { Some(pre_pre_block_id) => { let pre_pre_block = - match self.store.find_block_in_cache(pre_pre_block_id).await { + match self.store.find_block_in_cache(pre_pre_block_id) { Ok(pre_pre_block) => pre_pre_block, Err(_) => return false, }; diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 54530ad9b..e512f3d1d 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -357,7 +357,7 @@ impl GroupRPathMgr { let non_driver = local_info.non_driver.clone(); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath).await; + let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -403,7 +403,8 @@ impl GroupRPathMgr { IsCreateRPath::Yes(init_state) => init_state, _ => unreachable!(), }; - GroupStorage::create(group_id, dec_id, rpath, init_state).await? + GroupStorage::create(group_id, dec_id, rpath, init_state, non_driver.clone()) + .await? } }; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 4695fd77f..9525a503b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,10 +1,13 @@ -use std::collections::HashMap; +use std::{collections::HashMap, time::SystemTime}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, + bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, + ObjectDesc, ObjectId, }; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use crate::{network::NonDriver, TIME_PRECISION}; + pub enum BlockLinkState { Expired, DuplicateProposal, @@ -22,6 +25,7 @@ pub struct GroupStorage { group_id: ObjectId, dec_id: ObjectId, rpath: String, + non_driver: NonDriver, dec_state_id: Option, // commited/header state id group_chunk_id: ObjectId, @@ -38,6 +42,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, init_state_id: Option, + non_driver: NonDriver, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -48,6 +53,7 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, + non_driver: NonDriver, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -149,6 +155,13 @@ impl GroupStorage { if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); + assert_eq!( + prev_prev_block.prev_block_id(), + self.header_block + .as_ref() + .map(|b| b.named_object().desc().object_id()) + .as_ref() + ); new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.named_object().desc().object_id(); @@ -240,24 +253,114 @@ impl GroupStorage { } pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { - if block.height() <= self.header_height() { + let header_height = self.header_height(); + if block.height() <= header_height { return Ok(BlockLinkState::Expired); } - let linked_state = match block.height().cmp(&(self.header_height() + 3)) { - std::cmp::Ordering::Less => { - // 重复block,BlockLinkState::Duplicate - BlockLinkState::Link(None, HashMap::default()) - } - std::cmp::Ordering::Equal => BlockLinkState::Link(None, HashMap::default()), - std::cmp::Ordering::Greater => BlockLinkState::Pending, + if block.height() > header_height + 3 { + return Ok(BlockLinkState::Pending); }; // BlockLinkState::Link状态也可能因为缺少前序成为BlockLinkState::Pending // 去重proposal,BlockLinkState::DuplicateProposal,去重只检查相同分叉链上的proposal,不同分叉上允许有相同proposal // 检查Proposal时间戳,早于去重proposal集合区间,或者晚于当前系统时间戳一定时间 - Ok(linked_state) + let block_id = block.named_object().desc().object_id(); + + if self.find_block_in_cache(&block_id).is_ok() { + return Ok(BlockLinkState::Duplicate); + } + + let now = SystemTime::now(); + let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); + + if let Ok(duration) = block_time.duration_since(now) { + if duration > TIME_PRECISION { + return Err(BuckyError::new( + BuckyErrorCode::ErrorTimestamp, + "error timestamp", + )); + } + } + + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.find_block_in_cache(prev_block_id) { + Ok(prev_block) => { + if prev_block.height() + 1 != block.height() { + return Err(BuckyError::new(BuckyErrorCode::Failed, "height error")); + } else if prev_block.round() <= block.round() { + return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); + } else { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_time) { + if duration > TIME_PRECISION { + return Err(BuckyError::new( + BuckyErrorCode::ErrorTimestamp, + "error timestamp", + )); + } + } + Some(prev_block) + } + } + Err(_) => { + if block.height() == header_height + 1 { + return Ok(BlockLinkState::InvalidBranch); + } + return Ok(BlockLinkState::Pending); + } + }, + None => { + if block.height() != 1 { + return Err(BuckyError::new(BuckyErrorCode::Failed, "height error")); + } else if header_height != 0 { + return Ok(BlockLinkState::InvalidBranch); + } else { + None + } + } + }; + + let mut proposals = HashMap::new(); + for proposal_result in block.proposals().as_slice() { + if proposals.get(&proposal_result.proposal).is_some() { + return Ok(BlockLinkState::DuplicateProposal); + } + + if let Some(prev_block_id) = block.prev_block_id() { + if self + .is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await? + { + return Ok(BlockLinkState::DuplicateProposal); + } + } + + let proposal = self + .non_driver + .get_proposal(&proposal_result.proposal, Some(block.owner())) + .await?; + + let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); + if block_time + .duration_since(proposal_time) + .or(proposal_time.duration_since(block_time)) + .unwrap() + > TIME_PRECISION + { + return Err(BuckyError::new( + BuckyErrorCode::ErrorTimestamp, + "error timestamp", + )); + } + + proposals.insert(proposal_result.proposal, proposal); + } + + Ok(BlockLinkState::Link(prev_block, proposals)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From 58c2a73567faa6fcc573a98dbcd079d559006dc5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 30 Jan 2023 20:39:42 +0800 Subject: [PATCH 042/553] mock storage engine --- .../cyfs-group/src/statepath/design.md | 6 +- .../cyfs-group/src/storage/group_storage.rs | 75 +++++-- src/component/cyfs-group/src/storage/mod.rs | 2 + .../cyfs-group/src/storage/storage_engine.rs | 203 ++++++++++++++++++ 4 files changed, 270 insertions(+), 16 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/storage_engine.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 1cfd7483f..b73a46939 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -28,22 +28,20 @@ | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 | | -| |--range-->(${first_height}, ${header_seq}) // 保留的历史block序列号区间 +| |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height}) | | |--block-->GroupConsensusBlock -| | |--proposals-->Set | | | |--prepares // Prepare状态的block | | |--${block.id} | | |--block -| | |--result-state-->ObjectId(result-state) | |--pre-commits // pre-commit状态的block | | |--${block.id} | | |--block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 -| | |--recycle-->Set +| | |--over-->Set | | |--adding-->Set ``` diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 9525a503b..6b484601f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -4,10 +4,13 @@ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, }; +use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use crate::{network::NonDriver, TIME_PRECISION}; +use super::{storage_engine::StorageEngineMock, StorageEngine}; + pub enum BlockLinkState { Expired, DuplicateProposal, @@ -34,6 +37,8 @@ pub struct GroupStorage { first_block: Option, prepares: HashMap, pre_commits: HashMap, + + storage_engine: StorageEngineMock, } impl GroupStorage { @@ -44,9 +49,25 @@ impl GroupStorage { init_state_id: Option, non_driver: NonDriver, ) -> BuckyResult { - // 用hash加载chunk - // 从chunk解析group - unimplemented!() + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + dec_state_id: init_state_id, + group_chunk_id: group_chunk_id.object_id(), + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + storage_engine: StorageEngineMock::new(), + }) } pub async fn load( @@ -57,7 +78,9 @@ impl GroupStorage { ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - unimplemented!() + // unimplemented!() + + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } pub fn header_block(&self) -> &Option { @@ -103,8 +126,9 @@ impl GroupStorage { if height == self.first_block.as_ref().map_or(0, |b| b.height()) { self.first_block.clone() } else { - // TODO find in storage - unimplemented!() + // find in storage + let block_id = self.storage_engine.find_block_by_height(height).await?; + Some(self.non_driver.get_block(&block_id, None).await?) } } std::cmp::Ordering::Equal => self.header_block.clone(), @@ -191,8 +215,34 @@ impl GroupStorage { * 5. 追加去重proposal, 注意翻页清理过期proposal * 6. 如果header有变更,返回新的header和被清理的分叉blocks */ - // TODO: storage - // unimplemented!() + // storage + let mut writer = self.storage_engine.create_writer().await?; + writer.insert_prepares(&block_id).await?; + if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_pre_commit(new_pre_commit, new_header.is_some()) + .await?; + } + if let Some(new_header) = new_header.as_ref() { + writer + .push_commit( + new_header.height(), + &new_header.named_object().desc().object_id(), + ) + .await?; + + writer.remove_prepares(remove_prepares.as_slice()).await?; + + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + writer.push_proposals( + finish_proposals.as_slice(), + new_header.named_object().desc().create_time(), + ); + } // update memory if self.prepares.insert(block_id, block).is_some() { @@ -244,8 +294,9 @@ impl GroupStorage { return Ok(()); } - // TODO: storage - unimplemented!(); + // storage + let mut writer = self.storage_engine.create_writer().await?; + writer.set_last_vote_round(round).await?; self.last_vote_round = round; @@ -443,9 +494,9 @@ impl GroupStorage { } } - // TODO: find in storage + // find in storage - unimplemented!() + self.storage_engine.is_proposal_finished(proposal_id).await } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index 44de74436..d95cf7ddd 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,5 +1,7 @@ mod dec_storage; mod group_storage; +mod storage_engine; pub use dec_storage::*; pub use group_storage::*; +pub(crate) use storage_engine::*; diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/storage_engine.rs new file mode 100644 index 000000000..bf76f480e --- /dev/null +++ b/src/component/cyfs-group/src/storage/storage_engine.rs @@ -0,0 +1,203 @@ +use std::collections::{HashMap, HashSet}; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: u64, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + async fn create_writer(&mut self) -> BuckyResult>; + async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} + +struct StorageEngineMockFinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + +pub struct StorageEngineMock { + last_vote_round: u64, + + block_height_range: (u64, u64), + + commit_blocks: HashMap, + prepare_blocks: HashSet, + pre_commit_blocks: HashSet, + + finish_proposals: StorageEngineMockFinishProposalMgr, +} + +impl StorageEngineMock { + pub fn new() -> Self { + Self { + last_vote_round: 0, + block_height_range: (0, 0), + commit_blocks: HashMap::new(), + prepare_blocks: HashSet::new(), + pre_commit_blocks: HashSet::new(), + finish_proposals: StorageEngineMockFinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineMock { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + self.commit_blocks + .get(&height) + .map(|id| id.clone()) + .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + } + + async fn create_writer(&mut self) -> BuckyResult> { + Ok(Box::new(StorageEngineMockWriter { engine: self })) + } + + async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) + } +} + +struct StorageEngineMockWriter<'a> { + engine: &'a mut StorageEngineMock, +} + +#[async_trait::async_trait] +impl<'a> StorageWriter for StorageEngineMockWriter<'a> { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + if !self.engine.prepare_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block prepare twice", + )); + } + Ok(()) + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block should be prepared before pre-commit", + )); + } + + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if !self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: u64, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineMockWriter<'a> { + fn drop(&mut self) {} +} From c730bfd168dfc82ed543a09fdd9b48d1fedb6091 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 31 Jan 2023 11:37:46 +0800 Subject: [PATCH 043/553] compile --- src/component/cyfs-group/src/storage/group_storage.rs | 2 +- src/component/cyfs-group/src/storage/storage_engine.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 6b484601f..8e82add18 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -7,7 +7,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; -use crate::{network::NonDriver, TIME_PRECISION}; +use crate::{network::NonDriver, storage::StorageWriter, TIME_PRECISION}; use super::{storage_engine::StorageEngineMock, StorageEngine}; diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/storage_engine.rs index bf76f480e..55ea1aaae 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/storage_engine.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Drop { +pub trait StorageWriter: Send + Sync + Drop { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; @@ -21,7 +21,7 @@ pub trait StorageWriter: Drop { #[async_trait::async_trait] pub trait StorageEngine { async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult>; + async fn create_writer(&mut self) -> BuckyResult; async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; } @@ -69,8 +69,8 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult> { - Ok(Box::new(StorageEngineMockWriter { engine: self })) + async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) } async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { @@ -84,7 +84,7 @@ impl StorageEngine for StorageEngineMock { } } -struct StorageEngineMockWriter<'a> { +pub struct StorageEngineMockWriter<'a> { engine: &'a mut StorageEngineMock, } From 5b3de3c6c77c956172e5ce1785cb198eb35615d9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 31 Jan 2023 20:05:14 +0800 Subject: [PATCH 044/553] integration with cyfs-stack --- src/Cargo.lock | 1 + .../cyfs-group/examples/app_example.rs | 40 +++++---- .../src/consensus/hotstuff/hotstuff.rs | 6 +- .../src/consensus/vote/committee.rs | 6 +- .../cyfs-group/src/dec/rpath_client.rs | 6 +- .../cyfs-group/src/dec/rpath_control.rs | 4 +- src/component/cyfs-group/src/dec/rpath_mgr.rs | 44 +++++----- .../src/dec_state/dec_state_requestor.rs | 8 +- .../src/dec_state/dec_state_synchronizer.rs | 10 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/lib.rs | 2 +- src/component/cyfs-group/src/network/mod.rs | 4 +- .../cyfs-group/src/network/non_driver.rs | 85 +++++++++++++++--- .../cyfs-group/src/network/sender.rs | 6 +- .../cyfs-group/src/storage/group_storage.rs | 12 +-- src/component/cyfs-stack/Cargo.toml | 1 + .../cyfs-stack/src/stack/cyfs_stack.rs | 24 ++++- .../cyfs-stack/src/stack/group_non_driver.rs | 88 +++++++++++++++++++ src/component/cyfs-stack/src/stack/mod.rs | 2 + 19 files changed, 265 insertions(+), 92 deletions(-) create mode 100644 src/component/cyfs-stack/src/stack/group_non_driver.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index a8bda21b4..597993987 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2323,6 +2323,7 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", diff --git a/src/component/cyfs-group/examples/app_example.rs b/src/component/cyfs-group/examples/app_example.rs index 5dcbfeef4..5484d04e7 100644 --- a/src/component/cyfs-group/examples/app_example.rs +++ b/src/component/cyfs-group/examples/app_example.rs @@ -1,9 +1,9 @@ mod Client { + use cyfs_base::ObjectId; use cyfs_core::GroupProposal; + use cyfs_group::RPathClient; - pub struct DecClient { - - } + pub struct DecClient {} impl DecClient { async fn do_something(&self) { @@ -24,8 +24,8 @@ mod Client { mod GroupDecService { use cyfs_base::*; - use cyfs_core::GroupProposal; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathControlMgr}; + use cyfs_core::{DecAppId, GroupConsensusBlock, GroupProposal}; + use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; pub struct DecService {} @@ -43,9 +43,8 @@ mod GroupDecService { pub fn is_accept( &self, group: &Group, - dec_id: &ObjectId, rpath: &str, - with_proposal: Option<&GroupProposal>, + with_block: Option<&GroupConsensusBlock>, ) -> bool { // 由应用定义是否接收该rpath,并启动共识过程,参与该rpath的信息维护 true @@ -57,17 +56,26 @@ mod GroupDecService { async fn create_rpath_delegate( &self, group: &Group, - dec_id: &ObjectId, rpath: &str, - with_proposal: Option<&GroupProposal>, + with_block: Option<&GroupConsensusBlock>, ) -> BuckyResult> { - if self.is_accept(group, dec_id, rpath, with_proposal) { + if self.is_accept(group, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(MyRPathDelegate::new()) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } + + async fn on_state_changed( + &self, + group_id: &ObjectId, + rpath: &str, + state_id: Option, + pre_state_id: Option, + ) { + unimplemented!() + } } pub struct MyRPathDelegate {} @@ -91,7 +99,7 @@ mod GroupDecService { ObjectId::default() }; - let return_object = { + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? */ @@ -109,9 +117,9 @@ mod GroupDecService { * (result_state_id, return_object) = pre_state_id + proposal + context */ Ok(ExecuteResult { - result_state_id, - return_object, context, + result_state_id: Some(result_state_id), + receipt, }) } @@ -124,7 +132,7 @@ mod GroupDecService { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context - */ + */ Ok(true) } } @@ -154,9 +162,7 @@ mod GroupDecService { pre_state_id: ObjectId, execute_result: &ExecuteResult, ) { - /** - * 提交到共识链上了,可能有些善后事宜 - */ + // 提交到共识链上了,可能有些善后事宜 } } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 73cdf366e..7fb0d1425 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -39,7 +39,7 @@ impl Hotstuff { store: GroupStorage, signer: Arc, network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, delegate: Arc>, rpath: GroupRPath, @@ -134,7 +134,7 @@ struct HotstuffRunner { timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, @@ -154,7 +154,7 @@ impl HotstuffRunner { store: GroupStorage, signer: Arc, network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 135256d7a..4a783338b 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -12,17 +12,17 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use crate::{network::NonDriver, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { group_id: ObjectId, - non_driver: NonDriver, + non_driver: NONDriverHelper, group_cache: Arc>>, // (group_chunk_id, group) } impl Committee { - pub fn new(group_id: ObjectId, non_driver: NonDriver) -> Self { + pub fn new(group_id: ObjectId, non_driver: NONDriverHelper) -> Self { Committee { group_id, non_driver, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 859461842..9f1d08579 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -17,7 +17,7 @@ use crate::{ struct RPathClientRaw { rpath: GroupRPath, local_id: ObjectId, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, state_requestor: DecStateRequestor, @@ -27,10 +27,10 @@ struct RPathClientRaw { pub struct RPathClient(Arc); impl RPathClient { - pub async fn load( + pub(crate) async fn load( local_id: ObjectId, rpath: GroupRPath, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { let dec_store = DecStorage::load().await?; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 55e844f5a..cc1436555 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -4,7 +4,7 @@ use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use crate::{ - network::NonDriver, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, + network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, PendingProposalHandler, PendingProposalMgr, RPathDelegate, }; @@ -27,7 +27,7 @@ impl RPathControl { signer: Arc, delegate: Arc>, network_sender: crate::network::Sender, - non_driver: NonDriver, + non_driver: NONDriverHelper, store: GroupStorage, ) -> BuckyResult { let (pending_proposal_handle, pending_proposal_consumer) = PendingProposalMgr::new(); diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index e512f3d1d..176fe60d4 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -1,13 +1,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, RsaCPUObjectSigner}; -use cyfs_bdt::Stack; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, +}; +use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - RPathClient, RPathControl, NET_PROTOCOL_VPORT, + NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -25,11 +27,10 @@ struct GroupRPathMgrRaw { } struct LocalInfo { - local_id: ObjectId, signer: Arc, - network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, - bdt_stack: Stack, + non_driver: Arc>, + datagram: DatagramTunnelGuard, + bdt_stack: StackGuard, } #[derive(Clone)] @@ -37,19 +38,16 @@ pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); impl GroupRPathMgr { pub fn new( - local_id: ObjectId, signer: RsaCPUObjectSigner, - non_driver: crate::network::NonDriver, - bdt_stack: Stack, + non_driver: Box, + bdt_stack: StackGuard, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; - let network_sender = crate::network::Sender::new(datagram.clone(), non_driver.clone()); let local_info = LocalInfo { - local_id, signer: Arc::new(signer), - network_sender, - non_driver, + non_driver: Arc::new(non_driver), + datagram: datagram.clone(), bdt_stack, }; @@ -118,9 +116,10 @@ impl GroupRPathMgr { // write let local_info = self.local_info(); - let local_id = local_info.local_id; - let network_sender = local_info.network_sender.clone(); - let non_driver = local_info.non_driver.clone(); + let local_id = local_info.bdt_stack.local_const().owner().unwrap(); + let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let network_sender = + crate::network::Sender::new(local_info.datagram.clone(), non_driver.clone()); let mut raw = self.write().await; @@ -351,10 +350,11 @@ impl GroupRPathMgr { // write let local_info = self.local_info(); - let local_id = local_info.local_id; + let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let signer = local_info.signer.clone(); - let network_sender = local_info.network_sender.clone(); - let non_driver = local_info.non_driver.clone(); + let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let network_sender = + crate::network::Sender::new(local_info.datagram.clone(), non_driver.clone()); let local_device_id = local_info.bdt_stack.local_device_id().clone(); let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; @@ -373,9 +373,7 @@ impl GroupRPathMgr { }; // TODO: query group - let group = self - .local_info() - .non_driver + let group = non_driver .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) .await?; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 13951dddc..e30c0a5a7 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -25,11 +25,11 @@ struct DecStateRequestorRaw { pub struct DecStateRequestor(Arc); impl DecStateRequestor { - pub fn new( + pub(crate) fn new( local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -92,7 +92,7 @@ struct DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, query_state_notifier: CallReplyNotifier>, } @@ -106,7 +106,7 @@ impl DecStateRequestorRunner { )>, store: DecStorage, network_sender: crate::network::Sender, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, query_state_notifier: CallReplyNotifier>, ) -> Self { Self { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index ffbd2838f..8b32422c3 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -11,7 +11,7 @@ use futures::FutureExt; use crate::{ helper::{verify_block, Timer}, - network::NonDriver, + network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, CHANNEL_CAPACITY, }; @@ -41,10 +41,10 @@ struct DecStateSynchronizerRaw { pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { - pub fn new( + pub(crate) fn new( local_id: ObjectId, rpath: GroupRPath, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -136,7 +136,7 @@ struct DecStateSynchronizerRunner { state_cache: Option, update_notifies: Option, - non_driver: NonDriver, + non_driver: NONDriverHelper, proposal_result_notifier: CallReplyNotifier>>, } @@ -153,7 +153,7 @@ impl DecStateSynchronizerRunner { ObjectId, )>, store: DecStorage, - non_driver: NonDriver, + non_driver: NONDriverHelper, proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b3adbd9b4..01e8d0640 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -25,11 +25,11 @@ pub struct StatePusher { } impl StatePusher { - pub fn new( + pub(crate) fn new( local_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -98,7 +98,7 @@ struct StateChanggeRunner { local_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, tx_notifier: async_std::channel::Sender, rx_notifier: async_std::channel::Receiver, delay_notify_times: usize, @@ -112,7 +112,7 @@ impl StateChanggeRunner { local_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, - non_driver: crate::network::NonDriver, + non_driver: crate::network::NONDriverHelper, tx_notifier: async_std::channel::Sender, rx_notifier: async_std::channel::Receiver, ) -> Self { diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index 85b39d9c9..fefe3f808 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -16,7 +16,7 @@ pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; -pub(crate) use network::*; +pub use network::*; pub use objects::*; pub use statepath::*; pub(crate) use storage::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index 468f26086..f79e67dd4 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -2,6 +2,6 @@ mod listener; mod non_driver; mod sender; -pub use listener::*; +pub(crate) use listener::*; pub use non_driver::*; -pub use sender::*; +pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index c62446d5d..e84d95c5a 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,13 +1,39 @@ -use cyfs_base::{BuckyResult, Device, DeviceId, Group, ObjectId, PeopleId, RawDecode}; +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, ObjectDesc, + ObjectId, ObjectTypeCode, People, PeopleId, RawDecode, +}; +use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; +#[async_trait::async_trait] +pub trait NONDriver: Send + Sync { + async fn get_object( + &self, + dec_id: &ObjectId, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult; + + async fn post_object( + &self, + dec_id: &ObjectId, + obj: NONObjectInfo, + to: &ObjectId, + ) -> BuckyResult<()>; +} + #[derive(Clone)] -pub struct NonDriver {} +pub(crate) struct NONDriverHelper { + driver: Arc>, + dec_id: ObjectId, +} -impl NonDriver { - pub fn new() -> Self { - Self {} +impl NONDriverHelper { + pub fn new(driver: Arc>, dec_id: ObjectId) -> Self { + Self { driver, dec_id } } pub async fn get_object( @@ -15,15 +41,15 @@ impl NonDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { - unimplemented!() + self.driver.get_object(&self.dec_id, object_id, from).await } pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { - unimplemented!() + self.driver.post_object(&self.dec_id, obj, to).await } - pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) -> BuckyResult<()> { - unimplemented!() + pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; } pub async fn get_block( @@ -54,14 +80,49 @@ impl NonDriver { group_chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { - unimplemented!() + match group_chunk_id { + Some(group_chunk_id) => { + let chunk = self.get_object(group_chunk_id, from).await?; + let (group_chunk, remain) = ChunkMeta::raw_decode(chunk.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + let group = Group::try_from(&group_chunk)?; + if &group.desc().object_id() == group_id { + Ok(group) + } else { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "groupid")) + } + } + None => { + // TODO: latest version from metachain + let group = self.get_object(group_id, from).await?; + let (group, remain) = Group::raw_decode(group.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(group) + } + } } pub async fn get_ood(&self, people_id: &PeopleId) -> BuckyResult { - unimplemented!() + let people = self + .get_object(people_id.object_id(), Some(people_id.object_id())) + .await?; + let (people, remain) = People::raw_decode(people.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + people + .ood_list() + .get(0) + .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "empty ood-list")) + .map(|d| d.clone()) } pub async fn get_device(&self, device_id: &ObjectId) -> BuckyResult { - unimplemented!() + if let ObjectTypeCode::Device = device_id.obj_type_code() { + let device = self.get_object(device_id, Some(device_id)).await?; + let (device, remain) = Device::raw_decode(device.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(device) + } else { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "not device-id")) + } } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index c087aa456..42887da8b 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -4,17 +4,17 @@ use cyfs_core::GroupRPath; use crate::{HotstuffMessage, HotstuffPackage}; -use super::NonDriver; +use super::NONDriverHelper; #[derive(Clone)] pub struct Sender { datagram: DatagramTunnelGuard, vport: u16, - non_driver: NonDriver, + non_driver: NONDriverHelper, } impl Sender { - pub fn new(datagram: DatagramTunnelGuard, non_driver: NonDriver) -> Self { + pub(crate) fn new(datagram: DatagramTunnelGuard, non_driver: NONDriverHelper) -> Self { let vport = datagram.vport(); Self { datagram, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 8e82add18..0e4ecb2a3 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -7,7 +7,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; -use crate::{network::NonDriver, storage::StorageWriter, TIME_PRECISION}; +use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; use super::{storage_engine::StorageEngineMock, StorageEngine}; @@ -28,7 +28,7 @@ pub struct GroupStorage { group_id: ObjectId, dec_id: ObjectId, rpath: String, - non_driver: NonDriver, + non_driver: NONDriverHelper, dec_state_id: Option, // commited/header state id group_chunk_id: ObjectId, @@ -42,12 +42,12 @@ pub struct GroupStorage { } impl GroupStorage { - pub async fn create( + pub(crate) async fn create( group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, init_state_id: Option, - non_driver: NonDriver, + non_driver: NONDriverHelper, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); @@ -70,11 +70,11 @@ impl GroupStorage { }) } - pub async fn load( + pub(crate) async fn load( group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - non_driver: NonDriver, + non_driver: NONDriverHelper, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index e1f13933e..362de7d9c 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -24,6 +24,7 @@ cyfs-task-manager = { path = "../../component/cyfs-task-manager" } cyfs-chunk-cache = { path = "../../component/cyfs-chunk-cache" } cyfs-util = { path = "../cyfs-util" } cyfs-meta-lib = { path = "../cyfs-meta-lib" } +cyfs-group = { path = "../../component/cyfs-group" } #dsg-client = {path = "../dsg/dsg-client"} log = "0.4" serde = "1.0" diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 36c1b1d47..520139032 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -32,9 +32,11 @@ use crate::trans_api::{create_trans_store, TransService}; use crate::util::UtilOutputTransformer; use crate::util_api::UtilService; use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; +use crate::GroupNONDriver; use cyfs_base::*; use cyfs_bdt::{ChunkReader, DeviceCache, Stack, StackGuard, StackOpenParams}; use cyfs_chunk_cache::{ChunkManager, ChunkManagerRef}; +use cyfs_group::GroupRPathMgr; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -42,7 +44,6 @@ use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; use once_cell::sync::OnceCell; use std::sync::Arc; - #[derive(Clone)] pub(crate) struct ObjectServices { pub ndn_service: Arc, @@ -99,6 +100,9 @@ pub struct CyfsStackImpl { // global_state_meta global_state_meta: GlobalStateMetaService, + + // group + group_manager: GroupRPathMgr, } impl CyfsStackImpl { @@ -249,6 +253,11 @@ impl CyfsStackImpl { config.clone(), ); + let signer = RsaCPUObjectSigner::new( + bdt_param.device.desc().public_key().clone(), + bdt_param.secret.clone(), + ); + // 初始化bdt协议栈 let (bdt_stack, bdt_event) = Self::init_bdt_stack( zone_manager.clone(), @@ -380,7 +389,7 @@ impl CyfsStackImpl { let services = ObjectServices { ndn_service, - non_service, + non_service: non_service.clone(), crypto_service, util_service, @@ -396,6 +405,12 @@ impl CyfsStackImpl { config.clone(), ); + let group_manager = GroupRPathMgr::new( + signer, + Box::new(GroupNONDriver::new(non_service.clone())), + bdt_stack.clone(), + )?; + let mut stack = Self { config, @@ -431,6 +446,8 @@ impl CyfsStackImpl { fail_handler, acl_manager, + + group_manager, }; // init an system-dec router-handler processor for later use @@ -813,7 +830,6 @@ impl CyfsStackImpl { let task = async_std::task::spawn(async move { // 初始化known_objects for object in known_objects.list.into_iter() { - let req = NamedObjectCachePutObjectRequest { source: RequestSourceInfo::new_local_system(), object, @@ -829,7 +845,7 @@ impl CyfsStackImpl { if known_objects.mode == CyfsStackKnownObjectsInitMode::Sync { task.await; } - + Ok(noc) } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs new file mode 100644 index 000000000..95223c08d --- /dev/null +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -0,0 +1,88 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectTypeCode}; +use cyfs_lib::{ + DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, + NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, RequestProtocol, + RequestSourceInfo, +}; + +use crate::{non::NONInputProcessor, non_api::NONService}; + +pub struct GroupNONDriver { + non_service: Arc, +} + +impl GroupNONDriver { + pub fn new(non_service: Arc) -> Self { + Self { non_service } + } +} + +#[async_trait::async_trait] +impl cyfs_group::NONDriver for GroupNONDriver { + async fn get_object( + &self, + dec_id: &ObjectId, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + self.non_service + .get_object(NONGetObjectInputRequest { + common: NONInputRequestCommon { + req_path: None, + source: RequestSourceInfo { + protocol: RequestProtocol::DataBdt, + zone: DeviceZoneInfo { + device: None, + zone: None, + zone_category: DeviceZoneCategory::CurrentZone, + }, + dec: dec_id.clone(), + verified: None, + }, + + level: NONAPILevel::Router, + + target: from.map(|remote| remote.clone()), + flags: 0, + }, + object_id: object_id.clone(), + inner_path: None, + }) + .await + .map(|resp| resp.object) + } + + async fn post_object( + &self, + dec_id: &ObjectId, + obj: NONObjectInfo, + to: &ObjectId, + ) -> BuckyResult<()> { + self.non_service + .post_object(NONPostObjectInputRequest { + common: NONInputRequestCommon { + req_path: None, + source: RequestSourceInfo { + protocol: RequestProtocol::DataBdt, + zone: DeviceZoneInfo { + device: None, + zone: None, + zone_category: DeviceZoneCategory::CurrentZone, + }, + dec: dec_id.clone(), + verified: None, + }, + + level: NONAPILevel::Router, + + target: Some(to.clone()), + flags: 0, + }, + object: obj, + }) + .await + .map(|_| ()) + } +} diff --git a/src/component/cyfs-stack/src/stack/mod.rs b/src/component/cyfs-stack/src/stack/mod.rs index 21a67f403..971066bcc 100644 --- a/src/component/cyfs-stack/src/stack/mod.rs +++ b/src/component/cyfs-stack/src/stack/mod.rs @@ -1,6 +1,8 @@ mod cyfs_stack; +mod group_non_driver; mod params; mod uni_stack; pub use cyfs_stack::*; +pub(crate) use group_non_driver::*; pub use params::*; From bc31c4d5905afefc2eebc3469f6b44f7306dd702 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Feb 2023 20:26:13 +0800 Subject: [PATCH 045/553] test example --- src/Cargo.lock | 29 +- src/Cargo.toml | 1 + src/component/cyfs-group/Cargo.toml | 2 +- .../cyfs-group/examples/app_example.rs | 33 +- .../src/consensus/hotstuff/hotstuff.rs | 38 ++ .../cyfs-group/src/dec/delegate_factory.rs | 1 + .../cyfs-stack/src/stack/cyfs_stack.rs | 4 + src/tests/group-example/Cargo.toml | 29 + src/tests/group-example/src/main.rs | 513 ++++++++++++++++++ 9 files changed, 637 insertions(+), 13 deletions(-) create mode 100644 src/tests/group-example/Cargo.toml create mode 100644 src/tests/group-example/src/main.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 597993987..8a95160f9 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1946,7 +1946,7 @@ dependencies = [ [[package]] name = "cyfs-group" -version = "0.0.1" +version = "0.1.1" dependencies = [ "async-recursion", "async-std", @@ -3478,6 +3478,33 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.5", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.15" diff --git a/src/Cargo.toml b/src/Cargo.toml index c77bfc6e3..d1fa7fc4e 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -67,6 +67,7 @@ members = [ "./tests/cyfs-stack-test", "./tests/cyfs-bench-mark", "./tests/cyfs-stack-bench", + "./tests/group-example", ] [profile.release] diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index b22452ce8..82d58c3a1 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-group' -version = '0.0.1' +version = '0.1.1' authors = ['zhangzhen '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-group/examples/app_example.rs b/src/component/cyfs-group/examples/app_example.rs index 5484d04e7..aff70c6d6 100644 --- a/src/component/cyfs-group/examples/app_example.rs +++ b/src/component/cyfs-group/examples/app_example.rs @@ -6,8 +6,10 @@ mod Client { pub struct DecClient {} impl DecClient { - async fn do_something(&self) { - let rpath_client = RPathClient::new(); + async fn do_something(&self, stack: &CyfsStack) { + let rpath_mgr = stack.group_mgr(); + + let rpath_client = rpath_mgr.rpath_client(); let field_path = "/xxx/yyy"; let old_value = rpath_client.get_field(field_path).await; @@ -30,10 +32,13 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run() { - let rpath_mgr = RPathControlMgr::new(DecAppId::default()); + pub async fn run(stack: &CyfsStack) { + let rpath_mgr = stack.group_mgr(); + + let appid = DecAppId::default(); + let delegate_factory = GroupRPathDelegateFactory {}; - rpath_mgr.register(delegate_factory) + rpath_mgr.register(appid, delegate_factory) } } @@ -61,7 +66,7 @@ mod GroupDecService { ) -> BuckyResult> { if self.is_accept(group, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 - Ok(MyRPathDelegate::new()) + Ok(Box::new(MyRPathDelegate::new())) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } @@ -90,7 +95,7 @@ mod GroupDecService { pub fn execute( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, ) -> BuckyResult { let result_state_id = { /** @@ -126,7 +131,7 @@ mod GroupDecService { pub fn verify( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult { /** @@ -142,7 +147,7 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, ) -> BuckyResult { self.execute(proposal, pre_state_id) } @@ -150,7 +155,7 @@ mod GroupDecService { async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult { self.verify(proposal, pre_state_id, execute_result) @@ -159,10 +164,16 @@ mod GroupDecService { async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: ObjectId, + pre_state_id: Option, execute_result: &ExecuteResult, ) { // 提交到共识链上了,可能有些善后事宜 + unimplemented!() + } + + async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { + // 自定义同步Group版本策略 + unimplemented!() } } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7fb0d1425..16ae05086 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -428,6 +428,44 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); + let pre_state_id = match header_block.prev_block_id() { + Some(block_id) => self + .non_driver + .get_block(block_id, None) + .await? + .result_state_id() + .clone(), + None => None, + }; + + for proposal in header_block.proposals() { + let proposal_obj = self + .non_driver + .get_proposal(&proposal.proposal, None) + .await?; + let receipt = match proposal.receipt.as_ref() { + Some(receipt) => { + let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice())?; + assert_eq!(remain.len(), 0); + Some(receipt) + } + None => None, + }; + + self.delegate + .on_commited( + &proposal_obj, + pre_state_id, + &ExecuteResult { + result_state_id: header_block.result_state_id().clone(), + receipt, + context: proposal.context.clone(), + }, + &header_block, + ) + .await; + } + self.state_pusher .notify_block_commit(header_block, qc_block.clone()) .await diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 289bfc6f7..bdcb98f60 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -48,5 +48,6 @@ pub trait RPathDelegate: Sync + Send { proposal: &GroupProposal, pre_state_id: Option, execute_result: &ExecuteResult, + block: &GroupConsensusBlock, ); } diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 520139032..eca911380 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -1152,6 +1152,10 @@ impl CyfsStack { &self.stack.root_state } + pub fn group_mgr(&self) -> &GroupRPathMgr { + &self.stack.group_manager + } + // use system dec as default dec pub async fn root_state_stub( &self, diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml new file mode 100644 index 000000000..a2eddc0c8 --- /dev/null +++ b/src/tests/group-example/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "group-example" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +cyfs-base = { path = '../../component/cyfs-base'} +cyfs-core = { path = '../../component/cyfs-core' } +cyfs-bdt = { path = '../../component/cyfs-bdt' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group = { path = '../../component/cyfs-group' } +cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs new file mode 100644 index 000000000..0d8f62351 --- /dev/null +++ b/src/tests/group-example/src/main.rs @@ -0,0 +1,513 @@ +use std::{clone, time::Duration}; + +use cyfs_base::{NamedObject, ObjectDesc, ObjectId}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_group::IsCreateRPath; +use Common::{ + create_stack, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, + EXAMPLE_RPATH, +}; +use GroupDecService::DecService; + +mod Common { + use std::sync::Arc; + + use cyfs_base::{ + AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, Group, GroupMember, + NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawFrom, + StandardObject, TypelessCoreObject, UniqueId, + }; + use cyfs_core::{DecApp, DecAppId, DecAppObj}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_meta_lib::MetaMinerTarget; + use cyfs_stack::{ + BdtStackParams, CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, + CyfsStackInterfaceParams, CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, + CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, + }; + use rand::Rng; + + lazy_static::lazy_static! { + pub static ref EXAMPLE_ADMINS: Vec<(People, PrivateKey, Device)> = create_members("admin", 4); + pub static ref EXAMPLE_MEMBERS: Vec<(People, PrivateKey, Device)> = create_members("member", 9); + + pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0, EXAMPLE_ADMINS.iter().map(|m| &m.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.2).collect()); + pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); + pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + } + + fn create_members(name_prefix: &str, count: usize) -> Vec<(People, PrivateKey, Device)> { + let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); + let mut members = vec![]; + + for i in 0..count { + let name = format!("{}-{}", name_prefix, i); + let private_key = PrivateKey::generate_secp256k1().unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint.mut_addr().set_port(port_begin + i as u16); + endpoint.set_static_wan(true); + + let device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + members.push((owner, private_key, device)); + } + + members + } + + fn create_group( + founder: &People, + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + let mut group = Group::new_org(founder.desc().object_id(), Area::default()).build(); + group.check_org_body_content_mut().set_admins( + admins + .iter() + .map(|m| GroupMember::from_member_id(m.desc().object_id())) + .collect(), + ); + group.set_members( + members + .iter() + .map(|m| GroupMember::from_member_id(m.desc().object_id())) + .collect(), + ); + group.set_ood_list( + oods.iter() + .map(|d| DeviceId::try_from(d.desc().object_id()).unwrap()) + .collect(), + ); + group + } + + pub async fn create_stack( + people: People, + private_key: PrivateKey, + device: Device, + ) -> CyfsStack { + let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.2.clone()).collect(); + let mut member_device: Vec = EXAMPLE_MEMBERS.iter().map(|m| m.2.clone()).collect(); + let known_device = vec![admin_device, member_device].concat(); + + let bdt_param = BdtStackParams { + device, + tcp_port_mapping: vec![], + secret: private_key, + known_sn: vec![], + known_device, + known_passive_pn: vec![], + udp_sn_only: None, + }; + + let stack_param = CyfsStackParams { + config: CyfsStackConfigParams { + isolate: None, + sync_service: false, + shared_stack: false, + }, + noc: CyfsStackNOCParams {}, + interface: CyfsStackInterfaceParams { + bdt_listeners: vec![], + tcp_listeners: vec![], + ws_listener: None, + }, + meta: CyfsStackMetaParams { + target: MetaMinerTarget::Dev, + }, + front: CyfsStackFrontParams { + enable: false, + browser_mode: BrowserSanboxMode::None, + }, + }; + + let mut known_objects = CyfsStackKnownObjects { + list: vec![], + mode: CyfsStackKnownObjectsInitMode::Sync, + }; + + for (member, _, device) in EXAMPLE_ADMINS.iter() { + known_objects.list.push(NONObjectInfo::new( + member.desc().object_id(), + member.to_vec().unwrap(), + Some(Arc::new(AnyNamedObject::Standard(StandardObject::People( + member.clone(), + )))), + )); + + known_objects.list.push(NONObjectInfo::new( + member.desc().object_id(), + member.to_vec().unwrap(), + Some(Arc::new(AnyNamedObject::Standard(StandardObject::Device( + device.clone(), + )))), + )); + } + + for (member, _, device) in EXAMPLE_MEMBERS.iter() { + known_objects.list.push(NONObjectInfo::new( + member.desc().object_id(), + member.to_vec().unwrap(), + Some(Arc::new(AnyNamedObject::Standard(StandardObject::People( + member.clone(), + )))), + )); + + known_objects.list.push(NONObjectInfo::new( + member.desc().object_id(), + member.to_vec().unwrap(), + Some(Arc::new(AnyNamedObject::Standard(StandardObject::Device( + device.clone(), + )))), + )); + } + + known_objects.list.push(NONObjectInfo::new( + EXAMPLE_GROUP.desc().object_id(), + EXAMPLE_GROUP.to_vec().unwrap(), + Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( + EXAMPLE_GROUP.clone(), + )))), + )); + + let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); + known_objects.list.push(NONObjectInfo::new( + EXAMPLE_DEC_APP.desc().object_id(), + dec_app_vec, + Some(Arc::new(AnyNamedObject::Core(typeless))), + )); + + CyfsStack::open(bdt_param, stack_param, known_objects) + .await + .unwrap() + } +} + +mod Client { + // use cyfs_base::ObjectId; + // use cyfs_core::GroupProposal; + // use cyfs_group::RPathClient; + + // pub struct DecClient {} + + // impl DecClient { + // async fn do_something(&self) { + // let rpath_client = RPathClient::new(); + + // let field_path = "/xxx/yyy"; + // let old_value = rpath_client.get_field(field_path).await; + // let param = ObjectId::default(); // param = old_value.value + // let proposal = self.make_proposal(param); + // rpath_client.post_proposal(proposal).await; + // } + + // fn make_proposal(&self, param: ObjectId) -> GroupProposal { + // unimplemented!() + // } + // } +} + +mod GroupDecService { + use cyfs_base::*; + use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + }; + use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_stack::CyfsStack; + + use crate::Common::EXAMPLE_DEC_APP_ID; + + pub struct DecService {} + + impl DecService { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + let group_mgr = cyfs_stack.group_mgr(); + + group_mgr + .register( + EXAMPLE_DEC_APP_ID.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + ) + .await + .unwrap() + } + } + + pub struct GroupRPathDelegateFactory { + local_name: String, + } + + impl GroupRPathDelegateFactory { + pub fn is_accept( + &self, + group: &Group, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> bool { + // 由应用定义是否接收该rpath,并启动共识过程,参与该rpath的信息维护 + true + } + } + + #[async_trait::async_trait] + impl DelegateFactory for GroupRPathDelegateFactory { + async fn create_rpath_delegate( + &self, + group: &Group, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult> { + if self.is_accept(group, rpath, with_block) { + // 如果接受,就提供该rpath的处理响应对象 + Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "")) + } + } + + async fn on_state_changed( + &self, + group_id: &ObjectId, + rpath: &str, + state_id: Option, + pre_state_id: Option, + ) { + unimplemented!() + } + } + + pub struct MyRPathDelegate { + local_name: String, + } + + impl MyRPathDelegate { + pub fn new(local_name: String) -> Self { + MyRPathDelegate { local_name } + } + } + + impl MyRPathDelegate { + pub fn execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + let result_state_id = { + /** + * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + */ + let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let buf = pre_state_id.get_slice_value(); + let mut pre_value = [0u8; 8]; + pre_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(pre_value) + }); + + let delta_buf = proposal.params().as_ref().unwrap().as_slice(); + let mut delta = [0u8; 8]; + delta.copy_from_slice(delta_buf); + let delta = u64::from_be_bytes(delta); + + let value = pre_value + delta; + ObjectId::from_slice_value(&value.to_be_bytes()) + }; + + let receipt = { + /** + * 返回给Client的对象,相当于这个请求的结果或者叫回执? + */ + None + }; + + let context = { + /** + * 执行请求的上下文,运算过程中可能有验证节点无法得到的上下文信息(比如时间戳,随机数) + */ + None + }; + + /** + * (result_state_id, return_object) = pre_state_id + proposal + context + */ + Ok(ExecuteResult { + context, + result_state_id: Some(result_state_id), + receipt, + }) + } + + pub fn verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult { + /** + * let is_same = (execute_result.result_state_id, execute_result.return_object) + * == pre_state_id + proposal + execute_result.context + */ + let result = self.execute(proposal, pre_state_id)?; + + let is_ok = execute_result.result_state_id == result.result_state_id + && execute_result.context.is_none() + && execute_result.receipt.is_none(); + + Ok(is_ok) + } + } + + #[async_trait::async_trait] + impl RPathDelegate for MyRPathDelegate { + async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + self.execute(proposal, pre_state_id) + } + + async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult { + self.verify(proposal, pre_state_id, execute_result) + } + + async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + // 提交到共识链上了,可能有些善后事宜 + + let delta_buf = proposal.params().as_ref().unwrap().as_slice(); + let mut delta = [0u8; 8]; + delta.copy_from_slice(delta_buf); + let delta = u64::from_be_bytes(delta); + + let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let buf = pre_state_id.get_slice_value(); + let mut pre_value = [0u8; 8]; + pre_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(pre_value) + }); + + let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let buf = result_id.get_slice_value(); + let mut result_value = [0u8; 8]; + result_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(result_value) + }); + + log::info!( + "proposal commited: height: {}, delta: {}, result: {} -> {}, local: {}", + block.height(), + delta, + pre_value, + result_value, + self.local_name + ); + } + + async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { + unimplemented!() + } + } +} + +fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { + GroupProposal::create( + GroupRPath::new( + EXAMPLE_GROUP.desc().object_id(), + EXAMPLE_DEC_APP_ID.object_id().clone(), + EXAMPLE_RPATH.clone(), + ), + "add".to_string(), + Some(Vec::from(delta.to_be_bytes())), + None, + None, + owner, + None, + None, + None, + ) + .build() +} + +async fn main_run() { + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) + .level("debug") + .console("debug") + .enable_bdt(Some("debug"), Some("debug")) + .build() + .unwrap() + .start(); + + cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) + .exit_on_panic(true) + .build() + .start(); + + cyfs_debug::ProcessDeadHelper::instance().enable_exit_on_task_system_dead(None); + + let mut admin_stacks = vec![]; + for (admin, private_key, device) in EXAMPLE_ADMINS.iter() { + let cyfs_stack = create_stack(admin.clone(), private_key.clone(), device.clone()).await; + DecService::run(&cyfs_stack, admin.name().unwrap().to_string()).await; + admin_stacks.push(cyfs_stack); + } + + for i in 1..100000000 { + let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0; + let proposal = create_proposal(i as u64, owner.desc().object_id()); + + let control = stack + .group_mgr() + .find_rpath_control( + &EXAMPLE_GROUP.desc().object_id(), + EXAMPLE_DEC_APP_ID.object_id(), + &EXAMPLE_RPATH, + IsCreateRPath::Yes(None), + ) + .await + .unwrap(); + + async_std::task::spawn(async move { + control.push_proposal(proposal).await.unwrap(); + }); + + async_std::task::sleep(Duration::from_millis(1000)).await; + } +} + +fn main() { + cyfs_debug::ProcessDeadHelper::patch_task_min_thread(); + + async_std::task::block_on(main_run()) +} From 8fdeddf95758178516ceee68026cb84d2b0d5450 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Feb 2023 16:13:20 +0800 Subject: [PATCH 046/553] encode/decode --- src/Cargo.lock | 2460 +---------------- src/component/cyfs-base/src/objects/group.rs | 7 +- .../cyfs-core/src/group/group_proposal.rs | 1 + .../src/consensus/hotstuff/hotstuff.rs | 35 +- .../cyfs-group/src/consensus/proposal/mod.rs | 2 - .../proposal/pending_proposal_mgr.rs | 6 +- .../src/consensus/proposal/proposal.rs | 19 - .../src/consensus/vote/committee.rs | 14 +- src/component/cyfs-group/src/constant.rs | 2 +- src/component/cyfs-group/src/dec/rpath_mgr.rs | 19 +- .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../cyfs-group/src/objects/protocol.rs | 289 +- .../cyfs-stack/src/stack/group_non_driver.rs | 2 +- src/tests/group-example/src/main.rs | 218 +- 14 files changed, 589 insertions(+), 2487 deletions(-) delete mode 100644 src/component/cyfs-group/src/consensus/proposal/proposal.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 8a95160f9..c038f0090 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -145,91 +145,6 @@ version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" -[[package]] -name = "app-manager" -version = "0.5.0" -dependencies = [ - "app-manager-lib", - "async-std", - "async-trait", - "bollard", - "chrono", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-client", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-util", - "flate2", - "fs_extra", - "futures-util", - "log 0.4.17", - "ood-daemon", - "regex", - "serde", - "serde_json", - "tar", - "toml", - "version-compare", - "wait-timeout", - "walkdir", - "which", - "zip", -] - -[[package]] -name = "app-manager-lib" -version = "0.5.0" -dependencies = [ - "cyfs-base", - "cyfs-debug", - "cyfs-util", - "log 0.4.17", - "serde", - "serde_json", - "toml", -] - -[[package]] -name = "app-tool" -version = "0.5.0" -dependencies = [ - "async-std", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-util", - "lazy_static", - "log 0.4.17", - "serde_json", - "simple_logger 2.3.0", -] - -[[package]] -name = "app-tool-ex" -version = "0.5.0" -dependencies = [ - "async-std", - "chrono", - "clap", - "cyfs-base", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-util", - "lazy_static", - "log 0.4.17", - "serde_json", - "simple_logger 2.3.0", -] - [[package]] name = "arrayref" version = "0.3.6" @@ -248,12 +163,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" -[[package]] -name = "ascii_utils" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" - [[package]] name = "async-attributes" version = "1.1.2" @@ -312,7 +221,6 @@ dependencies = [ "blocking", "futures-lite", "once_cell", - "tokio", ] [[package]] @@ -410,7 +318,7 @@ checksum = "9c86f33abd5a4f3e2d6d9251a9e0c6a7e52eb1113caf893dae8429bf4a53f378" dependencies = [ "futures-lite", "rustls 0.19.1", - "webpki 0.21.4", + "webpki", ] [[package]] @@ -491,7 +399,7 @@ dependencies = [ "futures-core", "futures-io", "rustls 0.18.1", - "webpki 0.21.4", + "webpki", "webpki-roots 0.20.0", ] @@ -528,15 +436,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atoi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" -dependencies = [ - "num-traits", -] - [[package]] name = "atomic-waker" version = "1.0.0" @@ -584,16 +483,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base" -version = "0.5.0" -dependencies = [ - "cyfs-base", - "cyfs-meta-lib", - "cyfs-noc", - "cyfs-stack-loader", -] - [[package]] name = "base-x" version = "0.2.11" @@ -616,15 +505,6 @@ dependencies = [ "safemem", ] -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] - [[package]] name = "base64" version = "0.12.3" @@ -643,30 +523,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" -[[package]] -name = "bdt-debuger" -version = "0.5.0" -dependencies = [ - "async-std", - "clap", - "cyfs-base", - "cyfs-bdt", - "log 0.4.17", -] - -[[package]] -name = "bdt-debuger-deamon" -version = "0.5.0" -dependencies = [ - "async-std", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-debug", - "log 0.4.17", - "md5", -] - [[package]] name = "bincode" version = "1.3.3" @@ -683,7 +539,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f" dependencies = [ "bitcoin_hashes", - "rand 0.6.5", "rand_core 0.4.2", "serde", "unicode-normalization", @@ -766,7 +621,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", "generic-array 0.14.6", ] @@ -818,67 +672,6 @@ dependencies = [ "futures-lite", ] -[[package]] -name = "bollard" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" -dependencies = [ - "base64 0.13.1", - "bollard-stubs", - "bytes 1.3.0", - "chrono", - "dirs-next", - "futures-core", - "futures-util", - "hex", - "http", - "hyper 0.14.23", - "hyperlocal", - "log 0.4.17", - "pin-project", - "serde", - "serde_derive", - "serde_json", - "serde_urlencoded", - "thiserror", - "tokio", - "tokio-util 0.6.10", - "url 2.3.0", - "winapi", -] - -[[package]] -name = "bollard-stubs" -version = "1.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2f2e73fffe9455141e170fb9c1feb0ac521ec7e7dcd47a7cab72a658490fb8" -dependencies = [ - "chrono", - "serde", - "serde_with", -] - -[[package]] -name = "browser-meta-spv" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "cyfs-base", - "cyfs-base-meta", - "cyfs-debug", - "cyfs-meta-lib", - "hex", - "log 0.4.17", - "once_cell", - "serde", - "serde_json", - "sqlx 0.5.13", - "tide", - "toml", -] - [[package]] name = "bstr" version = "0.2.17" @@ -897,12 +690,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" -[[package]] -name = "bufstream" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" - [[package]] name = "bumpalo" version = "3.11.1" @@ -921,12 +708,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -[[package]] -name = "bytemuck" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" - [[package]] name = "byteorder" version = "1.4.3" @@ -1015,12 +796,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "checked_int_cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" - [[package]] name = "chrono" version = "0.4.23" @@ -1037,32 +812,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "chunk-manager" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-std", - "chrono", - "cyfs-base", - "cyfs-base-meta", - "cyfs-chunk", - "cyfs-debug", - "cyfs-meta-lib", - "cyfs-util", - "hex", - "http-types", - "lazy_static", - "log 0.4.17", - "rand 0.8.5", - "rusqlite", - "serde", - "serde_json", - "tide", - "timer", - "url 2.3.0", -] - [[package]] name = "cipher" version = "0.2.5" @@ -1090,7 +839,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim 0.8.0", + "strsim", "textwrap", "unicode-width", "vec_map", @@ -1105,24 +854,6 @@ dependencies = [ "term", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - -[[package]] -name = "cmake" -version = "0.1.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" -dependencies = [ - "cc", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1133,12 +864,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "colored" version = "2.0.0" @@ -1160,24 +885,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "comfy-table" -version = "6.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" -dependencies = [ - "crossterm", - "strum", - "strum_macros", - "unicode-width", -] - -[[package]] -name = "commandlines" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" - [[package]] name = "concurrent-queue" version = "2.0.0" @@ -1198,12 +905,6 @@ dependencies = [ "serde", ] -[[package]] -name = "const-cstr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" - [[package]] name = "const-oid" version = "0.7.1" @@ -1256,73 +957,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] -name = "core-graphics" -version = "0.22.3" +name = "cpufeatures" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ - "bitflags", - "core-foundation", - "core-graphics-types", - "foreign-types", "libc", ] [[package]] -name = "core-graphics-types" -version = "0.1.1" +name = "cpuid-bool" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation", - "foreign-types", - "libc", -] +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" [[package]] -name = "core-text" -version = "19.2.0" +name = "crc" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" dependencies = [ - "core-foundation", - "core-graphics", - "foreign-types", - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" -dependencies = [ - "libc", -] - -[[package]] -name = "cpuid-bool" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" - -[[package]] -name = "crc" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" -dependencies = [ - "crc-catalog 1.1.1", -] - -[[package]] -name = "crc" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" -dependencies = [ - "crc-catalog 2.1.0", + "crc-catalog", ] [[package]] @@ -1331,12 +986,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" -[[package]] -name = "crc-catalog" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" - [[package]] name = "crc32fast" version = "1.3.2" @@ -1449,31 +1098,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "crossterm" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" -dependencies = [ - "bitflags", - "crossterm_winapi", - "libc", - "mio", - "parking_lot 0.12.1", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" -dependencies = [ - "winapi", -] - [[package]] name = "crunchy" version = "0.2.2" @@ -1652,7 +1276,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "simple_logger 2.3.0", + "simple_logger", "url 2.3.0", "zip", ] @@ -1716,30 +1340,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cyfs-bench-mark" -version = "0.1.0" -dependencies = [ - "cyfs-debug", -] - -[[package]] -name = "cyfs-check" -version = "0.5.0" -dependencies = [ - "ansi_term", - "async-std", - "async-trait", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-meta-lib", - "cyfs-util", - "dirs 4.0.0", - "log 0.4.17", - "sysinfo", -] - [[package]] name = "cyfs-chunk" version = "0.5.0" @@ -1779,24 +1379,6 @@ dependencies = [ "sysinfo", ] -[[package]] -name = "cyfs-chunk-client" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-std", - "cyfs-base", - "cyfs-bdt", - "cyfs-chunk", - "cyfs-util", - "http-types", - "log 0.4.17", - "serde", - "serde_json", - "time 0.1.45", - "url 2.3.0", -] - [[package]] name = "cyfs-chunk-lib" version = "0.6.2" @@ -1829,49 +1411,6 @@ dependencies = [ "sha2 0.10.6", ] -[[package]] -name = "cyfs-client" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-std", - "async-trait", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-bdt", - "cyfs-chunk", - "cyfs-chunk-client", - "cyfs-debug", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-util", - "hex", - "http-types", - "log 0.4.17", - "once_cell", - "rand 0.7.3", - "serde_json", - "url 2.3.0", - "walkdir", -] - -[[package]] -name = "cyfs-container" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "cyfs-base", - "cyfs-bdt", - "cyfs-debug", - "cyfs-lib", - "cyfs-stack-loader", - "cyfs-util", - "futures", - "log 0.4.17", -] - [[package]] name = "cyfs-core" version = "0.6.2" @@ -1913,7 +1452,7 @@ dependencies = [ "futures", "hex", "http-types", - "hyper 0.10.16", + "hyper", "lazy_static", "libc", "log 0.4.17", @@ -2006,72 +1545,6 @@ dependencies = [ "tide", ] -[[package]] -name = "cyfs-meta" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-std", - "async-trait", - "base58", - "base64 0.13.1", - "byteorder", - "chrono", - "cyfs-base", - "cyfs-base-meta", - "cyfs-core", - "cyfs-util", - "evm", - "futures", - "generic-array 0.12.4", - "hex", - "http-types", - "lazy_static", - "libsqlite3-sys", - "log 0.4.17", - "primitive-types", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", - "sqlx 0.5.13", - "tide", - "timer", -] - -[[package]] -name = "cyfs-meta-client" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-recursion", - "async-std", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-meta-lib", - "cyfs-util", - "dirs 4.0.0", - "hex", - "http-types", - "lazy_static", - "log 0.4.17", - "rand 0.7.3", - "serde_json", - "simple_logger 2.3.0", -] - -[[package]] -name = "cyfs-meta-genesis" -version = "0.5.0" -dependencies = [ - "commandlines", - "cyfs-meta", - "log 0.4.17", - "serde_json", - "simple_logger 2.3.0", -] - [[package]] name = "cyfs-meta-lib" version = "0.6.2" @@ -2088,46 +1561,6 @@ dependencies = [ "surf", ] -[[package]] -name = "cyfs-meta-miner" -version = "0.5.0" -dependencies = [ - "async-std", - "clap", - "cyfs-base", - "cyfs-debug", - "cyfs-meta", - "cyfs-meta-lib", - "hex", - "lazy_static", - "log 0.4.17", - "serde", - "serde_json", - "tide", -] - -[[package]] -name = "cyfs-meta-spv" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "base58", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-debug", - "cyfs-meta-lib", - "ethabi", - "hex", - "libsqlite3-sys", - "log 0.4.17", - "serde", - "serde_json", - "sqlx 0.5.13", - "tide", -] - [[package]] name = "cyfs-mobile-stack" version = "0.5.0" @@ -2146,33 +1579,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "cyfs-monitor" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "chrono", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-bdt", - "cyfs-client", - "cyfs-core", - "cyfs-debug", - "cyfs-meta-lib", - "cyfs-util", - "futures", - "log 0.4.17", - "once_cell", - "rand 0.7.3", - "serde", - "serde_json", - "surf", - "toml", - "url 2.3.0", -] - [[package]] name = "cyfs-ndc" version = "0.5.0" @@ -2261,48 +1667,13 @@ dependencies = [ ] [[package]] -name = "cyfs-runtime" -version = "0.5.0" -dependencies = [ - "android_logger", - "async-h1", - "async-std", - "async-trait", - "base", - "bytes 1.3.0", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-debug", - "cyfs-lib", - "cyfs-stack-loader", - "cyfs-util", - "dirs 4.0.0", - "formdata", - "futures", - "http-types", - "hyper 0.10.16", - "jni", - "log 0.4.17", - "mime-sniffer", - "once_cell", - "ood-control", - "rand 0.7.3", - "serde", - "serde_json", - "tide", - "toml", - "url 2.3.0", -] - -[[package]] -name = "cyfs-sha2" -version = "0.8.3" +name = "cyfs-sha2" +version = "0.8.3" dependencies = [ "block-buffer 0.7.3", "digest 0.8.1", "fake-simd", - "hex-literal 0.1.4", + "hex-literal", "libc", "opaque-debug 0.2.3", "sha2-asm", @@ -2349,35 +1720,12 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "sqlx 0.5.13", + "sqlx", "tide", "toml", "zip", ] -[[package]] -name = "cyfs-stack-bench" -version = "0.1.0" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "chrono", - "clap", - "cyfs-base", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-util", - "futures", - "hex", - "lazy_static", - "log 0.4.17", - "rand 0.8.5", - "serde", - "toml", -] - [[package]] name = "cyfs-stack-loader" version = "0.5.0" @@ -2399,34 +1747,6 @@ dependencies = [ "toml", ] -[[package]] -name = "cyfs-stack-test" -version = "0.5.0" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "cyfs-base", - "cyfs-bdt", - "cyfs-chunk-lib", - "cyfs-cip", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-noc", - "cyfs-perf-client", - "cyfs-stack-loader", - "cyfs-util", - "futures", - "hex", - "log 0.4.17", - "once_cell", - "rand 0.8.5", - "serde", - "serde_json", - "zone-simulator", -] - [[package]] name = "cyfs-task-manager" version = "0.6.0" @@ -2439,7 +1759,7 @@ dependencies = [ "generic-array 0.12.4", "lazy_static", "log 0.4.17", - "sqlx 0.5.13", + "sqlx", ] [[package]] @@ -2487,7 +1807,7 @@ dependencies = [ "rusqlite", "serde", "serde_json", - "simple_logger 2.3.0", + "simple_logger", "sysinfo", "toml", "url 2.3.0", @@ -2496,41 +1816,6 @@ dependencies = [ "zip", ] -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core", - "quote", - "syn", -] - [[package]] name = "dashmap" version = "5.4.0" @@ -2569,33 +1854,6 @@ dependencies = [ "pem-rfc7468", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "desc-tool" -version = "0.5.0" -dependencies = [ - "async-std", - "chrono", - "clap", - "cyfs-base", - "cyfs-core", - "cyfs-debug", - "hex", - "log 0.4.17", - "serde_json", - "simple_logger 2.3.0", -] - [[package]] name = "digest" version = "0.8.1" @@ -2646,16 +1904,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - [[package]] name = "dirs-sys" version = "0.3.7" @@ -2667,77 +1915,24 @@ dependencies = [ "winapi", ] -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users 0.4.3", - "winapi", -] - [[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading", -] - [[package]] name = "dotenv" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" -[[package]] -name = "dotenvy" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" - -[[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "winapi", - "wio", -] - [[package]] name = "either" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" -[[package]] -name = "email" -version = "0.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4" -dependencies = [ - "base64 0.9.3", - "chrono", - "encoding", - "lazy_static", - "rand 0.4.6", - "time 0.1.45", - "version_check 0.1.5", -] - [[package]] name = "encoding" version = "0.2.33" @@ -2821,133 +2016,12 @@ dependencies = [ "serde", ] -[[package]] -name = "ethabi" -version = "14.0.0" -dependencies = [ - "anyhow", - "cyfs-base", - "ethereum-types", - "evm", - "hex", - "hex-literal 0.3.4", - "itertools", - "paste 1.0.11", - "rustc-hex", - "serde", - "serde_json", - "sha3 0.9.1", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9" -dependencies = [ - "ethereum-types", - "funty", - "hash-db", - "hash256-std-hasher", - "parity-scale-codec", - "rlp", - "rlp-derive", - "serde", - "sha3 0.9.1", - "triehash", -] - -[[package]] -name = "ethereum-types" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "uint", -] - [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "evm" -version = "0.26.0" -dependencies = [ - "criterion", - "cyfs-base", - "cyfs-base-meta", - "ethereum", - "evm-core", - "evm-gasometer", - "evm-runtime", - "hex", - "log 0.4.17", - "parity-scale-codec", - "primitive-types", - "rlp", - "rlp-derive", - "serde", - "sha3 0.8.2", -] - -[[package]] -name = "evm-core" -version = "0.26.0" -dependencies = [ - "cyfs-base-meta", - "funty", - "hex", - "parity-scale-codec", - "primitive-types", - "serde", -] - -[[package]] -name = "evm-gasometer" -version = "0.26.0" -dependencies = [ - "cyfs-base", - "evm-core", - "evm-runtime", - "primitive-types", -] - -[[package]] -name = "evm-runtime" -version = "0.26.0" -dependencies = [ - "cyfs-base", - "evm-core", - "primitive-types", - "sha3 0.8.2", -] - [[package]] name = "fake-simd" version = "0.1.2" @@ -2966,15 +2040,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" -[[package]] -name = "fast_chemail" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4" -dependencies = [ - "ascii_utils", -] - [[package]] name = "fastrand" version = "1.8.0" @@ -3000,32 +2065,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "file-manager" -version = "0.5.0" -dependencies = [ - "async-std", - "cyfs-base", - "cyfs-debug", - "cyfs-util", - "lazy_static", - "log 0.4.17", - "rusqlite", - "tide", -] - -[[package]] -name = "filetime" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.2.16", - "windows-sys 0.42.0", -] - [[package]] name = "fixed-hash" version = "0.7.0" @@ -3071,12 +2110,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "float-ord" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" - [[package]] name = "flume" version = "0.10.14" @@ -3095,31 +2128,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "font-kit" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21fe28504d371085fae9ac7a3450f0b289ab71e07c8e57baa3fb68b9e57d6ce5" -dependencies = [ - "bitflags", - "byteorder", - "core-foundation", - "core-graphics", - "core-text", - "dirs-next", - "dwrote", - "float-ord", - "freetype", - "lazy_static", - "libc", - "log 0.4.17", - "pathfinder_geometry", - "pathfinder_simd", - "walkdir", - "winapi", - "yeslogic-fontconfig-sys", -] - [[package]] name = "foreign-types" version = "0.3.2" @@ -3152,32 +2160,11 @@ checksum = "6b2e172b694029467db935166c398f911adce5373d63bb1149740cd9182a3eee" dependencies = [ "encoding", "httparse", - "hyper 0.10.16", + "hyper", "log 0.4.17", - "mime 0.2.6", - "mime_multipart", - "textnonce", -] - -[[package]] -name = "freetype" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" -dependencies = [ - "freetype-sys", - "libc", -] - -[[package]] -name = "freetype-sys" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" -dependencies = [ - "cmake", - "libc", - "pkg-config", + "mime 0.2.6", + "mime_multipart", + "textnonce", ] [[package]] @@ -3190,12 +2177,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -3294,17 +2275,6 @@ dependencies = [ "syn", ] -[[package]] -name = "futures-rustls" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" -dependencies = [ - "futures-io", - "rustls 0.20.7", - "webpki 0.22.0", -] - [[package]] name = "futures-sink" version = "0.3.25" @@ -3335,39 +2305,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gateway" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-std", - "async-trait", - "base", - "bytes 1.3.0", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-stack-loader", - "cyfs-util", - "futures", - "hex", - "http-types", - "lazy_static", - "log 0.4.17", - "lru_time_cache", - "regex", - "serde", - "serde_json", - "tide", - "toml", - "url 2.3.0", - "wildmatch", - "winapi", -] - [[package]] name = "generic-array" version = "0.12.4" @@ -3431,16 +2368,6 @@ dependencies = [ "syn", ] -[[package]] -name = "gif" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "gimli" version = "0.27.0" @@ -3505,25 +2432,6 @@ dependencies = [ "sha2 0.8.2", ] -[[package]] -name = "h2" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" -dependencies = [ - "bytes 1.3.0", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util 0.7.4", - "tracing", -] - [[package]] name = "half" version = "1.8.2" @@ -3536,21 +2444,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" -[[package]] -name = "hash-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" - -[[package]] -name = "hash256-std-hasher" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" -dependencies = [ - "crunchy", -] - [[package]] name = "hashbrown" version = "0.11.2" @@ -3565,9 +2458,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] [[package]] name = "hashlink" @@ -3578,15 +2468,6 @@ dependencies = [ "hashbrown 0.11.2", ] -[[package]] -name = "hashlink" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" -dependencies = [ - "hashbrown 0.12.3", -] - [[package]] name = "heck" version = "0.3.3" @@ -3639,12 +2520,6 @@ dependencies = [ "proc-macro-hack 0.4.3", ] -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - [[package]] name = "hex-literal-impl" version = "0.1.2" @@ -3724,16 +2599,6 @@ dependencies = [ "hmac 0.7.1", ] -[[package]] -name = "hostname" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -dependencies = [ - "libc", - "winutil", -] - [[package]] name = "http" version = "0.2.8" @@ -3745,17 +2610,6 @@ dependencies = [ "itoa 1.0.5", ] -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes 1.3.0", - "http", - "pin-project-lite 0.2.9", -] - [[package]] name = "http-client" version = "6.5.3" @@ -3809,12 +2663,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - [[package]] name = "hyper" version = "0.10.16" @@ -3834,43 +2682,6 @@ dependencies = [ "url 1.7.2", ] -[[package]] -name = "hyper" -version = "0.14.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" -dependencies = [ - "bytes 1.3.0", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.5", - "pin-project-lite 0.2.9", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyperlocal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" -dependencies = [ - "futures-util", - "hex", - "hyper 0.14.23", - "pin-project", - "tokio", -] - [[package]] name = "iana-time-zone" version = "0.1.53" @@ -3895,12 +2706,6 @@ dependencies = [ "cxx-build", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.1.5" @@ -3923,35 +2728,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "image" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-iter", - "num-rational 0.3.2", - "num-traits", -] - -[[package]] -name = "image" -version = "0.24.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "jpeg-decoder", - "num-rational 0.4.1", - "num-traits", - "png", -] - [[package]] name = "impl-codec" version = "0.5.1" @@ -3961,24 +2737,6 @@ dependencies = [ "parity-scale-codec", ] -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" -dependencies = [ - "serde", -] - [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -4148,12 +2906,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" - [[package]] name = "js-sys" version = "0.3.60" @@ -4163,15 +2915,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "keccak" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" -dependencies = [ - "cpufeatures", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -4196,38 +2939,6 @@ dependencies = [ "spin 0.5.2", ] -[[package]] -name = "lettre" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ed8677138975b573ab4949c35613931a4addeadd0a8a6aa0327e2a979660de" -dependencies = [ - "base64 0.10.1", - "bufstream", - "fast_chemail", - "hostname", - "log 0.4.17", - "native-tls", - "nom 4.2.3", - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "lettre_email" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5" -dependencies = [ - "base64 0.10.1", - "email", - "lettre", - "mime 0.3.16", - "time 0.1.45", - "uuid", -] - [[package]] name = "lexical-core" version = "0.7.6" @@ -4247,16 +2958,6 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - [[package]] name = "libm" version = "0.2.6" @@ -4345,16 +3046,6 @@ version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd" -[[package]] -name = "mac_address" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" -dependencies = [ - "nix 0.23.2", - "winapi", -] - [[package]] name = "matches" version = "0.1.9" @@ -4412,32 +3103,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93c0d11ac30a033511ae414355d80f70d9f29a44a49140face477117a1ee90db" -[[package]] -name = "meta-stat" -version = "0.1.0" -dependencies = [ - "async-std", - "async-trait", - "chrono", - "clap", - "comfy-table", - "cyfs-base", - "lettre", - "lettre_email", - "log 0.4.17", - "mime 0.3.16", - "once_cell", - "plotters", - "rand 0.7.3", - "serde", - "serde_json", - "simple_logger 3.0.0", - "sqlx 0.6.2", - "surf", - "timer", - "toml", -] - [[package]] name = "mime" version = "0.2.6" @@ -4453,15 +3118,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "mime-sniffer" -version = "0.1.2" -source = "git+https://github.com/buckyos/rust-mime-sniffer?rev=99c00bba5091810514741bfe0f05d8c9ca244796#99c00bba5091810514741bfe0f05d8c9ca244796" -dependencies = [ - "mime 0.3.16", - "url 1.7.2", -] - [[package]] name = "mime_guess" version = "2.0.4" @@ -4481,7 +3137,7 @@ dependencies = [ "buf-read-ext", "encoding", "httparse", - "hyper 0.10.16", + "hyper", "log 0.4.17", "mime 0.2.6", "tempdir", @@ -4503,18 +3159,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" -dependencies = [ - "libc", - "log 0.4.17", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", -] - [[package]] name = "multimap" version = "0.8.3" @@ -4574,18 +3218,8 @@ checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nom" -version = "4.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -dependencies = [ - "memchr", - "version_check 0.1.5", + "libc", + "memoffset 0.6.5", ] [[package]] @@ -4697,28 +3331,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -4763,89 +3375,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" -[[package]] -name = "ood-control" -version = "0.5.1" -dependencies = [ - "android_logger", - "async-h1", - "async-std", - "async-trait", - "cyfs-base", - "cyfs-debug", - "cyfs-lib", - "cyfs-util", - "futures", - "hex", - "http-types", - "jni", - "lazy_static", - "log 0.4.17", - "mac_address", - "once_cell", - "rand 0.8.5", - "serde", - "serde_json", - "sysinfo", - "tide", -] - -[[package]] -name = "ood-daemon" -version = "0.5.0" -dependencies = [ - "async-h1", - "async-std", - "async-trait", - "base", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-client", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-util", - "fs_extra", - "futures", - "futures-util", - "http-types", - "lazy_static", - "log 0.4.17", - "once_cell", - "ood-control", - "serde", - "serde_json", - "toml", - "zip", -] - -[[package]] -name = "ood-installer" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "base", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-debug", - "cyfs-meta-lib", - "cyfs-util", - "desc-tool", - "futures-util", - "hex", - "log 0.4.17", - "mac_address", - "ood-control", - "ood-daemon", - "os_type", - "qrcode", - "rust-embed", -] - [[package]] name = "oorandom" version = "11.1.3" @@ -4909,28 +3438,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "os_type" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24d44c0eea30167516ed8f6daca4b5e3eebcde1bde1e4e6e08b809fb02c7ba5" -dependencies = [ - "regex", -] - -[[package]] -name = "pack-tools" -version = "0.5.0" -dependencies = [ - "clap", - "cyfs-base", - "log 0.4.17", - "sha2 0.8.2", - "simple_logger 2.3.0", - "walkdir", - "zip", -] - [[package]] name = "parity-scale-codec" version = "2.3.1" @@ -5047,25 +3554,6 @@ dependencies = [ "proc-macro-hack 0.5.20+deprecated", ] -[[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log 0.4.17", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" -dependencies = [ - "rustc_version 0.3.3", -] - [[package]] name = "pbkdf2" version = "0.11.0" @@ -5110,16 +3598,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" -[[package]] -name = "pest" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" -dependencies = [ - "thiserror", - "ucd-trie", -] - [[package]] name = "petgraph" version = "0.6.2" @@ -5202,16 +3680,9 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ - "chrono", - "font-kit", - "image 0.24.5", - "lazy_static", "num-traits", - "pathfinder_geometry", "plotters-backend", - "plotters-bitmap", "plotters-svg", - "ttf-parser", "wasm-bindgen", "web-sys", ] @@ -5222,17 +3693,6 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" -[[package]] -name = "plotters-bitmap" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4a1f21490a6cf4a84c272ad20bd7844ed99a3178187a4c5ab7f2051295beef" -dependencies = [ - "gif", - "image 0.24.5", - "plotters-backend", -] - [[package]] name = "plotters-svg" version = "0.3.3" @@ -5242,37 +3702,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "pn-miner" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-debug", - "cyfs-util", - "libc", - "log 0.4.17", - "rusqlite", - "serde", - "serde_json", - "tide", -] - -[[package]] -name = "png" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" -dependencies = [ - "bitflags", - "crc32fast", - "flate2", - "miniz_oxide", -] - [[package]] name = "polling" version = "2.5.2" @@ -5368,8 +3797,6 @@ checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e" dependencies = [ "fixed-hash", "impl-codec", - "impl-rlp", - "impl-serde", "uint", ] @@ -5659,16 +4086,6 @@ dependencies = [ "syn", ] -[[package]] -name = "qrcode" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" -dependencies = [ - "checked_int_cast", - "image 0.23.14", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -5703,25 +4120,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" @@ -5732,7 +4130,7 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", ] [[package]] @@ -5746,16 +4144,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", -] - [[package]] name = "rand_chacha" version = "0.2.2" @@ -5809,15 +4197,6 @@ dependencies = [ "getrandom 0.2.8", ] -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rand_hc" version = "0.2.0" @@ -5827,59 +4206,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rayon" version = "1.6.1" @@ -5999,30 +4325,9 @@ dependencies = [ name = "ringbuf" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65af18d50f789e74aaf23bbb3f65dcd22a3cb6e029b5bced149f6bd57c5c2a2" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes 1.3.0", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn", +checksum = "f65af18d50f789e74aaf23bbb3f65dcd22a3cb6e029b5bced149f6bd57c5c2a2" +dependencies = [ + "cache-padded", ] [[package]] @@ -6093,10 +4398,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a" dependencies = [ "bitflags", - "chrono", "fallible-iterator", "fallible-streaming-iterator", - "hashlink 0.7.0", + "hashlink", "libsqlite3-sys", "memchr", "smallvec 1.10.0", @@ -6114,40 +4418,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rust-embed" -version = "6.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1" -dependencies = [ - "rust-embed-impl", - "rust-embed-utils", - "walkdir", -] - -[[package]] -name = "rust-embed-impl" -version = "6.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" -dependencies = [ - "proc-macro2", - "quote", - "rust-embed-utils", - "syn", - "walkdir", -] - -[[package]] -name = "rust-embed-utils" -version = "7.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" -dependencies = [ - "sha2 0.10.6", - "walkdir", -] - [[package]] name = "rustc-demangle" version = "0.1.21" @@ -6169,15 +4439,6 @@ dependencies = [ "semver 0.9.0", ] -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - [[package]] name = "rustls" version = "0.18.1" @@ -6187,8 +4448,8 @@ dependencies = [ "base64 0.12.3", "log 0.4.17", "ring", - "sct 0.6.1", - "webpki 0.21.4", + "sct", + "webpki", ] [[package]] @@ -6200,29 +4461,8 @@ dependencies = [ "base64 0.13.1", "log 0.4.17", "ring", - "sct 0.6.1", - "webpki 0.21.4", -] - -[[package]] -name = "rustls" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" -dependencies = [ - "log 0.4.17", - "ring", - "sct 0.7.0", - "webpki 0.22.0", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" -dependencies = [ - "base64 0.13.1", + "sct", + "webpki", ] [[package]] @@ -6252,30 +4492,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scale-info" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" -dependencies = [ - "cfg-if 1.0.0", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" -dependencies = [ - "proc-macro-crate 1.2.1", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "scan_dir" version = "0.3.3" @@ -6317,16 +4533,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "security-framework" version = "2.7.0" @@ -6356,16 +4562,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser 0.10.2", + "semver-parser", ] [[package]] @@ -6380,15 +4577,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - [[package]] name = "serde" version = "1.0.152" @@ -6462,28 +4650,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" -dependencies = [ - "serde", - "serde_with_macros", -] - -[[package]] -name = "serde_with_macros" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sha-1" version = "0.10.1" @@ -6566,31 +4732,6 @@ dependencies = [ "cc", ] -[[package]] -name = "sha3" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" -dependencies = [ - "block-buffer 0.7.3", - "byte-tools", - "digest 0.8.1", - "keccak", - "opaque-debug 0.2.3", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug 0.3.0", -] - [[package]] name = "shared_memory" version = "0.12.4" @@ -6615,17 +4756,6 @@ dependencies = [ "signal-hook-registry", ] -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -6668,32 +4798,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "simple_logger" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc20708d703a44b96b3b700578a85b6fe887fc63ab20315757026bb8a12faaad" -dependencies = [ - "atty", - "colored", - "log 0.4.17", - "time 0.3.17", - "winapi", -] - -[[package]] -name = "simple_logger" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" -dependencies = [ - "atty", - "colored", - "log 0.4.17", - "time 0.3.17", - "windows-sys 0.42.0", -] - [[package]] name = "slab" version = "0.4.7" @@ -6718,36 +4822,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -[[package]] -name = "sn-miner-rust" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "cyfs-base", - "cyfs-bdt", - "cyfs-debug", - "cyfs-util", - "libc", - "log 0.4.17", - "serde", - "serde_json", -] - -[[package]] -name = "sn-updater" -version = "0.1.0" -dependencies = [ - "async-std", - "clap", - "cyfs-base", - "cyfs-base-meta", - "cyfs-meta-lib", - "cyfs-util", - "log 0.4.17", - "simple_logger 4.0.0", -] - [[package]] name = "socket2" version = "0.4.7" @@ -6785,110 +4859,39 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" -dependencies = [ - "itertools", - "nom 7.1.1", - "unicode_categories", -] - -[[package]] -name = "sqlformat" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" -dependencies = [ - "itertools", - "nom 7.1.1", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551873805652ba0d912fec5bbb0f8b4cdd96baf8e2ebf5970e5671092966019b" -dependencies = [ - "sqlx-core 0.5.13", - "sqlx-macros 0.5.13", -] - -[[package]] -name = "sqlx" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" -dependencies = [ - "sqlx-core 0.6.2", - "sqlx-macros 0.6.2", -] - -[[package]] -name = "sqlx-core" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5" -dependencies = [ - "ahash", - "atoi 0.4.0", - "bitflags", - "byteorder", - "bytes 1.3.0", - "crc 2.1.0", - "crossbeam-queue", - "digest 0.10.6", - "either", - "event-listener", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "generic-array 0.14.6", - "hashlink 0.7.0", - "hex", - "indexmap", - "itoa 1.0.5", - "libc", - "libsqlite3-sys", - "log 0.4.17", - "memchr", - "num-bigint 0.3.3", - "once_cell", - "paste 1.0.11", - "percent-encoding 2.2.0", - "rand 0.8.5", - "rsa 0.6.1", - "rustls 0.19.1", - "sha-1", - "sha2 0.10.6", - "smallvec 1.10.0", - "sqlformat 0.1.8", - "sqlx-rt 0.5.13", - "stringprep", - "thiserror", - "url 2.3.0", - "webpki 0.21.4", - "webpki-roots 0.21.1", +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +dependencies = [ + "itertools", + "nom 7.1.1", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "551873805652ba0d912fec5bbb0f8b4cdd96baf8e2ebf5970e5671092966019b" +dependencies = [ + "sqlx-core", + "sqlx-macros", ] [[package]] name = "sqlx-core" -version = "0.6.2" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5" dependencies = [ "ahash", - "atoi 1.0.0", + "atoi", "bitflags", "byteorder", "bytes 1.3.0", - "crc 3.0.0", + "crc", "crossbeam-queue", - "dotenvy", + "digest 0.10.6", "either", "event-listener", "flume", @@ -6897,7 +4900,8 @@ dependencies = [ "futures-executor", "futures-intrusive", "futures-util", - "hashlink 0.8.1", + "generic-array 0.14.6", + "hashlink", "hex", "indexmap", "itoa 1.0.5", @@ -6905,19 +4909,23 @@ dependencies = [ "libsqlite3-sys", "log 0.4.17", "memchr", + "num-bigint 0.3.3", "once_cell", "paste 1.0.11", "percent-encoding 2.2.0", - "rustls 0.20.7", - "rustls-pemfile", + "rand 0.8.5", + "rsa 0.6.1", + "rustls 0.19.1", + "sha-1", "sha2 0.10.6", "smallvec 1.10.0", - "sqlformat 0.2.0", - "sqlx-rt 0.6.2", + "sqlformat", + "sqlx-rt", "stringprep", "thiserror", "url 2.3.0", - "webpki-roots 0.22.6", + "webpki", + "webpki-roots 0.21.1", ] [[package]] @@ -6933,27 +4941,8 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.6", - "sqlx-core 0.5.13", - "sqlx-rt 0.5.13", - "syn", - "url 2.3.0", -] - -[[package]] -name = "sqlx-macros" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" -dependencies = [ - "dotenvy", - "either", - "heck 0.4.0", - "once_cell", - "proc-macro2", - "quote", - "sha2 0.10.6", - "sqlx-core 0.6.2", - "sqlx-rt 0.6.2", + "sqlx-core", + "sqlx-rt", "syn", "url 2.3.0", ] @@ -6970,16 +4959,6 @@ dependencies = [ "native-tls", ] -[[package]] -name = "sqlx-rt" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" -dependencies = [ - "async-std", - "futures-rustls", -] - [[package]] name = "standback" version = "0.2.17" @@ -7002,7 +4981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ "discard", - "rustc_version 0.2.3", + "rustc_version", "stdweb-derive", "stdweb-internal-macros", "stdweb-internal-runtime", @@ -7060,31 +5039,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck 0.4.0", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - [[package]] name = "subtle" version = "1.0.0" @@ -7172,17 +5126,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tar" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "tempdir" version = "0.3.7" @@ -7394,15 +5337,6 @@ dependencies = [ "chrono", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -7420,44 +5354,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" dependencies = [ "autocfg 1.1.0", - "bytes 1.3.0", - "libc", - "memchr", - "mio", - "num_cpus", "pin-project-lite 0.2.9", - "socket2", "windows-sys 0.42.0", ] -[[package]] -name = "tokio-util" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes 1.3.0", - "futures-core", - "futures-sink", - "log 0.4.17", - "pin-project-lite 0.2.9", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" -dependencies = [ - "bytes 1.3.0", - "futures-core", - "futures-sink", - "pin-project-lite 0.2.9", - "tokio", - "tracing", -] - [[package]] name = "toml" version = "0.5.10" @@ -7468,60 +5368,12 @@ dependencies = [ "serde", ] -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite 0.2.9", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", -] - [[package]] name = "traitobject" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -[[package]] -name = "triehash" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" -dependencies = [ - "hash-db", - "rlp", -] - -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "ttf-parser" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" - [[package]] name = "tungstenite" version = "0.17.3" @@ -7553,12 +5405,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - [[package]] name = "uint" version = "0.9.5" @@ -7685,15 +5531,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "uuid" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -dependencies = [ - "rand 0.6.5", -] - [[package]] name = "value-bag" version = "1.0.0-alpha.9" @@ -7720,12 +5557,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -[[package]] -name = "version-compare" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" - [[package]] name = "version_check" version = "0.1.5" @@ -7738,15 +5569,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - [[package]] name = "waker-fn" version = "1.1.0" @@ -7764,16 +5586,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log 0.4.17", - "try-lock", -] - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -7880,23 +5692,13 @@ dependencies = [ "untrusted", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" dependencies = [ - "webpki 0.21.4", + "webpki", ] [[package]] @@ -7905,24 +5707,9 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ - "webpki 0.21.4", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki 0.22.0", + "webpki", ] -[[package]] -name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - [[package]] name = "wepoll-ffi" version = "0.1.2" @@ -7949,12 +5736,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" -[[package]] -name = "wildmatch" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" - [[package]] name = "win-sys" version = "0.3.1" @@ -8138,51 +5919,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" -[[package]] -name = "winutil" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" -dependencies = [ - "winapi", -] - -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi", -] - [[package]] name = "wyz" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" -[[package]] -name = "xattr" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" -dependencies = [ - "libc", -] - -[[package]] -name = "yeslogic-fontconfig-sys" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2bbd69036d397ebbff671b1b8e4d918610c181c5a16073b96f984a38d08c386" -dependencies = [ - "const-cstr", - "dlib", - "once_cell", - "pkg-config", -] - [[package]] name = "zeroize" version = "1.5.7" @@ -8224,56 +5966,6 @@ dependencies = [ "zstd", ] -[[package]] -name = "zone-simulator" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "bip39", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-cip", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-stack-loader", - "cyfs-util", - "futures", - "hex", - "lazy_static", - "log 0.4.17", - "once_cell", - "rand 0.7.3", -] - -[[package]] -name = "zone-stack" -version = "0.5.0" -dependencies = [ - "async-std", - "async-trait", - "bip39", - "clap", - "cyfs-base", - "cyfs-bdt", - "cyfs-cip", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-stack-loader", - "cyfs-util", - "futures", - "hex", - "log 0.4.17", - "rand 0.8.5", - "serde", - "serde_json", - "toml", - "zone-simulator", -] - [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index bab348c55..dda6c779d 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -666,7 +666,12 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { ret.set_history_block_lifespan(value.history_block_lifespan); } ret.set_revoked_conclusions(ProtobufCodecHelper::encode_buf_list( - value.revoked_conclusions.to_vec()?.as_slice(), + value + .revoked_conclusions + .iter() + .map(|id| id.clone()) + .collect::>() + .as_slice(), )?); ret.version = value.version; if value.consensus_interval > 0 { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index c09eb7e40..554888cdd 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -438,6 +438,7 @@ impl GroupProposalObject for GroupProposal { } } } + #[cfg(test)] mod test { use super::{GroupProposal, GroupProposalObject}; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 16ae05086..92456c6d5 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -15,10 +15,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::synchronizer::Synchronizer, dec_state::StatePusher, helper::Timer, AsProposal, - Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, - HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, - VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + consensus::synchronizer::Synchronizer, dec_state::StatePusher, helper::Timer, Committee, + ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, }; /** @@ -629,7 +629,7 @@ impl HotstuffRunner { self.process_qc(&Some(qc)).await; if self.local_id == self.committee.get_leader(None, self.round).await? { - self.generate_proposal(None).await; + self.generate_block(None).await; } Ok(()) } @@ -683,7 +683,7 @@ impl HotstuffRunner { self.tc = Some(tc.clone()); if self.local_id == self.committee.get_leader(None, self.round).await? { - self.generate_proposal(Some(tc)).await; + self.generate_block(Some(tc)).await; Ok(()) } else { let latest_group = self.committee.get_group(None).await?; @@ -736,7 +736,7 @@ impl HotstuffRunner { self.tc = Some(tc.clone()); if self.local_id == self.committee.get_leader(None, self.round).await? { - self.generate_proposal(Some(tc.clone())).await; + self.generate_block(Some(tc.clone())).await; } Ok(()) } @@ -781,7 +781,7 @@ impl HotstuffRunner { Ok(()) } - async fn generate_proposal(&mut self, tc: Option) -> BuckyResult<()> { + async fn generate_block(&mut self, tc: Option) -> BuckyResult<()> { let mut proposals = self.proposal_consumer.query_proposals().await?; proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); @@ -806,15 +806,16 @@ impl HotstuffRunner { // TODO: The time may be too long for too many proposals for proposal in proposals { + let proposal_id = proposal.desc().object_id(); if let Some(high_qc) = self.high_qc.as_ref() { if let Ok(is_finished) = self .store - .is_proposal_finished(&proposal.id(), &high_qc.block_id) + .is_proposal_finished(&proposal_id, &high_qc.block_id) .await { if is_finished { // dup_proposals.push(proposal); - remove_proposals.push(proposal.id()); + remove_proposals.push(proposal_id); continue; } } @@ -828,14 +829,14 @@ impl HotstuffRunner { > TIME_PRECISION { // 时间误差太大 - remove_proposals.push(proposal.id()); + remove_proposals.push(proposal.desc().object_id()); time_adjust_proposals.push(proposal); continue; } if let Some(ending) = proposal.effective_ending() { if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.id()); + remove_proposals.push(proposal.desc().object_id()); timeout_proposals.push(proposal); continue; } @@ -847,7 +848,7 @@ impl HotstuffRunner { executed_proposals.push((proposal, exe_result)); } Err(e) => { - remove_proposals.push(proposal.id()); + remove_proposals.push(proposal_id); failed_proposals.push((proposal, e)); } }; @@ -890,7 +891,7 @@ impl HotstuffRunner { let proposals_param = executed_proposals .into_iter() .map(|(proposal, exe_result)| GroupConsensusBlockProposal { - proposal: proposal.id(), + proposal: proposal.desc().object_id(), result_state: exe_result.result_state_id, receipt: exe_result.receipt.map(|receipt| receipt.to_vec().unwrap()), context: exe_result.context, @@ -907,7 +908,7 @@ impl HotstuffRunner { self.rpath.clone(), proposals_param, result_state_id, - self.store.header_height(), + pre_block.map_or(0, |b| b.height()) + 1, ObjectId::default(), // TODO: meta block id self.round, group_chunk_id.object_id(), @@ -1050,7 +1051,7 @@ impl HotstuffRunner { .await; } _ => { - self.generate_proposal(None).await; + self.generate_block(None).await; } } } @@ -1101,7 +1102,7 @@ impl HotstuffRunner { () = self.timer.wait_next().fuse() => self.local_timeout_round().await, wait_round = Self::proposal_waiter(self.rx_proposal_waiter.clone()).fuse() => { if wait_round == self.round { - self.generate_proposal(None).await + self.generate_block(None).await } else { Ok(()) } diff --git a/src/component/cyfs-group/src/consensus/proposal/mod.rs b/src/component/cyfs-group/src/consensus/proposal/mod.rs index 6aefbfd3d..6efc53d99 100644 --- a/src/component/cyfs-group/src/consensus/proposal/mod.rs +++ b/src/component/cyfs-group/src/consensus/proposal/mod.rs @@ -1,5 +1,3 @@ -mod proposal; mod pending_proposal_mgr; -pub use proposal::*; pub use pending_proposal_mgr::*; diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs index c3abf3c81..3deb31f52 100644 --- a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; use async_std::channel::{Receiver, Sender}; -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId}; use cyfs_core::GroupProposal; use futures::FutureExt; -use crate::{AsProposal, CHANNEL_CAPACITY}; +use crate::CHANNEL_CAPACITY; pub enum ProposalConsumeMessage { Query(Sender>), @@ -112,7 +112,7 @@ impl PendingProposalMgrRunner { futures::select! { proposal = self.rx_product.recv().fuse() => { if let Ok(proposal) = proposal { - self.buffer.insert(proposal.id(), proposal); + self.buffer.insert(proposal.desc().object_id(), proposal); if let Some(waker) = self.tx_proposal_waker.take() { waker.send(()).await; } diff --git a/src/component/cyfs-group/src/consensus/proposal/proposal.rs b/src/component/cyfs-group/src/consensus/proposal/proposal.rs deleted file mode 100644 index ad926b40a..000000000 --- a/src/component/cyfs-group/src/consensus/proposal/proposal.rs +++ /dev/null @@ -1,19 +0,0 @@ -// as Tx in blockchain - -use cyfs_base::ObjectId; -use cyfs_core::GroupProposal; - -pub trait AsProposal { - fn id(&self) -> ObjectId; - fn caller(&self) -> &ObjectId; -} - -impl AsProposal for GroupProposal { - fn id(&self) -> ObjectId { - todo!() - } - - fn caller(&self) -> &ObjectId { - todo!() - } -} diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 4a783338b..a9f9d7e3b 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -42,10 +42,16 @@ impl Committee { let group = self.check_group(group_chunk_id, None).await?; let voters: Vec<&ObjectId> = voters .iter() - .filter(|id| group.admins().iter().find(|mem| mem.id == **id).is_some()) + .filter(|id| { + group + .ood_list() + .iter() + .find(|mem| mem.object_id() == *id) + .is_some() + }) .collect(); - let is_enough = voters.len() >= ((group.admins().len() << 1) / 3 + 1); + let is_enough = voters.len() >= ((group.ood_list().len() << 1) / 3 + 1); Ok(is_enough) } @@ -55,8 +61,8 @@ impl Committee { round: u64, ) -> BuckyResult { let group = self.check_group(group_chunk_id, None).await?; - let i = (round % (group.admins().len() as u64)) as usize; - Ok(group.admins()[i].id) + let i = (round % (group.ood_list().len() as u64)) as usize; + Ok(group.ood_list()[i].object_id().clone()) } pub async fn verify_block( diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 726d0623a..42460e055 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -18,4 +18,4 @@ pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; -pub const NET_PROTOCOL_VPORT: u16 = 20; +pub const NET_PROTOCOL_VPORT: u16 = 2048; diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 176fe60d4..4771f96d0 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -279,8 +279,8 @@ impl GroupRPathMgr { .on_message(HotstuffMessage::LastStateRequest, remote) .await; } - HotstuffPackage::StateChangeNotify(target, header_block, qc_block) => { - let rpath = target.check_rpath(); + HotstuffPackage::StateChangeNotify(header_block, qc_block) => { + let rpath = header_block.r_path(); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; @@ -291,13 +291,22 @@ impl GroupRPathMgr { ) .await; } - HotstuffPackage::ProposalResult(target, proposal_id, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::ProposalResult(proposal_id, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::ProposalResult(proposal_id, result), remote) + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) .await; } HotstuffPackage::QueryState(target, sub_path) => { diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 01e8d0640..cd8f5a800 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -9,7 +9,7 @@ use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, G use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{helper::Timer, HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; +use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index a0edf1ae1..067e6d705 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -5,6 +5,7 @@ pub mod protos { use cyfs_base::*; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; @@ -106,7 +107,10 @@ pub(crate) enum HotstuffMessage { VerifiableState(String, BuckyResult), } -#[derive(Clone, RawEncode, RawDecode)] +const PACKAGE_FLAG_BITS: usize = 1; +const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; + +#[derive(Clone)] pub(crate) enum HotstuffPackage { Block(cyfs_core::GroupConsensusBlock), BlockVote(ProtocolAddress, HotstuffBlockQCVote), @@ -115,21 +119,277 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(ProtocolAddress, GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) LastStateRequest(ProtocolAddress), ProposalResult( - ProtocolAddress, ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + Result< + ( + Option, + GroupConsensusBlock, + GroupConsensusBlock, + ), + (BuckyError, ProtocolAddress), + >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), VerifiableState(ProtocolAddress, String, BuckyResult), } +fn encode_with_length<'a, O: RawEncode>( + buf: &'a mut [u8], + obj: &O, + purpose: &Option, + length_size: usize, +) -> BuckyResult<&'a mut [u8]> { + let (len_buf, buf) = buf.split_at_mut(length_size); + let before_len = buf.len(); + let buf = obj.raw_encode(buf, purpose)?; + let len = before_len - buf.len(); + assert!(len <= (1 << (length_size << 3)) - 1); + len_buf.copy_from_slice(&len.to_le_bytes()[..length_size]); + + Ok(buf) +} + +fn decode_with_length<'de, O: RawDecode<'de>>( + buf: &'de [u8], + length_size: usize, +) -> BuckyResult<(O, &'de [u8])> { + assert!(length_size <= 4); + let (len_buf, buf) = buf.split_at(length_size); + + let mut len_buf_4 = [0u8; 4]; + len_buf_4[..length_size].copy_from_slice(len_buf); + let len = u32::from_le_bytes(len_buf_4) as usize; + + let before_len = buf.len(); + let (obj, remain) = O::raw_decode(&buf[..len])?; + assert_eq!(remain.len(), 0); + + Ok((obj, &buf[len..])) +} + +impl RawEncode for HotstuffPackage { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let len = match self { + HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::BlockVote(addr, vote) => { + 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + } + HotstuffPackage::TimeoutVote(addr, vote) => { + 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + } + HotstuffPackage::Timeout(addr, tc) => { + 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + } + HotstuffPackage::SyncRequest(addr, min, max) => { + addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + } + HotstuffPackage::StateChangeNotify(block, qc) => { + 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + } + HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::ProposalResult(id, result) => { + id.raw_measure(purpose)? + + match result { + Ok((non, block, block_qc)) => { + non.raw_measure(purpose)? + + 3 + + block.raw_measure(purpose)? + + block_qc.raw_measure(purpose)? + } + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } + } + HotstuffPackage::QueryState(addr, sub_path) => { + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + } + HotstuffPackage::VerifiableState(addr, sub_path, result) => { + 2 + addr.raw_measure(purpose)? + + sub_path.raw_measure(purpose)? + + result.raw_measure(purpose)? + } + }; + + Ok(1 + len) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + match self { + HotstuffPackage::Block(b) => { + buf[0] = 0; + let buf = &mut buf[1..]; + b.raw_encode(buf, purpose) + } + HotstuffPackage::BlockVote(addr, vote) => { + buf[0] = 1; + let buf = &mut buf[1..]; + let buf = encode_with_length(buf, addr, purpose, 2)?; + vote.raw_encode(buf, purpose) + } + HotstuffPackage::TimeoutVote(addr, vote) => { + buf[0] = 2; + let buf = &mut buf[1..]; + let buf = encode_with_length(buf, addr, purpose, 2)?; + vote.raw_encode(buf, purpose) + } + HotstuffPackage::Timeout(addr, tc) => { + buf[0] = 3; + let buf = &mut buf[1..]; + let buf = encode_with_length(buf, addr, purpose, 2)?; + tc.raw_encode(buf, purpose) + } + HotstuffPackage::SyncRequest(addr, min, max) => { + buf[0] = 4; + let buf = &mut buf[1..]; + let buf = min.raw_encode(buf, purpose)?; + let buf = max.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + HotstuffPackage::StateChangeNotify(block, qc) => { + buf[0] = 5; + let buf = &mut buf[1..]; + let buf = encode_with_length(buf, block, purpose, 3)?; + qc.raw_encode(buf, purpose) + } + HotstuffPackage::LastStateRequest(addr) => { + buf[0] = 6; + let buf = &mut buf[1..]; + addr.raw_encode(buf, purpose) + } + HotstuffPackage::ProposalResult(id, result) => { + buf[0] = 7; + if result.is_ok() { + buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + } + + let buf = &mut buf[1..]; + let buf = id.raw_encode(buf, purpose)?; + match result { + Ok((non, block, qc)) => { + let buf = non.raw_encode(buf, purpose)?; + let buf = encode_with_length(buf, block, purpose, 3)?; + qc.raw_encode(buf, purpose) + } + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } + } + HotstuffPackage::QueryState(addr, sub_path) => { + buf[0] = 8; + let buf = &mut buf[1..]; + let buf = sub_path.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + HotstuffPackage::VerifiableState(addr, sub_path, result) => { + buf[0] = 9; + let buf = &mut buf[1..]; + let buf = encode_with_length(buf, addr, purpose, 2)?; + let buf = sub_path.raw_encode(buf, purpose)?; + result.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for HotstuffPackage { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let pkg_type = buf[0] << PACKAGE_FLAG_BITS >> PACKAGE_FLAG_BITS; + // let pkg_flag = buf[0] - pkg_type; + + match pkg_type { + 0 => { + let buf = &buf[1..]; + let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + Ok((HotstuffPackage::Block(b), buf)) + } + 1 => { + let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; + let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + Ok((HotstuffPackage::BlockVote(addr, vote), buf)) + } + 2 => { + let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; + let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) + } + 3 => { + let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; + let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + Ok((HotstuffPackage::Timeout(addr, vote), buf)) + } + 4 => { + let buf = &buf[1..]; + let (min, buf) = SyncBound::raw_decode(buf)?; + let (max, buf) = SyncBound::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) + } + 5 => { + let buf = &buf[1..]; + let (block, buf) = decode_with_length(buf, 3)?; + let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) + } + 6 => { + let buf = &buf[1..]; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + Ok((HotstuffPackage::LastStateRequest(addr), buf)) + } + 7 => { + let is_ok = (buf[0] & PACKAGE_FLAG_PROPOSAL_RESULT_OK) != 0; + let buf = &buf[1..]; + let (id, buf) = ObjectId::raw_decode(buf)?; + match is_ok { + true => { + let (non, buf) = Option::::raw_decode(buf)?; + let (block, buf) = decode_with_length(buf, 3)?; + let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + Ok(( + HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), + buf, + )) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) + } + } + } + 8 => { + let buf = &buf[1..]; + let (sub_path, buf) = String::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) + } + 9 => { + let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 3)?; + let (sub_path, buf) = String::raw_decode(buf)?; + let (result, buf) = BuckyResult::::raw_decode(buf)?; + Ok(( + HotstuffPackage::VerifiableState(addr, sub_path, result), + buf, + )) + } + _ => unreachable!("unknown protocol"), + } + } +} + impl HotstuffPackage { pub fn from_msg(msg: HotstuffMessage, rpath: GroupRPath) -> Self { match msg { @@ -150,14 +410,13 @@ impl HotstuffPackage { HotstuffPackage::LastStateRequest(ProtocolAddress::Full(rpath)) } HotstuffMessage::StateChangeNotify(header_block, qc_block) => { - HotstuffPackage::StateChangeNotify( - ProtocolAddress::Full(rpath), - header_block, - qc_block, - ) + HotstuffPackage::StateChangeNotify(header_block, qc_block) } HotstuffMessage::ProposalResult(proposal_id, result) => { - HotstuffPackage::ProposalResult(ProtocolAddress::Full(rpath), proposal_id, result) + HotstuffPackage::ProposalResult( + proposal_id, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ) } HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) @@ -176,7 +435,7 @@ pub(crate) enum ProtocolAddress { } impl ProtocolAddress { - pub fn check_rpath(self) -> GroupRPath { + pub fn check_rpath(&self) -> &GroupRPath { match self { ProtocolAddress::Full(rpath) => rpath, ProtocolAddress::Channel(_) => panic!("no rpath"), diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 95223c08d..da434c1f9 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectTypeCode}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, RequestProtocol, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0d8f62351..b829afafb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,10 +1,17 @@ -use std::{clone, time::Duration}; +use std::{clone, sync::Arc, time::Duration}; -use cyfs_base::{NamedObject, ObjectDesc, ObjectId}; +use cyfs_base::{ + AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, +}; use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; +use cyfs_lib::{ + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, + NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, +}; +use cyfs_stack::CyfsStack; use Common::{ - create_stack, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, + create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, EXAMPLE_RPATH, }; use GroupDecService::DecService; @@ -14,9 +21,11 @@ mod Common { use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, Group, GroupMember, - NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawFrom, - StandardObject, TypelessCoreObject, UniqueId, + IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawEncode, + RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, UniqueId, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; + use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId, DecAppObj}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; use cyfs_meta_lib::MetaMinerTarget; @@ -28,38 +37,48 @@ mod Common { use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<(People, PrivateKey, Device)> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<(People, PrivateKey, Device)> = create_members("member", 9); + pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0, EXAMPLE_ADMINS.iter().map(|m| &m.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.2).collect()); + pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members(name_prefix: &str, count: usize) -> Vec<(People, PrivateKey, Device)> { + fn create_members( + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + log::info!("create members"); + let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); let mut members = vec![]; for i in 0..count { let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_secp256k1().unwrap(); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); let mut owner = People::new(None, vec![], private_key.public(), None, Some(name), None).build(); let mut endpoint = Endpoint::default(); endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))); endpoint.mut_addr().set_port(port_begin + i as u16); endpoint.set_static_wan(true); - let device = Device::new( + let mut device = Device::new( Some(owner.desc().object_id()), UniqueId::create_with_random(), vec![endpoint], vec![], // TODO: 当前版本是否支持无SN? vec![], - private_key.public(), + device_private_key.public(), Area::default(), DeviceCategory::PC, ) @@ -68,7 +87,72 @@ mod Common { owner .ood_list_mut() .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - members.push((owner, private_key, device)); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); + + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); + + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( + "people: {:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", + owner.desc().object_id(), + device.desc().object_id(), + private_key.public().to_hex().unwrap().split_at(32).0, + private_key.to_string(), + desc_signature.to_hex().unwrap(), + owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() + ); + + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + members.push(((owner, private_key), (device, device_private_key))); } members @@ -80,6 +164,8 @@ mod Common { members: Vec<&People>, oods: Vec<&Device>, ) -> Group { + log::info!("create group"); + let mut group = Group::new_org(founder.desc().object_id(), Area::default()).build(); group.check_org_body_content_mut().set_admins( admins @@ -98,22 +184,28 @@ mod Common { .map(|d| DeviceId::try_from(d.desc().object_id()).unwrap()) .collect(), ); + + log::info!("create group: {:?}", group.desc().object_id()); + group } - pub async fn create_stack( + fn init_stack_params( people: People, - private_key: PrivateKey, + private_key: &PrivateKey, device: Device, - ) -> CyfsStack { - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.2.clone()).collect(); - let mut member_device: Vec = EXAMPLE_MEMBERS.iter().map(|m| m.2.clone()).collect(); + ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { + log::info!("init_stack_params"); + + let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); + let mut member_device: Vec = + EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { - device, + device: device.clone(), tcp_port_mapping: vec![], - secret: private_key, + secret: private_key.clone(), known_sn: vec![], known_device, known_passive_pn: vec![], @@ -146,7 +238,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for (member, _, device) in EXAMPLE_ADMINS.iter() { + for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -156,15 +248,15 @@ mod Common { )); known_objects.list.push(NONObjectInfo::new( - member.desc().object_id(), - member.to_vec().unwrap(), + device.desc().object_id(), + device.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Device( device.clone(), )))), )); } - for (member, _, device) in EXAMPLE_MEMBERS.iter() { + for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -174,8 +266,8 @@ mod Common { )); known_objects.list.push(NONObjectInfo::new( - member.desc().object_id(), - member.to_vec().unwrap(), + device.desc().object_id(), + device.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Device( device.clone(), )))), @@ -198,9 +290,31 @@ mod Common { Some(Arc::new(AnyNamedObject::Core(typeless))), )); - CyfsStack::open(bdt_param, stack_param, known_objects) + Box::new((bdt_param, stack_param, known_objects)) + } + + pub async fn create_stack( + people: People, + private_key: &PrivateKey, + device: Device, + ) -> CyfsStack { + let params = init_stack_params(people, private_key, device); + + log::info!("cyfs-stack.open"); + + let stack = CyfsStack::open(params.0, params.1, params.2) .await - .unwrap() + .map_err(|e| { + log::error!("stack start failed: {}", e); + e + }) + .unwrap(); + + stack + } + + pub fn dummy(people: People, device: Device) { + log::info!("common::dummy"); } } @@ -460,6 +574,8 @@ fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { } async fn main_run() { + log::info!("main_run"); + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -475,16 +591,19 @@ async fn main_run() { cyfs_debug::ProcessDeadHelper::instance().enable_exit_on_task_system_dead(None); - let mut admin_stacks = vec![]; - for (admin, private_key, device) in EXAMPLE_ADMINS.iter() { - let cyfs_stack = create_stack(admin.clone(), private_key.clone(), device.clone()).await; + log::info!("will open stacks"); + + let mut admin_stacks: Vec = vec![]; + for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { + // dummy(admin.clone(), device.clone()); + let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; DecService::run(&cyfs_stack, admin.name().unwrap().to_string()).await; admin_stacks.push(cyfs_stack); } for i in 1..100000000 { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0; + let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; let proposal = create_proposal(i as u64, owner.desc().object_id()); let control = stack @@ -498,7 +617,33 @@ async fn main_run() { .await .unwrap(); + let noc = stack.noc_manager().clone(); + async_std::task::spawn(async move { + let buf = proposal.to_vec().unwrap(); + let proposal_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + noc.put_object(&NamedObjectCachePutObjectRequest { + source: RequestSourceInfo { + protocol: RequestProtocol::DatagramBdt, + zone: DeviceZoneInfo { + device: None, + zone: None, + zone_category: DeviceZoneCategory::CurrentDevice, + }, + dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + verified: None, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), + storage_category: NamedObjectStorageCategory::Storage, + context: None, + last_access_rpath: None, + access_string: None, + }) + .await + .unwrap(); + control.push_proposal(proposal).await.unwrap(); }); @@ -507,7 +652,12 @@ async fn main_run() { } fn main() { + log::info!("main"); + cyfs_debug::ProcessDeadHelper::patch_task_min_thread(); - async_std::task::block_on(main_run()) + log::info!("will main-run"); + + let fut = Box::pin(main_run()); + async_std::task::block_on(async move { fut.await }) } From 1dd31994c3892048aa547a6294fae7bee28c1112 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Feb 2023 18:13:12 +0800 Subject: [PATCH 047/553] use ood.id --- .../src/consensus/hotstuff/hotstuff.rs | 82 +++++++++++-------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 92456c6d5..dd9c337a2 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -3,8 +3,8 @@ use std::{collections::HashMap, sync::Arc, time::SystemTime}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectLink, RawConvertTo, RawDecode, RawEncode, RsaCPUObjectSigner, - SignatureSource, Signer, + ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, + RsaCPUObjectSigner, SignatureSource, Signer, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -234,13 +234,23 @@ impl HotstuffRunner { .committee .get_leader(Some(block.group_chunk_id()), block.round()) .await?; - if &leader != block.owner() { - log::warn!( - "receive block from invalid leader({}), expected {}", - block.owner(), - leader - ); - return Err(BuckyError::new(BuckyErrorCode::Ignored, "invalid leader")); + let leader_owner = self + .non_driver + .get_device(&leader) + .await? + .desc() + .owner() + .clone(); + match leader_owner.as_ref() { + Some(owner) if owner == block.owner() => {} + _ => { + log::warn!( + "receive block from invalid leader({}), expected {}", + block.owner(), + leader + ); + return Err(BuckyError::new(BuckyErrorCode::Ignored, "invalid leader")); + } } } @@ -489,7 +499,7 @@ impl HotstuffRunner { if let Some(vote) = self.make_vote(block).await { let next_leader = self.committee.get_leader(None, self.round + 1).await?; - if self.local_id == next_leader { + if self.local_device_id == next_leader { self.handle_vote(&vote, Some(block), remote).await?; } else { self.network_sender @@ -628,7 +638,7 @@ impl HotstuffRunner { ) -> BuckyResult<()> { self.process_qc(&Some(qc)).await; - if self.local_id == self.committee.get_leader(None, self.round).await? { + if self.local_device_id == self.committee.get_leader(None, self.round).await? { self.generate_block(None).await; } Ok(()) @@ -642,6 +652,18 @@ impl HotstuffRunner { if timeout.round < self.round || timeout.high_qc.as_ref().map_or(0, |qc| qc.round) >= timeout.round { + if let Some(tc) = self.tc.as_ref() { + // if there is a timeout-qc, notify the remote to advance the round + if tc.round + 1 == self.round { + self.network_sender + .post_message( + HotstuffMessage::Timeout(tc.clone()), + self.rpath.clone(), + &remote, + ) + .await; + } + } return Ok(()); } @@ -682,7 +704,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - if self.local_id == self.committee.get_leader(None, self.round).await? { + if self.local_device_id == self.committee.get_leader(None, self.round).await? { self.generate_block(Some(tc)).await; Ok(()) } else { @@ -735,7 +757,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - if self.local_id == self.committee.get_leader(None, self.round).await? { + if self.local_device_id == self.committee.get_leader(None, self.round).await? { self.generate_block(Some(tc.clone())).await; } Ok(()) @@ -753,30 +775,20 @@ impl HotstuffRunner { } }; - match self.tc.as_ref() { - Some(tc) => { - if tc.round + 1 == self.round { - self.broadcast(HotstuffMessage::Timeout(tc.clone()), &latest_group) - .await; - } - } - None => { - let timeout = HotstuffTimeoutVote::new( - self.high_qc.clone(), - self.round, - self.local_device_id, - &self.signer, - ) - .await?; + let timeout = HotstuffTimeoutVote::new( + self.high_qc.clone(), + self.round, + self.local_device_id, + &self.signer, + ) + .await?; - self.store.set_last_vote_round(self.round).await?; + self.store.set_last_vote_round(self.round).await?; - self.handle_timeout(&timeout, self.local_id).await; + self.handle_timeout(&timeout, self.local_id).await; - self.broadcast(HotstuffMessage::TimeoutVote(timeout), &latest_group) - .await; - } - } + self.broadcast(HotstuffMessage::TimeoutVote(timeout), &latest_group) + .await; Ok(()) } @@ -1032,7 +1044,7 @@ impl HotstuffRunner { self.timer.reset(duration); if let Ok(leader) = self.committee.get_leader(None, self.round).await { - if leader == self.local_id { + if leader == self.local_device_id { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id From ba1682ff3591e7126c9a8867d6522e90b5ab953a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Feb 2023 20:53:20 +0800 Subject: [PATCH 048/553] add logs --- .../src/consensus/hotstuff/hotstuff.rs | 324 ++++++++++++++++-- .../cyfs-group/src/objects/protocol.rs | 2 +- src/tests/group-example/src/main.rs | 3 +- 3 files changed, 292 insertions(+), 37 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index dd9c337a2..be343f55a 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -27,6 +27,7 @@ use crate::{ */ pub(crate) struct Hotstuff { + local_device_id: ObjectId, tx_message: Sender<(HotstuffMessage, ObjectId)>, state_pusher: StatePusher, } @@ -77,30 +78,72 @@ impl Hotstuff { }); Self { + local_device_id, tx_message, state_pusher, } } pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { + log::debug!("[hotstuff] local: {:?}, on_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", + self.local_device_id, + block.named_object().desc().object_id(), block.round(), block.height(), + block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), + block.owner(), remote); + self.tx_message .send((HotstuffMessage::Block(block), remote)) .await; } pub async fn on_block_vote(&self, vote: HotstuffBlockQCVote, remote: ObjectId) { + log::debug!("[hotstuff] local: {:?}, on_block_vote: {:?}/{:?}, prev: {:?}, voter: {:?}, remote: {:?},", + self.local_device_id, + vote.block_id, vote.round, + vote.prev_block_id, + vote.voter, remote); + self.tx_message .send((HotstuffMessage::BlockVote(vote), remote)) .await; } pub async fn on_timeout_vote(&self, vote: HotstuffTimeoutVote, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_timeout_vote: {:?}, qc: {:?}, voter: {:?}, remote: {:?},", + self.local_device_id, + vote.round, + vote.high_qc.as_ref().map(|qc| format!( + "{:?}/{:?}/{:?}/{:?}", + qc.block_id, + qc.round, + qc.prev_block_id, + qc.votes + .iter() + .map(|v| v.voter.to_string()) + .collect::>() + )), + vote.voter, + remote + ); + self.tx_message .send((HotstuffMessage::TimeoutVote(vote), remote)) .await; } pub async fn on_timeout(&self, tc: HotstuffTimeout, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_timeout: {:?}, voter: {:?}, remote: {:?},", + self.local_device_id, + tc.round, + tc.votes + .iter() + .map(|vote| format!("{:?}/{:?}", vote.high_qc_round, vote.voter,)) + .collect::>(), + remote + ); + self.tx_message .send((HotstuffMessage::Timeout(tc), remote)) .await; @@ -112,12 +155,26 @@ impl Hotstuff { max_bound: SyncBound, remote: ObjectId, ) { + log::debug!( + "[hotstuff] local: {:?}, on_sync_request: min: {:?}, max: {:?}, remote: {:?},", + self.local_device_id, + min_bound, + max_bound, + remote + ); + self.tx_message .send((HotstuffMessage::SyncRequest(min_bound, max_bound), remote)) .await; } pub async fn request_last_state(&self, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_sync_request: remote: {:?},", + self.local_device_id, + remote + ); + self.state_pusher.request_last_state(remote).await; } } @@ -210,10 +267,17 @@ impl HotstuffRunner { block: &GroupConsensusBlock, remote: ObjectId, ) -> BuckyResult<()> { + log::debug!("[hotstuff] local: {:?}, handle_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", + self.local_device_id, + block.named_object().desc().object_id(), block.round(), block.height(), + block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), + block.owner(), remote); + let latest_group = self.committee.get_group(None).await?; if !latest_group.contain_ood(&remote) { log::warn!( - "receive block({}) from unknown({})", + "[hotstuff] local: {:?}, receive block({}) from unknown({})", + self.local_device_id, block.named_object().desc().object_id(), remote ); @@ -233,21 +297,41 @@ impl HotstuffRunner { let leader = self .committee .get_leader(Some(block.group_chunk_id()), block.round()) - .await?; + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", + self.local_device_id, + block.group_chunk_id(), block.round(), + err + ); + + err + })?; let leader_owner = self .non_driver .get_device(&leader) - .await? + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader by id {:?} failed, {:?}.", + self.local_device_id, + leader, + err + ); + + err + })? .desc() .owner() .clone(); match leader_owner.as_ref() { - Some(owner) if owner == block.owner() => {} + Some(leader_owner) if leader_owner == block.owner() => {} _ => { - log::warn!( - "receive block from invalid leader({}), expected {}", + log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", + self.local_device_id, + block.named_object().desc().object_id(), block.owner(), - leader + leader_owner ); return Err(BuckyError::new(BuckyErrorCode::Ignored, "invalid leader")); } @@ -257,29 +341,51 @@ impl HotstuffRunner { let (prev_block, proposals) = { match self.store.block_linked(block).await? { crate::storage::BlockLinkState::Expired => { - log::warn!("receive block expired."); + log::warn!( + "[hotstuff] local: {:?}, receive block expired.", + self.local_device_id + ); return Err(BuckyError::new(BuckyErrorCode::Ignored, "expired")); } crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!("receive block with duplicate proposal."); + log::warn!( + "[hotstuff] local: {:?}, receive block with duplicate proposal.", + self.local_device_id + ); return Err(BuckyError::new( BuckyErrorCode::AlreadyExists, "duplicate proposal", )); } crate::storage::BlockLinkState::Duplicate => { - log::warn!("receive duplicate block."); + log::warn!( + "[hotstuff] local: {:?}, receive duplicate block.", + self.local_device_id + ); return Err(BuckyError::new( BuckyErrorCode::AlreadyExists, "duplicate block", )); } crate::storage::BlockLinkState::Link(prev_block, proposals) => { + log::debug!( + "[hotstuff] local: {:?}, receive in-order block, height: {}.", + self.local_device_id, + block.height() + ); + // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block)?; (prev_block, proposals) } crate::storage::BlockLinkState::Pending => { + log::warn!( + "[hotstuff] local: {:?}, receive out-order block, expect height: {}, get height: {}.", + self.local_device_id, + self.store.header_height() + 3, + block.height() + ); + // 乱序,同步 if block.height() <= self.store.header_height() + 3 { self.fetch_block(block.prev_block_id().unwrap(), remote) @@ -296,13 +402,27 @@ impl HotstuffRunner { return Ok(()); } crate::storage::BlockLinkState::InvalidBranch => { - log::warn!("receive block in invalid branch."); + log::warn!( + "[hotstuff] local: {:?}, receive block in invalid branch.", + self.local_device_id + ); return Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch")); } } }; - self.committee.verify_block(block, remote).await?; + self.committee + .verify_block(block, remote) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, verify block {:?} failed, {:?}.", + self.local_device_id, + block.named_object().desc().object_id(), + err + ); + err + })?; self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) .await?; @@ -373,10 +493,34 @@ impl HotstuffRunner { .map_or(None, |block| block.result_state_id().clone()); for proposal_exe_info in block.proposals() { - // TODO: 去重 + // 去重 + if let Some(prev_block_id) = block.prev_block_id() { + if self.store + .is_proposal_finished(&proposal_exe_info.proposal, prev_block_id) + .await.map_err(|err| { + log::warn!("[hotstuff] local: {:?}, check proposal {:?} in block {:?} with prev-block {:?} duplicate failed, {:?}." + , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id, err); + err + })? { + log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." + , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id); + + return Err(BuckyError::new(BuckyErrorCode::ErrorState, "duplicate proposal")) + } + } + let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); let receipt = match proposal_exe_info.receipt.as_ref() { - Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + Some(receipt) => { + let (receipt, _) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { + log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} decode receipt failed {:?}." + , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); + + err + })?; + + Some(receipt) + }, None => None, }; @@ -389,12 +533,17 @@ impl HotstuffRunner { if self .delegate .on_verify(proposal, prev_state_id, &exe_result) - .await? + .await.map_err(|err| { + log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." + , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); + err + })? { prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + self.local_device_id, proposal_exe_info.proposal, prev_state_id, proposal_exe_info.result_state @@ -421,11 +570,28 @@ impl HotstuffRunner { /** * 验证过的块执行这个函数 */ - let new_header_block = self.store.push_block(block.clone()).await?; + + log::info!( + "[hotstuff] local: {:?}, will push new block {:?} to storage", + self.local_device_id, block.named_object().desc().object_id() + ); + + let new_header_block = self.store.push_block(block.clone()).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, push verified block {:?} to storage failed {:?}", + self.local_device_id, block.named_object().desc().object_id(), err + ); + + err + })?; if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + log::info!( + "[hotstuff] local: {:?}, new header-block {:?} committed", + self.local_device_id, header_block.named_object().desc().object_id() + ); + /** - * TODO: * 这里只清理已经提交的block包含的proposal * 已经执行过的待提交block包含的proposal在下次打包时候去重 * */ @@ -442,7 +608,13 @@ impl HotstuffRunner { Some(block_id) => self .non_driver .get_block(block_id, None) - .await? + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", + self.local_device_id, block_id, err + ); + err + })? .result_state_id() .clone(), None => None, @@ -452,10 +624,23 @@ impl HotstuffRunner { let proposal_obj = self .non_driver .get_proposal(&proposal.proposal, None) - .await?; + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", + self.local_device_id, proposal.proposal, header_block.named_object().desc().object_id(), err + ); + + err + })?; let receipt = match proposal.receipt.as_ref() { Some(receipt) => { - let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice())?; + let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", + self.local_device_id, proposal.proposal, header_block.named_object().desc().object_id(), err + ); + err + })?; assert_eq!(remain.len(), 0); Some(receipt) } @@ -482,8 +667,19 @@ impl HotstuffRunner { } match self.vote_mgr.add_voting_block(block).await { - VoteThresholded::QC(qc) => return self.process_block_qc(qc, block, remote).await, + VoteThresholded::QC(qc) => { + log::debug!( + "[hotstuff] local: {:?}, the qc of block {:?} has received before", + self.local_device_id, block.named_object().desc().object_id() + ); + return self.process_block_qc(qc, block, remote).await; + }, VoteThresholded::TC(tc, max_high_qc_block) => { + log::debug!( + "[hotstuff] local: {:?}, the timeout-qc of block {:?} has received before", + self.local_device_id, block.named_object().desc().object_id() + ); + return self .process_timeout_qc(tc, max_high_qc_block.as_ref()) .await @@ -492,12 +688,26 @@ impl HotstuffRunner { } if block.round() != self.round { + log::debug!( + "[hotstuff] local: {:?}, not my round {}, expect {}", + self.local_device_id, block.round(), self.round + ); // 不是我的投票round return Ok(()); } if let Some(vote) = self.make_vote(block).await { - let next_leader = self.committee.get_leader(None, self.round + 1).await?; + log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", + self.local_device_id, block.named_object().desc().object_id(), block.round()); + + let next_leader = self.committee.get_leader(None, self.round + 1).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader in round {} failed {:?}", + self.local_device_id, self.round + 1, err + ); + + err + })?; if self.local_device_id == next_leader { self.handle_vote(&vote, Some(block), remote).await?; @@ -516,27 +726,47 @@ impl HotstuffRunner { } async fn process_qc(&mut self, qc: &Option) { - self.advance_round(qc.as_ref().map_or(0, |qc| qc.round)) - .await; + let qc_round = qc.as_ref().map_or(0, |qc| qc.round); + + log::debug!("[hotstuff] local: {:?}, process_qc round {}", + self.local_device_id, qc_round); + + self.advance_round(qc_round).await; self.update_high_qc(qc); } async fn advance_round(&mut self, round: u64) { if round < self.round { + log::debug!("[hotstuff] local: {:?}, round {} timeout expect {}", + self.local_device_id, round, self.round); return; } - if let Ok(group) = self.committee.get_group(None).await { - self.timer.reset(group.consensus_interval()); - self.round = round + 1; - self.vote_mgr.cleanup(self.round); - self.tc = None; + match self.committee.get_group(None).await { + Ok(group) => { + self.timer.reset(group.consensus_interval()); + self.round = round + 1; + self.vote_mgr.cleanup(self.round); + self.tc = None; + + log::info!("[hotstuff] local: {:?}, update round from {} to {}", + self.local_device_id, self.round, round + 1); + } + Err(err) => { + log::warn!("[hotstuff] local: {:?}, get group before update round from {} to {} failed {:?}", + self.local_device_id, self.round, round + 1, err); + } } } fn update_high_qc(&mut self, qc: &Option) { - if qc.as_ref().map_or(0, |qc| qc.round) > self.high_qc.as_ref().map_or(0, |qc| qc.round) { + let to_high_round = qc.as_ref().map_or(0, |qc| qc.round); + let cur_high_round = self.high_qc.as_ref().map_or(0, |qc| qc.round); + if to_high_round > cur_high_round { self.high_qc = qc.clone(); + + log::info!("[hotstuff] local: {:?}, update high-qc from {} to {}", + self.local_device_id, cur_high_round, to_high_round); } } @@ -546,10 +776,17 @@ impl HotstuffRunner { .iter() .map(|proposal| proposal.proposal) .collect(); + + log::debug!("[hotstuff] local: {:?}, remove proposals: {:?}", + self.local_device_id, proposals); + self.proposal_consumer.remove_proposals(proposals).await } async fn notify_proposal_err(&self, proposal: &GroupProposal, err: BuckyError) { + log::debug!("[hotstuff] local: {:?}, proposal {} failed {:?}", + self.local_device_id, proposal.desc().object_id(), err); + self.state_pusher .notify_proposal_err(proposal.clone(), err) .await; @@ -557,36 +794,53 @@ impl HotstuffRunner { async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { if block.round() <= self.store.last_vote_round() { + log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", + self.local_device_id, block.named_object().desc().object_id(), block.round(), self.store.last_vote_round()); + return None; } // TODO: 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 // round只能逐个递增 - let is_valid_round = if block.round() == block.qc().as_ref().map_or(0, |qc| qc.round) + 1 { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + let is_valid_round = if block.round() == qc_round + 1 { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && block.qc().as_ref().map_or(0, |qc| qc.round) + && qc_round >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() } else { false }; if !is_valid_round { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + self.local_device_id, + block.named_object().desc().object_id(), + block.round(), qc_round, + block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + return None; } match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} - _ => return None, + _ => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", + self.local_device_id, + block.named_object().desc().object_id()); + + return None; + } } let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => vote, Err(e) => { log::warn!( - "signature for block-vote failed, block: {}, err: {}", + "[hotstuff] local: {:?}, signature for block-vote failed, block: {}, err: {}", + self.local_device_id, block.named_object().desc().object_id(), e ); diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 067e6d705..f4a868190 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -10,7 +10,7 @@ use cyfs_core::{ use cyfs_lib::NONObjectInfo; use sha2::Digest; -#[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone)] +#[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), Round(u64), diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b829afafb..c5e8e8294 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -141,7 +141,8 @@ mod Common { device.signs_mut().set_body_sign(body_signature); log::info!( - "people: {:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", + "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", + owner.name().unwrap(), owner.desc().object_id(), device.desc().object_id(), private_key.public().to_hex().unwrap().split_at(32).0, From f455f124943ba3008cb976e2d4b49e8ba5ac31da Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Feb 2023 18:24:50 +0800 Subject: [PATCH 049/553] add logs --- .../src/group/group_consensus_block.rs | 3 +- .../cyfs-core/src/group/group_proposal.rs | 3 +- .../cyfs-core/src/group/group_rpath.rs | 9 +- .../src/consensus/hotstuff/hotstuff.rs | 543 ++++++++++++++---- 4 files changed, 454 insertions(+), 104 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index aa1c75c03..e7e808ef5 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -5,10 +5,9 @@ use std::sync::{ use crate::{CoreObjectType, GroupRPath}; use cyfs_base::*; -use serde::Serialize; use sha2::Digest; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { r_path: GroupRPath, diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 554888cdd..0ce57b6a9 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,10 +1,9 @@ use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; -use serde::Serialize; use sha2::Digest; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { r_path: GroupRPath, diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index b7a43bfc3..3b86fbc57 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,7 +1,6 @@ use cyfs_base::*; -use serde::Serialize; -#[derive(Clone, Debug, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, @@ -9,6 +8,12 @@ pub struct GroupRPath { r_path: String, } +impl std::fmt::Debug for GroupRPath { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + } +} + impl GroupRPath { pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { Self { diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index be343f55a..9d3492255 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -27,11 +27,18 @@ use crate::{ */ pub(crate) struct Hotstuff { + rpath: GroupRPath, local_device_id: ObjectId, tx_message: Sender<(HotstuffMessage, ObjectId)>, state_pusher: StatePusher, } +impl std::fmt::Debug for Hotstuff { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}-{:?}", self.rpath, self.local_device_id) + } +} + impl Hotstuff { pub fn new( local_id: ObjectId, @@ -57,36 +64,40 @@ impl Hotstuff { let tx_message_runner = tx_message.clone(); let state_pusher_runner = state_pusher.clone(); - async_std::task::spawn(async move { - HotstuffRunner::new( - local_id, - local_device_id, - committee, - store, - signer, - network_sender, - non_driver, - tx_message_runner, - rx_message, - proposal_consumer, - state_pusher_runner, - delegate, - rpath, - ) - .run() - .await - }); + { + let rpath2 = rpath.clone(); + async_std::task::spawn(async move { + HotstuffRunner::new( + local_id, + local_device_id, + committee, + store, + signer, + network_sender, + non_driver, + tx_message_runner, + rx_message, + proposal_consumer, + state_pusher_runner, + delegate, + rpath2, + ) + .run() + .await + }); + } Self { local_device_id, tx_message, state_pusher, + rpath } } pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { log::debug!("[hotstuff] local: {:?}, on_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", - self.local_device_id, + self, block.named_object().desc().object_id(), block.round(), block.height(), block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), block.owner(), remote); @@ -98,7 +109,7 @@ impl Hotstuff { pub async fn on_block_vote(&self, vote: HotstuffBlockQCVote, remote: ObjectId) { log::debug!("[hotstuff] local: {:?}, on_block_vote: {:?}/{:?}, prev: {:?}, voter: {:?}, remote: {:?},", - self.local_device_id, + self, vote.block_id, vote.round, vote.prev_block_id, vote.voter, remote); @@ -111,7 +122,7 @@ impl Hotstuff { pub async fn on_timeout_vote(&self, vote: HotstuffTimeoutVote, remote: ObjectId) { log::debug!( "[hotstuff] local: {:?}, on_timeout_vote: {:?}, qc: {:?}, voter: {:?}, remote: {:?},", - self.local_device_id, + self, vote.round, vote.high_qc.as_ref().map(|qc| format!( "{:?}/{:?}/{:?}/{:?}", @@ -135,7 +146,7 @@ impl Hotstuff { pub async fn on_timeout(&self, tc: HotstuffTimeout, remote: ObjectId) { log::debug!( "[hotstuff] local: {:?}, on_timeout: {:?}, voter: {:?}, remote: {:?},", - self.local_device_id, + self, tc.round, tc.votes .iter() @@ -157,7 +168,7 @@ impl Hotstuff { ) { log::debug!( "[hotstuff] local: {:?}, on_sync_request: min: {:?}, max: {:?}, remote: {:?},", - self.local_device_id, + self, min_bound, max_bound, remote @@ -171,7 +182,7 @@ impl Hotstuff { pub async fn request_last_state(&self, remote: ObjectId) { log::debug!( "[hotstuff] local: {:?}, on_sync_request: remote: {:?},", - self.local_device_id, + self, remote ); @@ -202,6 +213,12 @@ struct HotstuffRunner { state_pusher: StatePusher, } +impl std::fmt::Debug for HotstuffRunner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.debug_identify()) + } +} + impl HotstuffRunner { #[allow(clippy::too_many_arguments)] pub fn new( @@ -268,7 +285,7 @@ impl HotstuffRunner { remote: ObjectId, ) -> BuckyResult<()> { log::debug!("[hotstuff] local: {:?}, handle_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", - self.local_device_id, + self, block.named_object().desc().object_id(), block.round(), block.height(), block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), block.owner(), remote); @@ -277,7 +294,7 @@ impl HotstuffRunner { if !latest_group.contain_ood(&remote) { log::warn!( "[hotstuff] local: {:?}, receive block({}) from unknown({})", - self.local_device_id, + self, block.named_object().desc().object_id(), remote ); @@ -300,7 +317,7 @@ impl HotstuffRunner { .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", - self.local_device_id, + self, block.group_chunk_id(), block.round(), err ); @@ -314,7 +331,7 @@ impl HotstuffRunner { .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader by id {:?} failed, {:?}.", - self.local_device_id, + self, leader, err ); @@ -328,7 +345,7 @@ impl HotstuffRunner { Some(leader_owner) if leader_owner == block.owner() => {} _ => { log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", - self.local_device_id, + self, block.named_object().desc().object_id(), block.owner(), leader_owner @@ -343,14 +360,14 @@ impl HotstuffRunner { crate::storage::BlockLinkState::Expired => { log::warn!( "[hotstuff] local: {:?}, receive block expired.", - self.local_device_id + self ); return Err(BuckyError::new(BuckyErrorCode::Ignored, "expired")); } crate::storage::BlockLinkState::DuplicateProposal => { log::warn!( "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self.local_device_id + self ); return Err(BuckyError::new( BuckyErrorCode::AlreadyExists, @@ -360,7 +377,7 @@ impl HotstuffRunner { crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", - self.local_device_id + self ); return Err(BuckyError::new( BuckyErrorCode::AlreadyExists, @@ -370,7 +387,7 @@ impl HotstuffRunner { crate::storage::BlockLinkState::Link(prev_block, proposals) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", - self.local_device_id, + self, block.height() ); @@ -381,7 +398,7 @@ impl HotstuffRunner { crate::storage::BlockLinkState::Pending => { log::warn!( "[hotstuff] local: {:?}, receive out-order block, expect height: {}, get height: {}.", - self.local_device_id, + self, self.store.header_height() + 3, block.height() ); @@ -404,7 +421,7 @@ impl HotstuffRunner { crate::storage::BlockLinkState::InvalidBranch => { log::warn!( "[hotstuff] local: {:?}, receive block in invalid branch.", - self.local_device_id + self ); return Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch")); } @@ -417,7 +434,7 @@ impl HotstuffRunner { .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, verify block {:?} failed, {:?}.", - self.local_device_id, + self, block.named_object().desc().object_id(), err ); @@ -499,11 +516,11 @@ impl HotstuffRunner { .is_proposal_finished(&proposal_exe_info.proposal, prev_block_id) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, check proposal {:?} in block {:?} with prev-block {:?} duplicate failed, {:?}." - , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id, err); + , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id, err); err })? { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." - , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id); + , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id); return Err(BuckyError::new(BuckyErrorCode::ErrorState, "duplicate proposal")) } @@ -514,7 +531,7 @@ impl HotstuffRunner { Some(receipt) => { let (receipt, _) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} decode receipt failed {:?}." - , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); + , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); err })?; @@ -535,7 +552,7 @@ impl HotstuffRunner { .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." - , self.local_device_id, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); + , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); err })? { @@ -543,7 +560,7 @@ impl HotstuffRunner { } else { log::warn!( "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", - self.local_device_id, + self, proposal_exe_info.proposal, prev_state_id, proposal_exe_info.result_state @@ -573,13 +590,14 @@ impl HotstuffRunner { log::info!( "[hotstuff] local: {:?}, will push new block {:?} to storage", - self.local_device_id, block.named_object().desc().object_id() + self, block.named_object().desc().object_id() ); + let debug_identify = self.debug_identify(); let new_header_block = self.store.push_block(block.clone()).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, push verified block {:?} to storage failed {:?}", - self.local_device_id, block.named_object().desc().object_id(), err + debug_identify, block.named_object().desc().object_id(), err ); err @@ -588,7 +606,7 @@ impl HotstuffRunner { if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", - self.local_device_id, header_block.named_object().desc().object_id() + self, header_block.named_object().desc().object_id() ); /** @@ -611,7 +629,7 @@ impl HotstuffRunner { .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self.local_device_id, block_id, err + self, block_id, err ); err })? @@ -627,7 +645,7 @@ impl HotstuffRunner { .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self.local_device_id, proposal.proposal, header_block.named_object().desc().object_id(), err + self, proposal.proposal, header_block.named_object().desc().object_id(), err ); err @@ -637,7 +655,7 @@ impl HotstuffRunner { let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { log::warn!( "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self.local_device_id, proposal.proposal, header_block.named_object().desc().object_id(), err + self, proposal.proposal, header_block.named_object().desc().object_id(), err ); err })?; @@ -670,14 +688,14 @@ impl HotstuffRunner { VoteThresholded::QC(qc) => { log::debug!( "[hotstuff] local: {:?}, the qc of block {:?} has received before", - self.local_device_id, block.named_object().desc().object_id() + self, block.named_object().desc().object_id() ); return self.process_block_qc(qc, block, remote).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( "[hotstuff] local: {:?}, the timeout-qc of block {:?} has received before", - self.local_device_id, block.named_object().desc().object_id() + self, block.named_object().desc().object_id() ); return self @@ -690,7 +708,7 @@ impl HotstuffRunner { if block.round() != self.round { log::debug!( "[hotstuff] local: {:?}, not my round {}, expect {}", - self.local_device_id, block.round(), self.round + self, block.round(), self.round ); // 不是我的投票round return Ok(()); @@ -698,12 +716,12 @@ impl HotstuffRunner { if let Some(vote) = self.make_vote(block).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", - self.local_device_id, block.named_object().desc().object_id(), block.round()); + self, block.named_object().desc().object_id(), block.round()); let next_leader = self.committee.get_leader(None, self.round + 1).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self.local_device_id, self.round + 1, err + self, self.round + 1, err ); err @@ -729,7 +747,7 @@ impl HotstuffRunner { let qc_round = qc.as_ref().map_or(0, |qc| qc.round); log::debug!("[hotstuff] local: {:?}, process_qc round {}", - self.local_device_id, qc_round); + self, qc_round); self.advance_round(qc_round).await; self.update_high_qc(qc); @@ -738,7 +756,7 @@ impl HotstuffRunner { async fn advance_round(&mut self, round: u64) { if round < self.round { log::debug!("[hotstuff] local: {:?}, round {} timeout expect {}", - self.local_device_id, round, self.round); + self, round, self.round); return; } @@ -750,11 +768,11 @@ impl HotstuffRunner { self.tc = None; log::info!("[hotstuff] local: {:?}, update round from {} to {}", - self.local_device_id, self.round, round + 1); + self, self.round, round + 1); } Err(err) => { log::warn!("[hotstuff] local: {:?}, get group before update round from {} to {} failed {:?}", - self.local_device_id, self.round, round + 1, err); + self, self.round, round + 1, err); } } } @@ -766,7 +784,7 @@ impl HotstuffRunner { self.high_qc = qc.clone(); log::info!("[hotstuff] local: {:?}, update high-qc from {} to {}", - self.local_device_id, cur_high_round, to_high_round); + self, cur_high_round, to_high_round); } } @@ -778,14 +796,14 @@ impl HotstuffRunner { .collect(); log::debug!("[hotstuff] local: {:?}, remove proposals: {:?}", - self.local_device_id, proposals); + self, proposals); self.proposal_consumer.remove_proposals(proposals).await } async fn notify_proposal_err(&self, proposal: &GroupProposal, err: BuckyError) { log::debug!("[hotstuff] local: {:?}, proposal {} failed {:?}", - self.local_device_id, proposal.desc().object_id(), err); + self, proposal.desc().object_id(), err); self.state_pusher .notify_proposal_err(proposal.clone(), err) @@ -795,7 +813,7 @@ impl HotstuffRunner { async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", - self.local_device_id, block.named_object().desc().object_id(), block.round(), self.store.last_vote_round()); + self, block.named_object().desc().object_id(), block.round(), self.store.last_vote_round()); return None; } @@ -816,7 +834,7 @@ impl HotstuffRunner { if !is_valid_round { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", - self.local_device_id, + self, block.named_object().desc().object_id(), block.round(), qc_round, block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); @@ -828,7 +846,7 @@ impl HotstuffRunner { Ok(is_latest) if is_latest => {} _ => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", - self.local_device_id, + self, block.named_object().desc().object_id()); return None; @@ -840,7 +858,7 @@ impl HotstuffRunner { Err(e) => { log::warn!( "[hotstuff] local: {:?}, signature for block-vote failed, block: {}, err: {}", - self.local_device_id, + self, block.named_object().desc().object_id(), e ); @@ -858,16 +876,30 @@ impl HotstuffRunner { async fn handle_vote( &mut self, vote: &HotstuffBlockQCVote, - block: Option<&GroupConsensusBlock>, + prev_block: Option<&GroupConsensusBlock>, remote: ObjectId, ) -> BuckyResult<()> { if vote.round < self.round { + log::warn!( + "[hotstuff] local: {:?}, receive timeout vote({}/{}/{:?}), local-round: {}", + self, + vote.block_id, vote.round, vote.prev_block_id, + self.round + ); return Ok(()); } - self.committee.verify_vote(vote).await?; + self.committee.verify_vote(vote).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, verify vote({}/{}/{:?}) failed {:?}", + self, + vote.block_id, vote.round, vote.prev_block_id, + err + ); + err + })?; - let block = match block { + let prev_block = match prev_block { Some(b) => Some(b.clone()), None => self .store @@ -875,24 +907,57 @@ impl HotstuffRunner { .map_or(None, |b| Some(b)), }; - if let Some((qc, block)) = self.vote_mgr.add_vote(vote.clone(), block).await? { + let is_prev_none = prev_block.is_none(); + let qc = self.vote_mgr.add_vote(vote.clone(), prev_block).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, add vote({}/{}/{:?}) prev-block: {} failed {:?}", + self, + vote.block_id, vote.round, vote.prev_block_id, + if is_prev_none {"None"} else {"Some"}, + err + ); + err + })?; + + if let Some((qc, block)) = qc { + log::info!( + "[hotstuff] local: {:?}, vote({}/{}/{:?}) prev-block: {} qc", + self, + vote.block_id, vote.round, vote.prev_block_id, + if is_prev_none {"None"} else {"Some"} + ); + self.process_block_qc(qc, &block, remote).await?; - } else if vote.round > self.round { - self.fetch_block(&vote.block_id, remote).await; + } else if vote.round > self.round && is_prev_none { + self.fetch_block(&vote.block_id, remote).await?; } - Ok(()) } async fn process_block_qc( &mut self, qc: HotstuffBlockQC, - block: &GroupConsensusBlock, + prev_block: &GroupConsensusBlock, remote: ObjectId, ) -> BuckyResult<()> { + let qc_block_id = qc.block_id; + let qc_round = qc.round; + let qc_prev_block_id = qc.prev_block_id; + self.process_qc(&Some(qc)).await; - if self.local_device_id == self.committee.get_leader(None, self.round).await? { + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader for vote-qc({}/{}/{:?}) with round {} failed {:?}", + self, + qc_block_id, qc_round, qc_prev_block_id, + self.round, + err + ); + err + })?; + + if self.local_device_id == new_leader { self.generate_block(None).await; } Ok(()) @@ -903,9 +968,25 @@ impl HotstuffRunner { timeout: &HotstuffTimeoutVote, remote: ObjectId, ) -> BuckyResult<()> { - if timeout.round < self.round - || timeout.high_qc.as_ref().map_or(0, |qc| qc.round) >= timeout.round - { + log::debug!( + "[hotstuff] local: {:?}, handle_timeout: {:?}, qc: {:?}, voter: {:?}, remote: {:?},", + self, + timeout.round, + timeout.high_qc.as_ref().map(|qc| format!( + "{:?}/{:?}/{:?}/{:?}", + qc.block_id, + qc.round, + qc.prev_block_id, + qc.votes + .iter() + .map(|v| v.voter.to_string()) + .collect::>() + )), + timeout.voter, + remote + ); + + if timeout.round < self.round { if let Some(tc) = self.tc.as_ref() { // if there is a timeout-qc, notify the remote to advance the round if tc.round + 1 == self.round { @@ -921,10 +1002,29 @@ impl HotstuffRunner { return Ok(()); } + let high_qc_round = timeout.high_qc.as_ref().map_or(0, |qc| qc.round); + if high_qc_round >= timeout.round { + log::warn!( + "[hotstuff] local: {:?}, handle_timeout: {:?}, ignore for high-qc(round={}) invalid", + self, + timeout.round, + high_qc_round + ); + return Ok(()); + } + let block = match timeout.high_qc.as_ref() { Some(qc) => match self.store.find_block_in_cache(&qc.block_id) { Ok(block) => Some(block), - Err(_) => { + Err(err) => { + log::warn!( + "[hotstuff] local: {:?}, handle_timeout: {:?}, find qc-block {} failed {:?}", + self, + timeout.round, + qc.block_id, + err + ); + self.vote_mgr.add_waiting_timeout(timeout.clone()); self.fetch_block(&qc.block_id, remote).await; return Ok(()); @@ -935,15 +1035,33 @@ impl HotstuffRunner { self.committee .verify_timeout(timeout, block.as_ref()) - .await?; + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_timeout: {:?}, verify failed {:?}", + self, + timeout.round, + err + ); + + err + })?; self.process_qc(&timeout.high_qc).await; - if let Some((tc, max_high_qc_block)) = self + let tc = self .vote_mgr .add_timeout(timeout.clone(), block.as_ref()) - .await? - { + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_timeout: {:?}, check tc failed {:?}", + self, + timeout.round, + err + ); + err + })?; + + if let Some((tc, max_high_qc_block)) = tc { self.process_timeout_qc(tc, max_high_qc_block.as_ref()) .await?; } @@ -955,14 +1073,44 @@ impl HotstuffRunner { tc: HotstuffTimeout, max_high_qc_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { + log::debug!( + "[hotstuff] local: {:?}, process_timeout_qc: {:?}, voter: {:?}, high-qc block: {:?},", + self, + tc.round, + tc.votes + .iter() + .map(|vote| format!("{:?}/{:?}", vote.high_qc_round, vote.voter,)) + .collect::>(), + max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) + ); + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - if self.local_device_id == self.committee.get_leader(None, self.round).await? { + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", + self, + tc.round, + err + ); + + err + })?; + if self.local_device_id == new_leader { self.generate_block(Some(tc)).await; Ok(()) } else { - let latest_group = self.committee.get_group(None).await?; + let latest_group = self.committee.get_group(None).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get group failed {:?}", + self, + tc.round, + err + ); + err + })?; + self.broadcast(HotstuffMessage::Timeout(tc), &latest_group) .await } @@ -974,13 +1122,39 @@ impl HotstuffRunner { .iter() .max_by(|high_qc_l, high_qc_r| high_qc_l.high_qc_round.cmp(&high_qc_r.high_qc_round)); + log::debug!( + "[hotstuff] local: {:?}, handle_tc: {:?}, voter: {:?}, remote: {:?}, max-qc: {:?}", + self, + tc.round, + tc.votes + .iter() + .map(|vote| format!("{:?}/{:?}", vote.high_qc_round, vote.voter,)) + .collect::>(), + remote, + max_high_qc.as_ref().map(|qc| qc.high_qc_round) + ); + let max_high_qc = if let Some(max_high_qc) = max_high_qc { max_high_qc } else { return Ok(()); }; - if tc.round < self.round || max_high_qc.high_qc_round >= tc.round { + if tc.round < self.round { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} ignore for round timeout", + self, + tc.round, + ); + } + + if max_high_qc.high_qc_round >= tc.round { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} ignore for high-qc round {} invalid", + self, + tc.round, max_high_qc.high_qc_round + ); + return Ok(()); } @@ -992,7 +1166,14 @@ impl HotstuffRunner { .find_block_in_cache_by_round(max_high_qc.high_qc_round) { Ok(block) => block, - Err(_) => { + Err(err) => { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} find prev-block by round {} failed {:?}", + self, + tc.round, max_high_qc.high_qc_round, + err + ); + // 同步前序block let max_round_block = self.store.block_with_max_round(); self.synchronizer.sync_with_round( @@ -1006,26 +1187,54 @@ impl HotstuffRunner { Some(block) }; - self.committee.verify_tc(tc, block.as_ref()).await?; + self.committee.verify_tc(tc, block.as_ref()).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} verify tc failed {:?}", + self, + tc.round, + err + ); + err + })?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - if self.local_device_id == self.committee.get_leader(None, self.round).await? { + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} get new leader failed {:?}", + self, + tc.round, + err + ); + err + })?; + + if self.local_device_id == new_leader { self.generate_block(Some(tc.clone())).await; } Ok(()) } async fn local_timeout_round(&mut self) -> BuckyResult<()> { + log::debug!( + "[hotstuff] local: {:?}, local_timeout_round", + self, + ); + let latest_group = match self.committee.get_group(None).await { Ok(group) => { self.timer.reset(group.consensus_interval()); group } - Err(e) => { + Err(err) => { + log::warn!( + "[hotstuff] local: {:?}, local_timeout_round get latest group failed {:?}", + self, err + ); + self.timer.reset(HOTSTUFF_TIMEOUT_DEFAULT); - return Err(e); + return Err(err); } }; @@ -1035,7 +1244,13 @@ impl HotstuffRunner { self.local_device_id, &self.signer, ) - .await?; + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", + self, err + ); + err + })?; self.store.set_last_vote_round(self.round).await?; @@ -1048,16 +1263,40 @@ impl HotstuffRunner { } async fn generate_block(&mut self, tc: Option) -> BuckyResult<()> { - let mut proposals = self.proposal_consumer.query_proposals().await?; - proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); - let now = SystemTime::now(); + log::debug!( + "[hotstuff] local: {:?}, generate_block with qc {:?} and tc {:?}, now: {:?}", + self, + self.high_qc.as_ref().map(|qc| format!("{}/{}/{:?}", qc.block_id, qc.round, qc.votes.iter().map(|v| v.voter).collect::>())), + tc.as_ref().map(|tc| format!("{}/{:?}", tc.round, tc.votes.iter().map(|v| v.voter).collect::>())), + now + ); + + let mut proposals = self.proposal_consumer.query_proposals().await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, generate_block query proposal failed {:?}", + self, + err + ); + err + })?; + + proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); + let pre_block = match self.high_qc.as_ref() { Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), None => None, }; - let latest_group = self.committee.get_group(None).await?; + let latest_group = self.committee.get_group(None).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, generate_block get latest group failed {:?}", + self, + err + ); + + err + })?; let mut remove_proposals = vec![]; // let mut dup_proposals = vec![]; @@ -1120,6 +1359,17 @@ impl HotstuffRunner { }; } + if time_adjust_proposals.len() > 0 { + log::warn!( + "[hotstuff] local: {:?}, generate_block timestamp err {:?}", + self, + time_adjust_proposals.iter().map(|proposal| { + let desc = proposal.desc(); + (desc.object_id(), desc.owner(), bucky_time_to_system_time(desc.create_time())) + }).collect::>() + ); + } + for proposal in time_adjust_proposals { // timestamp is error self.notify_proposal_err( @@ -1129,6 +1379,22 @@ impl HotstuffRunner { .await; } + if timeout_proposals.len() > 0 { + log::warn!( + "[hotstuff] local: {:?}, generate_block timeout {:?}", + self, + timeout_proposals.iter().map(|proposal| { + let desc = proposal.desc(); + ( + desc.object_id(), + desc.owner(), + bucky_time_to_system_time(desc.create_time()), + proposal.effective_ending().as_ref().map(|ending| bucky_time_to_system_time(*ending)) + ) + }).collect::>() + ); + } + for proposal in timeout_proposals { // has timeout self.notify_proposal_err( @@ -1138,11 +1404,34 @@ impl HotstuffRunner { .await; } + if failed_proposals.len() > 0 { + log::warn!( + "[hotstuff] local: {:?}, generate_block failed proposal {:?}", + self, + failed_proposals.iter().map(|(proposal, err)| { + let desc = proposal.desc(); + ( + desc.object_id(), + desc.owner(), + err.clone() + ) + }).collect::>() + ); + } + for (proposal, err) in failed_proposals { // failed self.notify_proposal_err(&proposal, err).await; } + if remove_proposals.len() > 0 { + log::warn!( + "[hotstuff] local: {:?}, generate_block finish proposal {:?}", + self, + remove_proposals + ); + } + self.proposal_consumer .remove_proposals(remove_proposals) .await; @@ -1151,6 +1440,10 @@ impl HotstuffRunner { .try_wait_proposals(executed_proposals.as_slice(), &pre_block) .await { + log::debug!( + "[hotstuff] local: {:?}, generate_block empty block, will ignore", + self, + ); return Ok(()); } @@ -1183,7 +1476,22 @@ impl HotstuffRunner { self.local_id, ); - self.sign_block(&mut block).await?; + log::debug!( + "[hotstuff] local: {:?}, generate_block new block {}", + self, + block.named_object().desc().object_id() + ); + + self.sign_block(&mut block).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, generate_block new block {} sign failed {:?}", + self, + block.named_object().desc().object_id(), + err + ); + + err + })?; self.tx_message .send((HotstuffMessage::Block(block.clone()), self.local_id)) @@ -1236,7 +1544,14 @@ impl HotstuffRunner { let mut will_wait_proposals = false; if executed_proposals.len() == 0 { match pre_block.as_ref() { - None => will_wait_proposals = true, + None => { + log::warn!( + "[hotstuff] local: {:?}, new empty block will ignore for first block is empty.", + self, + ); + + will_wait_proposals = true + }, Some(pre_block) => { if pre_block.proposals().len() == 0 { match pre_block.prev_block_id() { @@ -1244,13 +1559,35 @@ impl HotstuffRunner { let pre_pre_block = match self.store.find_block_in_cache(pre_pre_block_id) { Ok(pre_pre_block) => pre_pre_block, - Err(_) => return false, + Err(err) => { + log::warn!( + "[hotstuff] local: {:?}, new empty block will generate for find prev-block {} failed {:?}", + self, + pre_pre_block_id, + err + ); + return false; + } }; if pre_pre_block.proposals().len() == 0 { + log::warn!( + "[hotstuff] local: {:?}, new empty block will ignore for 2 prev-block({}/{}) is empty", + self, + pre_pre_block_id, pre_block.named_object().desc().object_id() + ); + will_wait_proposals = true; } } - None => will_wait_proposals = true, + None => { + log::warn!( + "[hotstuff] local: {:?}, new empty block will ignore for prev-prev-block is None and prev-block is {}, maybe is a bug.", + self, + pre_block.named_object().desc().object_id() + ); + + will_wait_proposals = true; + } } } } @@ -1374,6 +1711,16 @@ impl HotstuffRunner { } } }; + + log::debug!( + "[hotstuff] local: {:?}, new message response. result: {:?}", + self, + result + ); } } + + fn debug_identify(&self) -> String { + format!("{:?}-{:?}-{}", self.rpath, self.local_device_id, self.round) + } } From d367d80b4b2edf01296e9d98c0db7839b9f58841 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Feb 2023 20:08:50 +0800 Subject: [PATCH 050/553] split some long function --- src/component/cyfs-base/src/objects/group.rs | 9 +- .../src/consensus/hotstuff/hotstuff.rs | 469 ++++++++++-------- .../src/consensus/vote/committee.rs | 11 +- src/tests/group-example/src/main.rs | 2 + 4 files changed, 279 insertions(+), 212 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index dda6c779d..eb27cd4fd 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -94,6 +94,8 @@ pub type GroupDesc = NamedObjectDesc; pub type GroupId = NamedObjectId; pub type Group = NamedObjectBase; +pub const GROUP_DEFAULT_CONSENSUS_INTERVAL: u64 = 5000; // default 5000 ms + impl GroupDesc { pub fn group_id(&self) -> GroupId { GroupId::try_from(self.calculate_id()).unwrap() @@ -220,7 +222,12 @@ impl Group { } pub fn consensus_interval(&self) -> u64 { - self.common().consensus_interval + let interval = self.common().consensus_interval; + if interval == 0 { + GROUP_DEFAULT_CONSENSUS_INTERVAL + } else { + interval + } } pub fn set_consensus_interval(&mut self, interval: u64) { diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 9d3492255..832855e5d 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -23,7 +23,6 @@ use crate::{ /** * TODO: generate empty block when the 'Node' is synchronizing - * TODO: use admins instead ood_list */ pub(crate) struct Hotstuff { @@ -311,121 +310,22 @@ impl HotstuffRunner { { // check leader - let leader = self - .committee - .get_leader(Some(block.group_chunk_id()), block.round()) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", - self, - block.group_chunk_id(), block.round(), - err - ); - - err - })?; - let leader_owner = self - .non_driver - .get_device(&leader) - .await - .map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader by id {:?} failed, {:?}.", - self, - leader, - err - ); + let leader_owner = self.get_leader_owner(Some(block.group_chunk_id()), block.round()).await?; - err - })? - .desc() - .owner() - .clone(); - match leader_owner.as_ref() { - Some(leader_owner) if leader_owner == block.owner() => {} - _ => { - log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", - self, - block.named_object().desc().object_id(), - block.owner(), - leader_owner - ); - return Err(BuckyError::new(BuckyErrorCode::Ignored, "invalid leader")); - } + if &leader_owner != block.owner() { + log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", + self, + block.named_object().desc().object_id(), + block.owner(), + leader_owner + ); + return Err(BuckyError::new(BuckyErrorCode::Ignored, "invalid leader")); } } - let (prev_block, proposals) = { - match self.store.block_linked(block).await? { - crate::storage::BlockLinkState::Expired => { - log::warn!( - "[hotstuff] local: {:?}, receive block expired.", - self - ); - return Err(BuckyError::new(BuckyErrorCode::Ignored, "expired")); - } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - )); - } - crate::storage::BlockLinkState::Duplicate => { - log::warn!( - "[hotstuff] local: {:?}, receive duplicate block.", - self - ); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate block", - )); - } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { - log::debug!( - "[hotstuff] local: {:?}, receive in-order block, height: {}.", - self, - block.height() - ); - - // 顺序连接状态 - Self::check_empty_block_result_state_with_prev(block, &prev_block)?; - (prev_block, proposals) - } - crate::storage::BlockLinkState::Pending => { - log::warn!( - "[hotstuff] local: {:?}, receive out-order block, expect height: {}, get height: {}.", - self, - self.store.header_height() + 3, - block.height() - ); - - // 乱序,同步 - if block.height() <= self.store.header_height() + 3 { - self.fetch_block(block.prev_block_id().unwrap(), remote) - .await; - } - - let max_round_block = self.store.block_with_max_round(); - self.synchronizer.push_outorder_block( - block.clone(), - max_round_block.map_or(1, |block| block.height() + 1), - remote, - ); - - return Ok(()); - } - crate::storage::BlockLinkState::InvalidBranch => { - log::warn!( - "[hotstuff] local: {:?}, receive block in invalid branch.", - self - ); - return Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch")); - } - } + let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err }; self.committee @@ -579,6 +479,126 @@ impl HotstuffRunner { Ok(()) } + async fn get_leader_owner(&self, group_chunk_id: Option<&ObjectId>, round: u64) -> BuckyResult { + let leader = self + .committee + .get_leader(group_chunk_id, round) + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", + self, + group_chunk_id, round, + err + ); + + err + })?; + + let leader_owner = self + .non_driver + .get_device(&leader) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader by id {:?} failed, {:?}.", + self, + leader, + err + ); + + err + })? + .desc() + .owner() + .clone(); + + match leader_owner { + Some(owner) => Ok(owner), + None => { + log::warn!("[hotstuff] local: {:?}, a owner must be set to the device {}", + self, + leader + ); + Err(BuckyError::new(BuckyErrorCode::InvalidTarget, "no owner for device")) + } + } + } + + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + match self.store.block_linked(block).await + .map_err(|err| Err(err))? { + + crate::storage::BlockLinkState::Expired => { + log::warn!( + "[hotstuff] local: {:?}, receive block expired.", + self + ); + Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) + } + crate::storage::BlockLinkState::DuplicateProposal => { + log::warn!( + "[hotstuff] local: {:?}, receive block with duplicate proposal.", + self + ); + Err (Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "duplicate proposal", + ))) + } + crate::storage::BlockLinkState::Duplicate => { + log::warn!( + "[hotstuff] local: {:?}, receive duplicate block.", + self + ); + Err( Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "duplicate block", + ))) + } + crate::storage::BlockLinkState::Link(prev_block, proposals) => { + log::debug!( + "[hotstuff] local: {:?}, receive in-order block, height: {}.", + self, + block.height() + ); + + // 顺序连接状态 + Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; + Ok((prev_block, proposals)) + } + crate::storage::BlockLinkState::Pending => { + log::warn!( + "[hotstuff] local: {:?}, receive out-order block, expect height: {}, get height: {}.", + self, + self.store.header_height() + 3, + block.height() + ); + + // 乱序,同步 + if block.height() <= self.store.header_height() + 3 { + self.fetch_block(block.prev_block_id().unwrap(), remote) + .await; + } + + let max_round_block = self.store.block_with_max_round(); + self.synchronizer.push_outorder_block( + block.clone(), + max_round_block.map_or(1, |block| block.height() + 1), + remote, + ); + + Err(Ok(())) + } + crate::storage::BlockLinkState::InvalidBranch => { + log::warn!( + "[hotstuff] local: {:?}, receive block in invalid branch.", + self + ); + Err( Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch"))) + } + } + } + async fn process_block( &mut self, block: &GroupConsensusBlock, @@ -615,73 +635,7 @@ impl HotstuffRunner { * */ self.cleanup_proposal(&header_block).await; - let (_, qc_block) = self - .store - .pre_commits() - .iter() - .next() - .expect("the pre-commit block must exist."); - - let pre_state_id = match header_block.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; - - for proposal in header_block.proposals() { - let proposal_obj = self - .non_driver - .get_proposal(&proposal.proposal, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, header_block.named_object().desc().object_id(), err - ); - - err - })?; - let receipt = match proposal.receipt.as_ref() { - Some(receipt) => { - let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, header_block.named_object().desc().object_id(), err - ); - err - })?; - assert_eq!(remain.len(), 0); - Some(receipt) - } - None => None, - }; - - self.delegate - .on_commited( - &proposal_obj, - pre_state_id, - &ExecuteResult { - result_state_id: header_block.result_state_id().clone(), - receipt, - context: proposal.context.clone(), - }, - &header_block, - ) - .await; - } - - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await + self.notify_block_committed(header_block).await; } match self.vote_mgr.add_voting_block(block).await { @@ -743,6 +697,78 @@ impl HotstuffRunner { Ok(()) } + async fn notify_block_committed(&self, new_header: GroupConsensusBlock) -> BuckyResult<()> { + let (_, qc_block) = self + .store + .pre_commits() + .iter() + .next() + .expect("the pre-commit block must exist."); + + let pre_state_id = match new_header.prev_block_id() { + Some(block_id) => self + .non_driver + .get_block(block_id, None) + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", + self, block_id, err + ); + err + })? + .result_state_id() + .clone(), + None => None, + }; + + for proposal in new_header.proposals() { + let proposal_obj = self + .non_driver + .get_proposal(&proposal.proposal, None) + .await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", + self, proposal.proposal, new_header.named_object().desc().object_id(), err + ); + + err + })?; + let receipt = match proposal.receipt.as_ref() { + Some(receipt) => { + let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", + self, proposal.proposal, new_header.named_object().desc().object_id(), err + ); + err + })?; + assert_eq!(remain.len(), 0); + Some(receipt) + } + None => None, + }; + + self.delegate + .on_commited( + &proposal_obj, + pre_state_id, + &ExecuteResult { + result_state_id: new_header.result_state_id().clone(), + receipt, + context: proposal.context.clone(), + }, + &new_header, + ) + .await; + } + + self.state_pusher + .notify_block_commit(new_header, qc_block.clone()) + .await; + + Ok(()) + } + async fn process_qc(&mut self, qc: &Option) { let qc_round = qc.as_ref().map_or(0, |qc| qc.round); @@ -879,6 +905,12 @@ impl HotstuffRunner { prev_block: Option<&GroupConsensusBlock>, remote: ObjectId, ) -> BuckyResult<()> { + log::debug!("[hotstuff] local: {:?}, handle_vote: {:?}/{:?}, prev: {:?}, voter: {:?}, remote: {:?},", + self, + vote.block_id, vote.round, + vote.prev_block_id, + vote.voter, remote); + if vote.round < self.round { log::warn!( "[hotstuff] local: {:?}, receive timeout vote({}/{}/{:?}), local-round: {}", @@ -1284,7 +1316,7 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); - let pre_block = match self.high_qc.as_ref() { + let prev_block = match self.high_qc.as_ref() { Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), None => None, }; @@ -1304,7 +1336,7 @@ impl HotstuffRunner { let mut timeout_proposals = vec![]; let mut executed_proposals = vec![]; let mut failed_proposals = vec![]; - let mut result_state_id = match pre_block.as_ref() { + let mut result_state_id = match prev_block.as_ref() { Some(block) => block.result_state_id().clone(), None => self.store.dec_state_id().clone(), }; @@ -1359,6 +1391,36 @@ impl HotstuffRunner { }; } + self.notify_adjust_time_proposals(time_adjust_proposals).await; + self.notify_timeout_proposals(timeout_proposals).await; + self.notify_failed_proposals(failed_proposals).await; + self.remove_pending_proposals(remove_proposals).await; + + if self + .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .await + { + log::debug!( + "[hotstuff] local: {:?}, generate_block empty block, will ignore", + self, + ); + return Ok(()); + } + + let block = self.package_block_with_proposals(executed_proposals, &latest_group, result_state_id, &prev_block, tc).await?; + + self.tx_message + .send((HotstuffMessage::Block(block.clone()), self.local_id)) + .await; + + self.broadcast(HotstuffMessage::Block(block), &latest_group) + .await; + + self.rx_proposal_waiter = None; + Ok(()) + } + + async fn notify_adjust_time_proposals(&self, time_adjust_proposals: Vec) { if time_adjust_proposals.len() > 0 { log::warn!( "[hotstuff] local: {:?}, generate_block timestamp err {:?}", @@ -1378,7 +1440,9 @@ impl HotstuffRunner { ) .await; } + } + async fn notify_timeout_proposals(&self, timeout_proposals: Vec) { if timeout_proposals.len() > 0 { log::warn!( "[hotstuff] local: {:?}, generate_block timeout {:?}", @@ -1403,7 +1467,9 @@ impl HotstuffRunner { ) .await; } + } + async fn notify_failed_proposals(&self, failed_proposals: Vec<(GroupProposal, BuckyError)>) { if failed_proposals.len() > 0 { log::warn!( "[hotstuff] local: {:?}, generate_block failed proposal {:?}", @@ -1423,30 +1489,29 @@ impl HotstuffRunner { // failed self.notify_proposal_err(&proposal, err).await; } + } - if remove_proposals.len() > 0 { + async fn remove_pending_proposals(&self, pending_proposals: Vec) { + if pending_proposals.len() > 0 { log::warn!( "[hotstuff] local: {:?}, generate_block finish proposal {:?}", self, - remove_proposals + pending_proposals ); } self.proposal_consumer - .remove_proposals(remove_proposals) + .remove_proposals(pending_proposals) .await; + } - if self - .try_wait_proposals(executed_proposals.as_slice(), &pre_block) - .await - { - log::debug!( - "[hotstuff] local: {:?}, generate_block empty block, will ignore", - self, - ); - return Ok(()); - } - + async fn package_block_with_proposals(&self, + executed_proposals: Vec<(GroupProposal, ExecuteResult)>, + group: &Group, + result_state_id: Option, + prev_block: &Option, + tc: Option + ) -> BuckyResult { let proposals_param = executed_proposals .into_iter() .map(|(proposal, exe_result)| GroupConsensusBlockProposal { @@ -1457,7 +1522,7 @@ impl HotstuffRunner { }) .collect(); - let group_chunk_id = ChunkMeta::from(&latest_group) + let group_chunk_id = ChunkMeta::from(group) .to_chunk() .await .unwrap() @@ -1467,7 +1532,7 @@ impl HotstuffRunner { self.rpath.clone(), proposals_param, result_state_id, - pre_block.map_or(0, |b| b.height()) + 1, + prev_block.as_ref().map_or(0, |b| b.height()) + 1, ObjectId::default(), // TODO: meta block id self.round, group_chunk_id.object_id(), @@ -1493,15 +1558,7 @@ impl HotstuffRunner { err })?; - self.tx_message - .send((HotstuffMessage::Block(block.clone()), self.local_id)) - .await; - - self.broadcast(HotstuffMessage::Block(block), &latest_group) - .await; - - self.rx_proposal_waiter = None; - Ok(()) + Ok(block) } async fn sign_block(&self, block: &mut GroupConsensusBlock) -> BuckyResult<()> { diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index a9f9d7e3b..05284f2a9 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -163,11 +163,12 @@ impl Committee { prev_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { let highest_round = tc.votes.iter().map(|v| v.high_qc_round).max(); - if highest_round != prev_block.map(|b| b.round()) { - log::warn!("[group committee] hightest round is not match with prev-block in tc"); + let prev_round = prev_block.map(|b| b.round()); + if highest_round != prev_round { + log::warn!("[group committee] hightest round is not match with prev-block in tc, highest_round: {:?}, prev_round: {:?}", highest_round, prev_round); return Err(BuckyError::new( BuckyErrorCode::NotMatch, - "rount not match in tc", + "round not match in tc", )); } @@ -219,10 +220,10 @@ impl Committee { prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc"); + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, - "rount not match in qc", + "round not match in qc", )); } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index c5e8e8294..f891769d1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -186,6 +186,8 @@ mod Common { .collect(), ); + group.set_consensus_interval(5000); + log::info!("create group: {:?}", group.desc().object_id()); group From e7534810c15fddba78a88d3b95c0eda4b5d0b521 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Feb 2023 20:43:16 +0800 Subject: [PATCH 051/553] fix panic --- src/component/cyfs-group/src/helper/timer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-group/src/helper/timer.rs b/src/component/cyfs-group/src/helper/timer.rs index 022c4b5e4..3c9a35cce 100644 --- a/src/component/cyfs-group/src/helper/timer.rs +++ b/src/component/cyfs-group/src/helper/timer.rs @@ -35,7 +35,8 @@ impl Timer { } pub async fn wait_next(&mut self) { - self.sleep.take().unwrap().await; + let sleep = self.sleep.take().unwrap(); self.reset(self.duration); + sleep.await; } } From 394f20167cecb577c9f32d122bda1dfa1603be20 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 13:13:19 +0800 Subject: [PATCH 052/553] log for package --- .../src/group/group_consensus_block.rs | 28 ++- .../cyfs-group/src/network/listener.rs | 6 + .../cyfs-group/src/network/sender.rs | 26 ++- .../cyfs-group/src/objects/protocol.rs | 194 +++++++++++++++++- 4 files changed, 238 insertions(+), 16 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index e7e808ef5..83de4f1da 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -183,7 +183,10 @@ type GroupConsensusBlockBuilder = pub type GroupConsensusBlockId = NamedObjectId; #[derive(Clone)] -pub struct GroupConsensusBlock(NamedObjectBase, Arc); +pub struct GroupConsensusBlock( + NamedObjectBase, + Arc<(AtomicU8, GroupConsensusBlockId)>, +); const BLOCK_CHECK_STATE_NONE: u8 = 0; const BLOCK_CHECK_STATE_SUCC: u8 = 1; @@ -227,6 +230,7 @@ pub trait GroupConsensusBlockObject { fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; + fn block_id(&self) -> &GroupConsensusBlockId; fn meta_block_id(&self) -> &ObjectId; fn prev_block_id(&self) -> Option<&ObjectId>; fn owner(&self) -> &ObjectId; @@ -269,19 +273,23 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { .owner(owner) .build(); - Self(block, Arc::new(AtomicU8::new(BLOCK_CHECK_STATE_SUCC))) + let block_id = GroupConsensusBlockId::try_from(block.desc().object_id()).unwrap(); + Self( + block, + Arc::new((AtomicU8::new(BLOCK_CHECK_STATE_SUCC), block_id)), + ) } fn check(&self) -> bool { - let state = self.1.load(Ordering::SeqCst); + let state = self.1 .0.load(Ordering::SeqCst); if state == BLOCK_CHECK_STATE_NONE { let desc = self.0.desc().content(); let body = self.0.body().as_ref().unwrap().content(); if body.hash() != desc.body_hash { - self.1.store(BLOCK_CHECK_STATE_FAIL, Ordering::SeqCst); + self.1 .0.store(BLOCK_CHECK_STATE_FAIL, Ordering::SeqCst); false } else { - self.1.store(BLOCK_CHECK_STATE_SUCC, Ordering::SeqCst); + self.1 .0.store(BLOCK_CHECK_STATE_SUCC, Ordering::SeqCst); true } } else { @@ -309,6 +317,10 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { desc.height } + fn block_id(&self) -> &GroupConsensusBlockId { + &self.1 .1 + } + fn meta_block_id(&self) -> &ObjectId { let desc = self.0.desc().content(); &desc.meta_block_id @@ -370,8 +382,12 @@ impl RawEncode for GroupConsensusBlock { impl<'de> RawDecode<'de> for GroupConsensusBlock { fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { let (obj, remain) = NamedObjectBase::::raw_decode(buf)?; + let block_id = GroupConsensusBlockId::try_from(obj.desc().object_id()).unwrap(); Ok(( - Self(obj, Arc::new(AtomicU8::new(BLOCK_CHECK_STATE_NONE))), + Self( + obj, + Arc::new((AtomicU8::new(BLOCK_CHECK_STATE_NONE), block_id)), + ), remain, )) } diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6124a9cb5..34061260c 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -20,6 +20,12 @@ impl Listener { let remote = pkg.source.remote.object_id().clone(); if let Ok((pkg, remain)) = HotstuffPackage::raw_decode(pkg.data.as_slice()) { + log::debug!( + "[group-listener] {:?} recv message from {:?}, msg: {:?}", + pkg.rpath(), + remote, + pkg + ); assert_eq!(remain.len(), 0); processor.on_message(pkg, remote).await; } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 42887da8b..66806e011 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -29,15 +29,6 @@ impl Sender { rpath: GroupRPath, to: &ObjectId, ) { - let pkg = HotstuffPackage::from_msg(msg, rpath); - let len = pkg.raw_measure(&None).unwrap(); - let mut buf = Vec::with_capacity(len); - buf.resize(len, 0); - let remain = pkg.raw_encode(buf.as_mut_slice(), &None).unwrap(); - assert_eq!(remain.len(), 0); - - let mut options = DatagramOptions::default(); - let remote = match to.obj_type_code() { cyfs_base::ObjectTypeCode::Device => DeviceId::try_from(to).unwrap(), cyfs_base::ObjectTypeCode::People => { @@ -53,6 +44,23 @@ impl Sender { _ => panic!("invalid remote type: {:?}", to.obj_type_code()), }; + log::debug!( + "[group-sender] {:?} post message to {:?}, msg: {:?}", + rpath, + remote, + msg + ); + + let pkg = HotstuffPackage::from_msg(msg, rpath); + + let len = pkg.raw_measure(&None).unwrap(); + let mut buf = Vec::with_capacity(len); + buf.resize(len, 0); + let remain = pkg.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + + let mut options = DatagramOptions::default(); + self.datagram .send_to(buf.as_slice(), &mut options, &remote, self.vport); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index f4a868190..efed7d9f6 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,6 +2,8 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } +use std::result; + use cyfs_base::*; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, @@ -91,7 +93,7 @@ pub(crate) enum HotstuffMessage { TimeoutVote(HotstuffTimeoutVote), Timeout(cyfs_core::HotstuffTimeout), - SyncRequest(SyncBound, SyncBound), + SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) @@ -107,6 +109,91 @@ pub(crate) enum HotstuffMessage { VerifiableState(String, BuckyResult), } +impl std::fmt::Debug for HotstuffMessage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Block(block) => { + write!( + f, + "HotstuffMessage::Block({}/{})", + block.block_id(), + block.round() + ) + } + Self::BlockVote(vote) => { + write!( + f, + "HotstuffMessage::BlockVote({}/{})", + vote.block_id, vote.round + ) + } + Self::TimeoutVote(vote) => { + write!( + f, + "HotstuffMessage::TimeoutVote({}/{})", + vote.round, vote.voter + ) + } + Self::Timeout(tc) => { + write!( + f, + "HotstuffMessage::Timeout({}/{:?})", + tc.round, + tc.votes.iter().map(|v| v.voter).collect::>() + ) + } + Self::SyncRequest(min, max) => { + write!(f, "HotstuffMessage::SyncRequest([{:?}-{:?}])", min, max) + } + Self::StateChangeNotify(block, qc) => { + write!( + f, + "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + } + Self::LastStateRequest => { + write!(f, "HotstuffMessage::LastStateRequest",) + } + Self::ProposalResult(proposal_id, result) => { + write!( + f, + "HotstuffMessage::ProposalResult({}, {:?})", + proposal_id, + result.as_ref().map_or_else( + |err| { Err(err) }, + |(obj, block, qc)| { + let ok = format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ); + Ok(ok) + } + ) + ) + } + Self::QueryState(sub_path) => { + write!(f, "HotstuffMessage::QueryState({})", sub_path) + } + Self::VerifiableState(sub_path, result) => { + write!( + f, + "HotstuffMessage::VerifiableState({}, {:?})", + sub_path, + result.as_ref().map(|status| unimplemented!()) + ) + } + } + } +} + const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; @@ -136,6 +223,111 @@ pub(crate) enum HotstuffPackage { VerifiableState(ProtocolAddress, String, BuckyResult), } +impl std::fmt::Debug for HotstuffPackage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Block(block) => { + write!( + f, + "HotstuffPackage::Block({}/{})", + block.block_id(), + block.round() + ) + } + Self::BlockVote(_, vote) => { + write!( + f, + "HotstuffPackage::BlockVote({}/{})", + vote.block_id, vote.round + ) + } + Self::TimeoutVote(_, vote) => { + write!( + f, + "HotstuffPackage::TimeoutVote({}/{})", + vote.round, vote.voter + ) + } + Self::Timeout(_, tc) => { + write!( + f, + "HotstuffPackage::Timeout({}/{:?})", + tc.round, + tc.votes.iter().map(|v| v.voter).collect::>() + ) + } + Self::SyncRequest(_, min, max) => { + write!(f, "HotstuffPackage::SyncRequest([{:?}-{:?}])", min, max) + } + Self::StateChangeNotify(block, qc) => { + write!( + f, + "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + } + Self::LastStateRequest(_) => { + write!(f, "HotstuffPackage::LastStateRequest",) + } + Self::ProposalResult(proposal_id, result) => { + write!( + f, + "HotstuffPackage::ProposalResult({}, {:?})", + proposal_id, + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |(obj, block, qc)| { + let ok = format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ); + Ok(ok) + } + ) + ) + } + Self::QueryState(_, sub_path) => { + write!(f, "HotstuffPackage::QueryState({})", sub_path) + } + Self::VerifiableState(_, sub_path, result) => { + write!( + f, + "HotstuffPackage::VerifiableState({}, {:?})", + sub_path, + result.as_ref().map(|status| unimplemented!()) + ) + } + } + } +} + +impl HotstuffPackage { + pub(crate) fn rpath(&self) -> &GroupRPath { + match self { + HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), + HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), + HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), + HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), + HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), + HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |(_, block, _)| block.r_path(), + ), + HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + } + } +} + fn encode_with_length<'a, O: RawEncode>( buf: &'a mut [u8], obj: &O, From 5344f50aefa47d0146952deac3368dbd7f6c8179 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 19:06:18 +0800 Subject: [PATCH 053/553] fix: timer --- .../src/consensus/hotstuff/hotstuff.rs | 19 +++++---- .../proposal/pending_proposal_mgr.rs | 18 ++++++-- .../src/consensus/vote/committee.rs | 9 +++- src/component/cyfs-group/src/dec/rpath_mgr.rs | 19 ++++++--- src/component/cyfs-group/src/helper/timer.rs | 41 ++++++++----------- .../cyfs-group/src/network/listener.rs | 29 +++++++++---- .../cyfs-group/src/network/sender.rs | 24 +++++++---- src/tests/group-example/src/main.rs | 20 ++++++++- 8 files changed, 119 insertions(+), 60 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 832855e5d..85613dfdc 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -208,7 +208,7 @@ struct HotstuffRunner { delegate: Arc>, synchronizer: Synchronizer, rpath: GroupRPath, - rx_proposal_waiter: Option<(Receiver, u64)>, + rx_proposal_waiter: Option<(Receiver<()>, u64)>, state_pusher: StatePusher, } @@ -788,13 +788,13 @@ impl HotstuffRunner { match self.committee.get_group(None).await { Ok(group) => { + log::info!("[hotstuff] local: {:?}, update round from {} to {}", + self, self.round, round + 1); + self.timer.reset(group.consensus_interval()); self.round = round + 1; self.vote_mgr.cleanup(self.round); self.tc = None; - - log::info!("[hotstuff] local: {:?}, update round from {} to {}", - self, self.round, round + 1); } Err(err) => { log::warn!("[hotstuff] local: {:?}, get group before update round from {} to {} failed {:?}", @@ -1581,7 +1581,7 @@ impl HotstuffRunner { let targets: Vec = group .ood_list() .iter() - .filter(|ood_id| **ood_id != self.local_id) + .filter(|ood_id| **ood_id != self.local_device_id) .map(|ood_id| ood_id.object_id().clone()) .collect(); @@ -1652,8 +1652,10 @@ impl HotstuffRunner { } if will_wait_proposals { - let (tx, rx) = async_std::channel::bounded(1); - self.rx_proposal_waiter = Some((rx, self.round)); + match self.proposal_consumer.wait_proposals().await { + Ok(rx) => self.rx_proposal_waiter = Some((rx, self.round)), + _ => return false + } } will_wait_proposals @@ -1718,7 +1720,7 @@ impl HotstuffRunner { } } - fn proposal_waiter(waiter: Option<(Receiver, u64)>) -> impl futures::Future { + fn proposal_waiter(waiter: Option<(Receiver<()>, u64)>) -> impl futures::Future { async move { match waiter.as_ref() { Some((waiter, wait_round)) => { @@ -1761,6 +1763,7 @@ impl HotstuffRunner { }, () = self.timer.wait_next().fuse() => self.local_timeout_round().await, wait_round = Self::proposal_waiter(self.rx_proposal_waiter.clone()).fuse() => { + self.rx_proposal_waiter = None; if wait_round == self.round { self.generate_block(None).await } else { diff --git a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs index 3deb31f52..d16bb4536 100644 --- a/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs +++ b/src/component/cyfs-group/src/consensus/proposal/pending_proposal_mgr.rs @@ -53,7 +53,7 @@ impl PendingProposalHandler { pub async fn on_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { self.tx_product.send(proposal).await.map_err(|e| { log::error!( - "[pending_proposal_mgr] send message(on_proposal) faield: {}", + "[pending_proposal_mgr] send message(on_proposal) failed: {}", e ); BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") @@ -72,7 +72,7 @@ impl PendingProposalConsumer { .send(ProposalConsumeMessage::Query(sender)) .await .map_err(|e| { - log::error!("[pending_proposal_mgr] send message(query) faield: {}", e); + log::error!("[pending_proposal_mgr] send message(query) failed: {}", e); BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") })?; @@ -82,12 +82,24 @@ impl PendingProposalConsumer { }) } + pub async fn wait_proposals(&self) -> BuckyResult> { + let (sender, receiver) = async_std::channel::bounded(1); + self.tx_consume + .send(ProposalConsumeMessage::Wait(sender)) + .await + .map_err(|e| { + log::error!("[pending_proposal_mgr] send message(wait) failed: {}", e); + BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") + })?; + Ok(receiver) + } + pub async fn remove_proposals(&self, proposal_ids: Vec) -> BuckyResult<()> { self.tx_consume .send(ProposalConsumeMessage::Remove(proposal_ids)) .await .map_err(|e| { - log::error!("[pending_proposal_mgr] send message(remove) faield: {}", e); + log::error!("[pending_proposal_mgr] send message(remove) failed: {}", e); BuckyError::new(BuckyErrorCode::ErrorState, "channel closed") }) } diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 05284f2a9..ee6eb2060 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -162,8 +162,13 @@ impl Committee { tc: &HotstuffTimeout, prev_block: Option<&GroupConsensusBlock>, ) -> BuckyResult<()> { - let highest_round = tc.votes.iter().map(|v| v.high_qc_round).max(); - let prev_round = prev_block.map(|b| b.round()); + let highest_round = tc + .votes + .iter() + .map(|v| v.high_qc_round) + .max() + .map_or(0, |round| round); + let prev_round = prev_block.map_or(0, |b| b.round()); if highest_round != prev_round { log::warn!("[group committee] hightest round is not match with prev-block in tc, highest_round: {:?}, prev_round: {:?}", highest_round, prev_round); return Err(BuckyError::new( diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index 4771f96d0..bf1f0b27a 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -43,6 +43,7 @@ impl GroupRPathMgr { bdt_stack: StackGuard, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; + let local_device_id = bdt_stack.local_device_id().object_id().clone(); let local_info = LocalInfo { signer: Arc::new(signer), @@ -59,7 +60,7 @@ impl GroupRPathMgr { let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); - crate::network::Listener::spawn(datagram, mgr.clone()); + crate::network::Listener::spawn(datagram, mgr.clone(), local_device_id); Ok(mgr) } @@ -117,9 +118,13 @@ impl GroupRPathMgr { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); + let local_device_id = local_info.bdt_stack.local_device_id(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); - let network_sender = - crate::network::Sender::new(local_info.datagram.clone(), non_driver.clone()); + let network_sender = crate::network::Sender::new( + local_info.datagram.clone(), + non_driver.clone(), + local_device_id.object_id().clone(), + ); let mut raw = self.write().await; @@ -360,10 +365,14 @@ impl GroupRPathMgr { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); + let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); - let network_sender = - crate::network::Sender::new(local_info.datagram.clone(), non_driver.clone()); + let network_sender = crate::network::Sender::new( + local_info.datagram.clone(), + non_driver.clone(), + local_device_id.object_id().clone(), + ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; diff --git a/src/component/cyfs-group/src/helper/timer.rs b/src/component/cyfs-group/src/helper/timer.rs index 3c9a35cce..6d2ebb234 100644 --- a/src/component/cyfs-group/src/helper/timer.rs +++ b/src/component/cyfs-group/src/helper/timer.rs @@ -1,42 +1,35 @@ use std::future::Future; +use std::ops::Sub; use std::pin::Pin; -use std::time::Duration; +use std::time::{Duration, Instant}; pub struct Timer { - sleep: Option>>>, - duration: u64, + last_wake_time: Instant, + duration: Duration, } impl Timer { pub fn new(duration: u64) -> Self { - let sleep = Box::pin(async move { - async_std::future::timeout( - Duration::from_millis(duration), - std::future::pending::<()>(), - ) - .await; - }); Self { - sleep: Some(sleep), - duration, + last_wake_time: Instant::now(), + duration: Duration::from_millis(duration), } } pub fn reset(&mut self, duration: u64) { - let sleep = Box::pin(async move { - async_std::future::timeout( - Duration::from_millis(duration), - std::future::pending::<()>(), - ) - .await; - }); - self.duration = duration; - self.sleep = Some(sleep); + self.duration = Duration::from_millis(duration); + self.last_wake_time = Instant::now(); } pub async fn wait_next(&mut self) { - let sleep = self.sleep.take().unwrap(); - self.reset(self.duration); - sleep.await; + let elapsed = Instant::now().duration_since(self.last_wake_time); + if elapsed < self.duration { + let _ = async_std::future::timeout( + self.duration.sub(elapsed), + std::future::pending::<()>(), + ) + .await; + } + self.last_wake_time = Instant::now(); } } diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 34061260c..abb185d80 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -1,4 +1,4 @@ -use cyfs_base::RawDecode; +use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; use crate::{GroupRPathMgr, HotstuffPackage}; @@ -6,25 +6,36 @@ use crate::{GroupRPathMgr, HotstuffPackage}; pub struct Listener; impl Listener { - pub fn spawn(datagram: DatagramTunnelGuard, processor: GroupRPathMgr) { + pub fn spawn( + datagram: DatagramTunnelGuard, + processor: GroupRPathMgr, + local_device_id: ObjectId, + ) { async_std::task::spawn(async move { - Self::run(datagram, processor).await; + Self::run(datagram, processor, local_device_id).await; }); } - async fn run(datagram: DatagramTunnelGuard, processor: GroupRPathMgr) { + async fn run( + datagram: DatagramTunnelGuard, + processor: GroupRPathMgr, + local_device_id: ObjectId, + ) { loop { match datagram.recv_v().await { Ok(pkgs) => { - for pkg in pkgs { - let remote = pkg.source.remote.object_id().clone(); - if let Ok((pkg, remain)) = HotstuffPackage::raw_decode(pkg.data.as_slice()) + for datagram in pkgs { + let remote = datagram.source.remote.object_id().clone(); + if let Ok((pkg, remain)) = + HotstuffPackage::raw_decode(datagram.data.as_slice()) { log::debug!( - "[group-listener] {:?} recv message from {:?}, msg: {:?}", + "[group-listener] {:?}-{} recv message from {:?}, msg: {:?}, len: {}", pkg.rpath(), + local_device_id, remote, - pkg + pkg, + datagram.data.len() ); assert_eq!(remain.len(), 0); processor.on_message(pkg, remote).await; diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 66806e011..a10bca787 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -11,15 +11,21 @@ pub struct Sender { datagram: DatagramTunnelGuard, vport: u16, non_driver: NONDriverHelper, + local_device_id: ObjectId, } impl Sender { - pub(crate) fn new(datagram: DatagramTunnelGuard, non_driver: NONDriverHelper) -> Self { + pub(crate) fn new( + datagram: DatagramTunnelGuard, + non_driver: NONDriverHelper, + local_device_id: ObjectId, + ) -> Self { let vport = datagram.vport(); Self { datagram, vport, non_driver, + local_device_id, } } @@ -44,13 +50,6 @@ impl Sender { _ => panic!("invalid remote type: {:?}", to.obj_type_code()), }; - log::debug!( - "[group-sender] {:?} post message to {:?}, msg: {:?}", - rpath, - remote, - msg - ); - let pkg = HotstuffPackage::from_msg(msg, rpath); let len = pkg.raw_measure(&None).unwrap(); @@ -59,6 +58,15 @@ impl Sender { let remain = pkg.raw_encode(buf.as_mut_slice(), &None).unwrap(); assert_eq!(remain.len(), 0); + log::debug!( + "[group-sender] {:?}-{} post message to {:?}, pkg: {:?}, len: {}", + pkg.rpath(), + self.local_device_id, + remote, + pkg, + buf.len() + ); + let mut options = DatagramOptions::default(); self.datagram diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index f891769d1..779ad8293 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -600,10 +600,28 @@ async fn main_run() { for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { // dummy(admin.clone(), device.clone()); let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; - DecService::run(&cyfs_stack, admin.name().unwrap().to_string()).await; admin_stacks.push(cyfs_stack); } + for i in 0..admin_stacks.len() { + let stack = admin_stacks.get(i).unwrap(); + let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); + DecService::run(&stack, admin.name().unwrap().to_string()).await; + + let control = stack + .group_mgr() + .find_rpath_control( + &EXAMPLE_GROUP.desc().object_id(), + EXAMPLE_DEC_APP_ID.object_id(), + &EXAMPLE_RPATH, + IsCreateRPath::Yes(None), + ) + .await + .unwrap(); + } + + async_std::task::sleep(Duration::from_millis(30000)).await; + for i in 1..100000000 { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; From b90419a84813846a79850b59287927a173e15cc0 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 19:43:56 +0800 Subject: [PATCH 054/553] fix: sign(block) --- src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs | 2 +- src/component/cyfs-group/src/consensus/vote/committee.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 85613dfdc..1a72088d3 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1567,7 +1567,7 @@ impl HotstuffRunner { obj_owner: None, }); - let desc_hash = block.named_object().desc().raw_hash_encode()?; + let desc_hash = block.named_object().desc().raw_hash_value()?; let signature = self.signer.sign(desc_hash.as_slice(), &sign_source).await?; block .named_object_mut() diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ee6eb2060..43cc7a882 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -337,7 +337,7 @@ impl Committee { .named_object() .desc() .owner() - .and_then(|blk_owner| Some(dev_owner == dev_owner)) + .and_then(|blk_owner| Some(blk_owner == dev_owner)) }) == Some(true) { sign_device = Some((device, sign)); From 0f7557f59f03865a3b974361ca75ec17dd11d4c3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 19:50:42 +0800 Subject: [PATCH 055/553] fix: tc for block --- .../cyfs-group/src/consensus/hotstuff/hotstuff.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 1a72088d3..efe58b104 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1765,7 +1765,15 @@ impl HotstuffRunner { wait_round = Self::proposal_waiter(self.rx_proposal_waiter.clone()).fuse() => { self.rx_proposal_waiter = None; if wait_round == self.round { - self.generate_block(None).await + // timeout + let tc = self.tc.as_ref().map_or(None, |tc| { + if tc.round + 1 == self.round { + Some(tc.clone()) + } else { + None + } + }); + self.generate_block(tc).await } else { Ok(()) } From d61c1b24201aa96b4ec3354d80812a3f2db627cc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 20:07:08 +0800 Subject: [PATCH 056/553] named_object().desc().object_id => block_id --- .../src/consensus/hotstuff/hotstuff.rs | 50 +++++++++---------- .../consensus/synchronizer/synchronizer.rs | 15 ++++-- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 16 +++--- .../src/dec_state/dec_state_synchronizer.rs | 2 +- .../cyfs-group/src/dec_state/state_pusher.rs | 6 +-- src/component/cyfs-group/src/helper/verify.rs | 4 +- .../cyfs-group/src/objects/protocol.rs | 6 +-- .../cyfs-group/src/storage/group_storage.rs | 32 ++++++------ 8 files changed, 69 insertions(+), 62 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index efe58b104..caad9336a 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -97,7 +97,7 @@ impl Hotstuff { pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { log::debug!("[hotstuff] local: {:?}, on_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", self, - block.named_object().desc().object_id(), block.round(), block.height(), + block.block_id(), block.round(), block.height(), block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), block.owner(), remote); @@ -285,7 +285,7 @@ impl HotstuffRunner { ) -> BuckyResult<()> { log::debug!("[hotstuff] local: {:?}, handle_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", self, - block.named_object().desc().object_id(), block.round(), block.height(), + block.block_id(), block.round(), block.height(), block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), block.owner(), remote); @@ -294,7 +294,7 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, receive block({}) from unknown({})", self, - block.named_object().desc().object_id(), + block.block_id(), remote ); return Ok(()); @@ -315,7 +315,7 @@ impl HotstuffRunner { if &leader_owner != block.owner() { log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", self, - block.named_object().desc().object_id(), + block.block_id(), block.owner(), leader_owner ); @@ -335,7 +335,7 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, verify block {:?} failed, {:?}.", self, - block.named_object().desc().object_id(), + block.block_id(), err ); err @@ -416,11 +416,11 @@ impl HotstuffRunner { .is_proposal_finished(&proposal_exe_info.proposal, prev_block_id) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, check proposal {:?} in block {:?} with prev-block {:?} duplicate failed, {:?}." - , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id, err); + , self, proposal_exe_info.proposal, block.block_id(), prev_block_id, err); err })? { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." - , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), prev_block_id); + , self, proposal_exe_info.proposal, block.block_id(), prev_block_id); return Err(BuckyError::new(BuckyErrorCode::ErrorState, "duplicate proposal")) } @@ -431,7 +431,7 @@ impl HotstuffRunner { Some(receipt) => { let (receipt, _) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} decode receipt failed {:?}." - , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); + , self, proposal_exe_info.proposal, block.block_id(), err); err })?; @@ -452,7 +452,7 @@ impl HotstuffRunner { .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." - , self, proposal_exe_info.proposal, block.named_object().desc().object_id(), err); + , self, proposal_exe_info.proposal, block.block_id(), err); err })? { @@ -610,14 +610,14 @@ impl HotstuffRunner { log::info!( "[hotstuff] local: {:?}, will push new block {:?} to storage", - self, block.named_object().desc().object_id() + self, block.block_id() ); let debug_identify = self.debug_identify(); let new_header_block = self.store.push_block(block.clone()).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, push verified block {:?} to storage failed {:?}", - debug_identify, block.named_object().desc().object_id(), err + debug_identify, block.block_id(), err ); err @@ -626,7 +626,7 @@ impl HotstuffRunner { if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", - self, header_block.named_object().desc().object_id() + self, header_block.block_id() ); /** @@ -642,14 +642,14 @@ impl HotstuffRunner { VoteThresholded::QC(qc) => { log::debug!( "[hotstuff] local: {:?}, the qc of block {:?} has received before", - self, block.named_object().desc().object_id() + self, block.block_id() ); return self.process_block_qc(qc, block, remote).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( "[hotstuff] local: {:?}, the timeout-qc of block {:?} has received before", - self, block.named_object().desc().object_id() + self, block.block_id() ); return self @@ -670,7 +670,7 @@ impl HotstuffRunner { if let Some(vote) = self.make_vote(block).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", - self, block.named_object().desc().object_id(), block.round()); + self, block.block_id(), block.round()); let next_leader = self.committee.get_leader(None, self.round + 1).await.map_err(|err| { log::warn!( @@ -728,7 +728,7 @@ impl HotstuffRunner { .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, new_header.named_object().desc().object_id(), err + self, proposal.proposal, new_header.block_id(), err ); err @@ -738,7 +738,7 @@ impl HotstuffRunner { let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { log::warn!( "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, new_header.named_object().desc().object_id(), err + self, proposal.proposal, new_header.block_id(), err ); err })?; @@ -839,7 +839,7 @@ impl HotstuffRunner { async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", - self, block.named_object().desc().object_id(), block.round(), self.store.last_vote_round()); + self, block.block_id(), block.round(), self.store.last_vote_round()); return None; } @@ -861,7 +861,7 @@ impl HotstuffRunner { if !is_valid_round { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", self, - block.named_object().desc().object_id(), + block.block_id(), block.round(), qc_round, block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); @@ -873,7 +873,7 @@ impl HotstuffRunner { _ => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", self, - block.named_object().desc().object_id()); + block.block_id()); return None; } @@ -885,7 +885,7 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, signature for block-vote failed, block: {}, err: {}", self, - block.named_object().desc().object_id(), + block.block_id(), e ); return None; @@ -1544,14 +1544,14 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, generate_block new block {}", self, - block.named_object().desc().object_id() + block.block_id() ); self.sign_block(&mut block).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, generate_block new block {} sign failed {:?}", self, - block.named_object().desc().object_id(), + block.block_id(), err ); @@ -1630,7 +1630,7 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, new empty block will ignore for 2 prev-block({}/{}) is empty", self, - pre_pre_block_id, pre_block.named_object().desc().object_id() + pre_pre_block_id, pre_block.block_id() ); will_wait_proposals = true; @@ -1640,7 +1640,7 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, new empty block will ignore for prev-prev-block is None and prev-block is {}, maybe is a bug.", self, - pre_block.named_object().desc().object_id() + pre_block.block_id() ); will_wait_proposals = true; diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 0da84181e..2721035ea 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -106,10 +106,14 @@ impl Synchronizer { let tx_sync_message = self.tx_sync_message.clone(); let height = block.height(); let round = block.round(); - let block_id = block.named_object().desc().object_id(); + let block_id = block.block_id(); async_std::task::spawn(async move { tx_sync_message - .send(SynchronizerMessage::PopBlock(height, round, block_id)) + .send(SynchronizerMessage::PopBlock( + height, + round, + block_id.object_id().clone(), + )) .await }); } @@ -587,10 +591,11 @@ impl SynchronizerRunner { for pos in 0..self.out_order_blocks.len() { let (block, remote) = self.out_order_blocks.get(pos).unwrap(); - let block_id_out = block.named_object().desc().object_id(); - if remove_block_ids.contains(block.prev_block_id().unwrap()) || block_id_out == block_id + let block_id_out = block.block_id().object_id(); + if remove_block_ids.contains(block.prev_block_id().unwrap()) + || block_id_out == &block_id { - remove_block_ids.insert(block_id_out); + remove_block_ids.insert(block_id_out.clone()); remove_pos = Some(pos); max_height = max_height.max(block.height()); max_round = max_round.max(block.round()); diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index e03e2b314..82f4017a0 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -44,11 +44,11 @@ impl VoteMgr { return VoteThresholded::None; } - let block_id = block.named_object().desc().object_id(); - self.blocks.insert(block_id, block.clone()); + let block_id = block.block_id().object_id(); + self.blocks.insert(block_id.clone(), block.clone()); if let Some(qc_makers) = self.votes.get_mut(&block.round()) { - if let Some(qc_maker) = qc_makers.get_mut(&block_id) { + if let Some(qc_maker) = qc_makers.get_mut(block_id) { if let Some(qc) = qc_maker .on_block(block, &self.committee) .await @@ -66,6 +66,7 @@ impl VoteMgr { **round >= block.round() && tc_maker .max_block() + .as_ref() .map_or(false, |max_block_id| block_id == max_block_id) }) .collect(); @@ -82,7 +83,7 @@ impl VoteMgr { } } - let waiting_timeouts = self.waiting_timeouts.remove(&block_id); + let waiting_timeouts = self.waiting_timeouts.remove(block_id); if let Some(waiting_timeouts) = waiting_timeouts { let mut waiting_timeouts: Vec<(u64, HashMap)> = waiting_timeouts.into_iter().collect(); @@ -118,8 +119,7 @@ impl VoteMgr { ) -> BuckyResult> { assert!(block .as_ref() - .map_or(true, |b| b.named_object().desc().object_id() - == vote.block_id)); + .map_or(true, |b| b.block_id().object_id() == &vote.block_id)); let block_id = vote.block_id; @@ -145,7 +145,7 @@ impl VoteMgr { block: Option<&GroupConsensusBlock>, ) -> BuckyResult)>> { assert!( - block.map(|block| block.named_object().desc().object_id()) + block.map(|block| block.block_id().object_id().clone()) == timeout.high_qc.as_ref().map(|qc| qc.block_id) ); @@ -250,7 +250,7 @@ impl QCMaker { .await?; if self.thresholded { return Ok(Some(HotstuffBlockQC { - block_id: block.named_object().desc().object_id(), + block_id: block.block_id().object_id().clone(), prev_block_id: block.prev_block_id().map(|id| id.clone()), round: block.round(), votes: self diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 8b32422c3..1f33ec5fa 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -317,7 +317,7 @@ impl DecStateSynchronizerRunner { if qc_block.qc().is_none() { log::warn!( "the qc is none for qc-block({})", - qc_block.named_object().desc().object_id() + qc_block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cd8f5a800..cc0b4aff2 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -55,15 +55,15 @@ impl StatePusher { block: GroupConsensusBlock, qc_block: GroupConsensusBlock, ) { - let block_id = block.named_object().desc().object_id(); + let block_id = block.block_id(); if qc_block.height() != block.height() + 1 || qc_block.qc().as_ref().expect("qc should not empty").round != block.round() || qc_block.round() <= block.round() - || qc_block.prev_block_id().unwrap() != &block_id + || qc_block.prev_block_id().unwrap() != block_id.object_id() { log::error!( "the qc-block({}) should be next block({})", - qc_block.named_object().desc().object_id(), + qc_block.block_id(), block_id ); return; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 268101c56..2a384d1cf 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -8,8 +8,8 @@ pub async fn verify_block( qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.named_object().desc().object_id(); - if qc.round != block.round() || qc.block_id != block_id { + let block_id = block.block_id().object_id(); + if qc.round != block.round() || &qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index efed7d9f6..dcc44f499 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -651,11 +651,11 @@ impl HotstuffBlockQCVote { local_device_id: ObjectId, signer: &RsaCPUObjectSigner, ) -> BuckyResult { - let block_id = block.named_object().desc().object_id(); + let block_id = block.block_id().object_id(); let round = block.round(); let signature = signer .sign( - Self::hash_content(&block_id, block.prev_block_id(), round).as_slice(), + Self::hash_content(block_id, block.prev_block_id(), round).as_slice(), &SignatureSource::Object(ObjectLink { obj_id: local_device_id, obj_owner: None, @@ -664,7 +664,7 @@ impl HotstuffBlockQCVote { .await?; Ok(Self { - block_id, + block_id: block_id.clone(), round, voter: local_device_id, signature, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 0e4ecb2a3..b5f4db6e0 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -163,7 +163,7 @@ impl GroupStorage { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); - let block_id = block.named_object().desc().object_id(); + let block_id = block.block_id(); let prev_block_id = block.prev_block_id(); let mut remove_prepares = vec![]; @@ -183,17 +183,18 @@ impl GroupStorage { prev_prev_block.prev_block_id(), self.header_block .as_ref() - .map(|b| b.named_object().desc().object_id()) + .map(|b| b.block_id().object_id().clone()) .as_ref() ); new_header = Some(prev_prev_block.clone()); - let new_header_id = prev_prev_block.named_object().desc().object_id(); + let new_header_id = prev_prev_block.block_id().object_id(); for (id, block) in self.prepares.iter() { - if block.prev_block_id().map(|prev_id| { - prev_id == &new_header_id || prev_id == prev_block_id - }) != Some(true) + if block + .prev_block_id() + .map(|prev_id| prev_id == new_header_id || prev_id == prev_block_id) + != Some(true) { remove_prepares.push(id.clone()); } @@ -217,7 +218,7 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(&block_id).await?; + writer.insert_prepares(block_id.object_id()).await?; if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { writer .insert_pre_commit(new_pre_commit, new_header.is_some()) @@ -225,10 +226,7 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit( - new_header.height(), - &new_header.named_object().desc().object_id(), - ) + .push_commit(new_header.height(), new_header.block_id().object_id()) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -245,7 +243,11 @@ impl GroupStorage { } // update memory - if self.prepares.insert(block_id, block).is_some() { + if self + .prepares + .insert(block_id.object_id().clone(), block) + .is_some() + { assert!(false); } @@ -317,9 +319,9 @@ impl GroupStorage { // 去重proposal,BlockLinkState::DuplicateProposal,去重只检查相同分叉链上的proposal,不同分叉上允许有相同proposal // 检查Proposal时间戳,早于去重proposal集合区间,或者晚于当前系统时间戳一定时间 - let block_id = block.named_object().desc().object_id(); + let block_id = block.block_id(); - if self.find_block_in_cache(&block_id).is_ok() { + if self.find_block_in_cache(block_id.object_id()).is_ok() { return Ok(BlockLinkState::Duplicate); } @@ -416,7 +418,7 @@ impl GroupStorage { pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { if let Some(block) = self.header_block.as_ref() { - if &block.named_object().desc().object_id() == block_id { + if block.block_id().object_id() == block_id { return Ok(block.clone()); } } From c6e1e8f60c1ab7a8bdbd7ada1bec9af5c29df4a9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 20:39:06 +0800 Subject: [PATCH 057/553] fix: remove block from prepare when pre-commit --- .../cyfs-group/src/consensus/synchronizer/synchronizer.rs | 8 ++------ src/component/cyfs-group/src/storage/group_storage.rs | 5 +++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 2721035ea..59cb43b96 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -106,14 +106,10 @@ impl Synchronizer { let tx_sync_message = self.tx_sync_message.clone(); let height = block.height(); let round = block.round(); - let block_id = block.block_id(); + let block_id = block.block_id().object_id().clone(); async_std::task::spawn(async move { tx_sync_message - .send(SynchronizerMessage::PopBlock( - height, - round, - block_id.object_id().clone(), - )) + .send(SynchronizerMessage::PopBlock(height, round, block_id)) .await }); } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index b5f4db6e0..e2c1aef11 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -273,6 +273,8 @@ impl GroupStorage { } None => { if let Some(new_pre_commit) = new_pre_commit { + assert!(remove_prepares.is_empty()); + if self .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) @@ -280,6 +282,9 @@ impl GroupStorage { { assert!(false); } + self.prepares + .remove(&new_pre_commit.0) + .expect("any block in pre-commit should be from prepare"); } } } From 4ebee63bb856508e71252dd482d9291342d5c719 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 9 Feb 2023 21:32:36 +0800 Subject: [PATCH 058/553] fix: round error, put block --- .../src/consensus/hotstuff/hotstuff.rs | 37 +++++++---- .../cyfs-group/src/network/non_driver.rs | 66 ++++++++++++------- .../cyfs-group/src/storage/group_storage.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 32 ++++++++- 4 files changed, 100 insertions(+), 39 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index caad9336a..18d062f53 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1166,10 +1166,9 @@ impl HotstuffRunner { max_high_qc.as_ref().map(|qc| qc.high_qc_round) ); - let max_high_qc = if let Some(max_high_qc) = max_high_qc { - max_high_qc - } else { - return Ok(()); + let max_high_qc = match max_high_qc { + Some(max_high_qc) => max_high_qc, + None => return Ok(()) }; if tc.round < self.round { @@ -1178,6 +1177,7 @@ impl HotstuffRunner { self, tc.round, ); + return Ok(()); } if max_high_qc.high_qc_round >= tc.round { @@ -1558,6 +1558,8 @@ impl HotstuffRunner { err })?; + self.non_driver.put_block(&block).await?; + Ok(block) } @@ -1661,6 +1663,24 @@ impl HotstuffRunner { will_wait_proposals } + async fn handle_proposal_waiting(&mut self) -> BuckyResult<()> { + log::debug!( + "[hotstuff] local: {:?}, handle_proposal_waiting", + self + ); + + assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); + + let tc = self.tc.as_ref().map_or(None, |tc| { + if tc.round + 1 == self.round { + Some(tc.clone()) + } else { + None + } + }); + self.generate_block(tc).await + } + async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { let block = self.non_driver.get_block(block_id, Some(&remote)).await?; @@ -1766,14 +1786,7 @@ impl HotstuffRunner { self.rx_proposal_waiter = None; if wait_round == self.round { // timeout - let tc = self.tc.as_ref().map_or(None, |tc| { - if tc.round + 1 == self.round { - Some(tc.clone()) - } else { - None - } - }); - self.generate_block(tc).await + self.handle_proposal_waiting().await } else { Ok(()) } diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index e84d95c5a..600ba5466 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -2,10 +2,10 @@ use std::sync::Arc; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, ObjectDesc, - ObjectId, ObjectTypeCode, People, PeopleId, RawDecode, + ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] @@ -17,6 +17,8 @@ pub trait NONDriver: Send + Sync { from: Option<&ObjectId>, ) -> BuckyResult; + async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()>; + async fn post_object( &self, dec_id: &ObjectId, @@ -44,6 +46,10 @@ impl NONDriverHelper { self.driver.get_object(&self.dec_id, object_id, from).await } + pub async fn put_object(&self, obj: NONObjectInfo) -> BuckyResult<()> { + self.driver.put_object(&self.dec_id, obj).await + } + pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { self.driver.post_object(&self.dec_id, obj, to).await } @@ -63,6 +69,16 @@ impl NONDriverHelper { Ok(block) } + pub async fn put_block(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + let block = NONObjectInfo { + object_id: block.block_id().object_id().clone(), + object_raw: block.to_vec()?, + object: None, + }; + self.put_object(block).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, @@ -80,26 +96,32 @@ impl NONDriverHelper { group_chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { - match group_chunk_id { - Some(group_chunk_id) => { - let chunk = self.get_object(group_chunk_id, from).await?; - let (group_chunk, remain) = ChunkMeta::raw_decode(chunk.object_raw.as_slice())?; - assert_eq!(remain.len(), 0); - let group = Group::try_from(&group_chunk)?; - if &group.desc().object_id() == group_id { - Ok(group) - } else { - Err(BuckyError::new(BuckyErrorCode::Unmatch, "groupid")) - } - } - None => { - // TODO: latest version from metachain - let group = self.get_object(group_id, from).await?; - let (group, remain) = Group::raw_decode(group.object_raw.as_slice())?; - assert_eq!(remain.len(), 0); - Ok(group) - } - } + // TODO: ignore group_chunk_id first + // match group_chunk_id { + // Some(group_chunk_id) => { + // let chunk = self.get_object(group_chunk_id, from).await?; + // let (group_chunk, remain) = ChunkMeta::raw_decode(chunk.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // let group = Group::try_from(&group_chunk)?; + // if &group.desc().object_id() == group_id { + // Ok(group) + // } else { + // Err(BuckyError::new(BuckyErrorCode::Unmatch, "groupid")) + // } + // } + // None => { + // // TODO: latest version from metachain + // let group = self.get_object(group_id, from).await?; + // let (group, remain) = Group::raw_decode(group.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // Ok(group) + // } + // } + + let group = self.get_object(group_id, from).await?; + let (group, remain) = Group::raw_decode(group.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(group) } pub async fn get_ood(&self, people_id: &PeopleId) -> BuckyResult { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index e2c1aef11..2e07f7eff 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -203,8 +203,6 @@ impl GroupStorage { assert_eq!(block.height(), header_height + 2); } } - } else { - assert_eq!(block.height(), header_height + 1); } } @@ -347,7 +345,7 @@ impl GroupStorage { Ok(prev_block) => { if prev_block.height() + 1 != block.height() { return Err(BuckyError::new(BuckyErrorCode::Failed, "height error")); - } else if prev_block.round() <= block.round() { + } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { let prev_block_time = bucky_time_to_system_time( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index da434c1f9..9414cda7c 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, - NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, RequestProtocol, - RequestSourceInfo, + NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, + RequestProtocol, RequestSourceInfo, }; use crate::{non::NONInputProcessor, non_api::NONService}; @@ -54,6 +54,34 @@ impl cyfs_group::NONDriver for GroupNONDriver { .map(|resp| resp.object) } + async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + self.non_service + .put_object(NONPutObjectInputRequest { + common: NONInputRequestCommon { + req_path: None, + source: RequestSourceInfo { + protocol: RequestProtocol::DataBdt, + zone: DeviceZoneInfo { + device: None, + zone: None, + zone_category: DeviceZoneCategory::CurrentZone, + }, + dec: dec_id.clone(), + verified: None, + }, + + level: NONAPILevel::Router, + + target: None, + flags: 0, + }, + object: obj, + access: None, // TODO access + }) + .await + .map(|_| ()) + } + async fn post_object( &self, dec_id: &ObjectId, From 4d2058b02d0648d01245da80f8ba297481ab6815 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Feb 2023 14:36:46 +0800 Subject: [PATCH 059/553] fix: error assert, sort by distance --- src/component/cyfs-base/src/objects/group.rs | 29 +++++++++++++++++-- .../cyfs-group/src/network/non_driver.rs | 12 ++++++-- .../cyfs-group/src/storage/group_storage.rs | 11 ++++--- .../cyfs-group/src/storage/storage_engine.rs | 2 +- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index eb27cd4fd..ed7686157 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -329,11 +329,36 @@ impl Group { target: &ObjectId, scope: GroupMemberScope, ) -> Vec<&ObjectId> { - unimplemented!() + let mut members = match scope { + GroupMemberScope::Admin => self.admins().iter().map(|m| &m.id).collect::>(), + GroupMemberScope::Member => self.members().iter().map(|m| &m.id).collect::>(), + GroupMemberScope::All => [ + self.admins().iter().map(|m| &m.id).collect::>(), + self.members().iter().map(|m| &m.id).collect::>(), + ] + .concat(), + }; + + members.sort_unstable_by(|l, r| { + let dl = l.distance_of(target); + let dr = r.distance_of(target); + dl.cmp(&dr) + }); + members } pub fn ood_list_with_distance(&self, target: &ObjectId) -> Vec<&ObjectId> { - unimplemented!() + let mut oods = self + .ood_list() + .iter() + .map(|id| id.object_id()) + .collect::>(); + oods.sort_unstable_by(|l, r| { + let dl = l.distance_of(target); + let dr = r.distance_of(target); + dl.cmp(&dr) + }); + oods } // pub fn group_hash(&self) -> ObjectId { diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 600ba5466..9d617d149 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,8 +1,9 @@ use std::sync::Arc; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, ObjectDesc, - ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, + AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, + ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; @@ -70,10 +71,15 @@ impl NONDriverHelper { } pub async fn put_block(&self, block: &GroupConsensusBlock) -> BuckyResult<()> { + let buf = block.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + let block = NONObjectInfo { object_id: block.block_id().object_id().clone(), object_raw: block.to_vec()?, - object: None, + object: Some(block_any), }; self.put_object(block).await?; Ok(()) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 2e07f7eff..d1bd9aa39 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -191,10 +191,11 @@ impl GroupStorage { let new_header_id = prev_prev_block.block_id().object_id(); for (id, block) in self.prepares.iter() { - if block - .prev_block_id() - .map(|prev_id| prev_id == new_header_id || prev_id == prev_block_id) - != Some(true) + if block.prev_block_id().map(|prev_id| { + assert_ne!(prev_id, prev_block_id); + prev_id == new_header_id + }) != Some(true) + && id != prev_block_id { remove_prepares.push(id.clone()); } @@ -203,6 +204,8 @@ impl GroupStorage { assert_eq!(block.height(), header_height + 2); } } + } else { + assert_ne!(block.height(), header_height + 3); } } diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/storage_engine.rs index 55ea1aaae..b9376618b 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/storage_engine.rs @@ -130,7 +130,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if !self + if self .engine .commit_blocks .insert(height, block_id.clone()) From 8521065c385edf424064761ebd74c16b5e144d6d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Feb 2023 15:27:06 +0800 Subject: [PATCH 060/553] fix: remove from prepare when header change --- .../cyfs-group/src/consensus/hotstuff/hotstuff.rs | 8 ++++---- src/component/cyfs-group/src/storage/group_storage.rs | 7 +++++-- src/tests/group-example/src/main.rs | 5 +++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 18d062f53..0cd327389 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -609,8 +609,8 @@ impl HotstuffRunner { */ log::info!( - "[hotstuff] local: {:?}, will push new block {:?} to storage", - self, block.block_id() + "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", + self, block.block_id(), block.height(), block.round() ); let debug_identify = self.debug_identify(); @@ -1542,9 +1542,9 @@ impl HotstuffRunner { ); log::debug!( - "[hotstuff] local: {:?}, generate_block new block {}", + "[hotstuff] local: {:?}, generate_block new block {}/{}/{}", self, - block.block_id() + block.block_id(), block.height(), block.round() ); self.sign_block(&mut block).await.map_err(|err| { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d1bd9aa39..796fe26e0 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -256,8 +256,11 @@ impl GroupStorage { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); self.header_block = Some(new_header); - let mut removed_blocks = - HashMap::from([new_pre_commit.expect("shoud got new pre-commit block")]); + + let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); + self.prepares.remove(&new_pre_commit.0); + + let mut removed_blocks = HashMap::from([new_pre_commit]); std::mem::swap(&mut self.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 779ad8293..a0383c80a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -542,11 +542,12 @@ mod GroupDecService { }); log::info!( - "proposal commited: height: {}, delta: {}, result: {} -> {}, local: {}", - block.height(), + "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, block: {}, local: {}", + block.height(), block.round(), delta, pre_value, result_value, + block.block_id(), self.local_name ); } From 9eda7299ae776cda48cb482c7d8db661e1b08932 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Feb 2023 20:47:17 +0800 Subject: [PATCH 061/553] adapt to the master branch --- src/component/cyfs-base/src/objects/mock.rs | 2 +- .../cyfs-core/src/group/group_proposal.rs | 12 +---------- .../src/consensus/hotstuff/hotstuff.rs | 5 +++-- .../cyfs-stack/src/stack/cyfs_stack.rs | 3 +-- src/tests/group-example/Cargo.toml | 3 ++- src/tests/group-example/src/main.rs | 21 +++++++++++-------- 6 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/component/cyfs-base/src/objects/mock.rs b/src/component/cyfs-base/src/objects/mock.rs index edda480db..6c409ea3e 100644 --- a/src/component/cyfs-base/src/objects/mock.rs +++ b/src/component/cyfs-base/src/objects/mock.rs @@ -10,7 +10,7 @@ impl CustomObjectId for ObjectId { assert!(buf.len() <= 31); let mut value = [0u8; 32]; value[1..buf.len() + 1].copy_from_slice(buf); - ObjectId::clone_from_slice(&value) + ObjectId::clone_from_slice(&value).unwrap() } fn get_slice_value(&self) -> &[u8] { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 0ce57b6a9..10aeed798 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -253,17 +253,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { Some(params) => { - if params.len() != HASH_VALUE_LEN { - Err(BuckyError::new( - BuckyErrorCode::Unmatch, - format!( - "try parse GroupProposal.param as hash with error length: ${}", - params.len() - ), - )) - } else { - Ok(Some(HashValue::from(params.as_slice()))) - } + HashValue::try_from(params.as_slice()).map(|h| Some(h)) } None => Ok(None), } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 0cd327389..e0353cace 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1512,6 +1512,7 @@ impl HotstuffRunner { prev_block: &Option, tc: Option ) -> BuckyResult { + let proposal_count = executed_proposals.len(); let proposals_param = executed_proposals .into_iter() .map(|(proposal, exe_result)| GroupConsensusBlockProposal { @@ -1542,9 +1543,9 @@ impl HotstuffRunner { ); log::debug!( - "[hotstuff] local: {:?}, generate_block new block {}/{}/{}", + "[hotstuff] local: {:?}, generate_block new block {}/{}/{}, proposals: {}", self, - block.block_id(), block.height(), block.round() + block.block_id(), block.height(), block.round(), proposal_count ); self.sign_block(&mut block).await.map_err(|err| { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 35a2d815e..d936f3054 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,8 +35,7 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{ChunkReader, DeviceCache, Stack, StackGuard, StackOpenParams, SnStatus}; -use cyfs_chunk_cache::{ChunkManager, ChunkManagerRef}; +use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; use cyfs_group::GroupRPathMgr; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; use cyfs_lib::*; diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index a2eddc0c8..0053ccd5f 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -26,4 +26,5 @@ cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } -cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } \ No newline at end of file +cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index a0383c80a..cce749008 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -20,19 +20,20 @@ mod Common { use std::sync::Arc; use cyfs_base::{ - AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, Group, GroupMember, - IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawEncode, - RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, UniqueId, - SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, + GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, + RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, + UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; + use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId, DecAppObj}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ - BdtStackParams, CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, - CyfsStackInterfaceParams, CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, - CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, + CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, + CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, + CyfsStackNOCParams, CyfsStackParams, }; use rand::Rng; @@ -70,7 +71,7 @@ mod Common { .mut_addr() .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))); endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_static_wan(true); + endpoint.set_area(EndpointArea::Wan); let mut device = Device::new( Some(owner.desc().object_id()), @@ -669,7 +670,9 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - async_std::task::sleep(Duration::from_millis(1000)).await; + if i % 1 == 0 { + async_std::task::sleep(Duration::from_millis(1000)).await; + } } } From af3fc7c720e20fc343f347bafd162b9778ef85a6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 11 Feb 2023 13:15:45 +0800 Subject: [PATCH 062/553] fix: use ObjectIdDataBuilder instead Mock --- src/component/cyfs-base/src/objects/mock.rs | 19 ------------------- src/component/cyfs-base/src/objects/mod.rs | 2 -- .../src/statepath/group_statepath.rs | 4 ++-- src/tests/group-example/src/main.rs | 13 ++++++++----- 4 files changed, 10 insertions(+), 28 deletions(-) delete mode 100644 src/component/cyfs-base/src/objects/mock.rs diff --git a/src/component/cyfs-base/src/objects/mock.rs b/src/component/cyfs-base/src/objects/mock.rs deleted file mode 100644 index 6c409ea3e..000000000 --- a/src/component/cyfs-base/src/objects/mock.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::ObjectId; - -pub trait CustomObjectId { - fn from_slice_value(buf: &[u8]) -> Self; - fn get_slice_value(&self) -> &[u8]; -} - -impl CustomObjectId for ObjectId { - fn from_slice_value(buf: &[u8]) -> Self { - assert!(buf.len() <= 31); - let mut value = [0u8; 32]; - value[1..buf.len() + 1].copy_from_slice(buf); - ObjectId::clone_from_slice(&value).unwrap() - } - - fn get_slice_value(&self) -> &[u8] { - &self.as_slice()[1..] - } -} diff --git a/src/component/cyfs-base/src/objects/mod.rs b/src/component/cyfs-base/src/objects/mod.rs index 5c23701dd..4e4e76ec9 100644 --- a/src/component/cyfs-base/src/objects/mod.rs +++ b/src/component/cyfs-base/src/objects/mod.rs @@ -10,7 +10,6 @@ mod dir; mod empty; mod file; mod group; -mod mock; mod named_object_id; mod ndn; mod object; @@ -41,7 +40,6 @@ pub use dir::*; pub use empty::*; pub use file::*; pub use group::*; -pub use mock::*; pub use named_object_id::*; pub use ndn::*; pub use object::*; diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eabc1fdde..c0daef478 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,4 +1,4 @@ -use cyfs_base::{CustomObjectId, ObjectId}; +use cyfs_base::{ObjectId, ObjectIdDataBuilder}; pub const STATEPATH_SEPARATOR: &str = "/"; @@ -19,7 +19,7 @@ pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; lazy_static::lazy_static! { - pub static ref STATEPATH_GROUP_DEC_ID: ObjectId = ObjectId::from_slice_value(".group".as_bytes()); + pub static ref STATEPATH_GROUP_DEC_ID: ObjectId = ObjectIdDataBuilder::new().data(".group".as_bytes()).build().unwrap(); pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index cce749008..eab4eb1d5 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -436,7 +436,7 @@ mod GroupDecService { * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.get_slice_value(); + let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -448,7 +448,10 @@ mod GroupDecService { let delta = u64::from_be_bytes(delta); let value = pre_value + delta; - ObjectId::from_slice_value(&value.to_be_bytes()) + ObjectIdDataBuilder::new() + .data(&value.to_be_bytes()) + .build() + .unwrap() }; let receipt = { @@ -529,14 +532,14 @@ mod GroupDecService { let delta = u64::from_be_bytes(delta); let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.get_slice_value(); + let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); let result_value = execute_result.result_state_id.map_or(0, |result_id| { - let buf = result_id.get_slice_value(); + let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(result_value) @@ -670,7 +673,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 4 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; } } From a9fb53cc6cfa03006b665e7bfeadc27817d5455b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 11 Feb 2023 18:23:46 +0800 Subject: [PATCH 063/553] fix: discard vote to the block with Error Timestamp --- .../cyfs-core/protos/core_objects.proto | 1 - .../src/group/group_consensus_block.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 53 +++++++++++++++---- .../cyfs-group/src/network/listener.rs | 35 +++++++----- .../cyfs-group/src/network/non_driver.rs | 42 ++++++++++++++- .../cyfs-group/src/network/sender.rs | 8 +++ src/component/cyfs-noc/src/blob/file.rs | 7 +++ src/tests/group-example/src/main.rs | 19 +++++-- 8 files changed, 137 insertions(+), 31 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 1c92a8ca9..164c6bcd6 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -412,7 +412,6 @@ message GroupConsensusBlockDescContent { // time bytes meta_block_id = 5; - uint64 timestamp = 6; uint64 round = 7; bytes group_chunk_id = 8; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 83de4f1da..5d6d114c0 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -15,7 +15,6 @@ pub struct GroupConsensusBlockDescContent { result_state_id: Option, height: u64, meta_block_id: ObjectId, - timestamp: u64, round: u64, group_chunk_id: ObjectId, } @@ -263,7 +262,6 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { height, meta_block_id, - timestamp: bucky_time_now(), body_hash: body.hash(), round, group_chunk_id, @@ -271,6 +269,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let block = GroupConsensusBlockBuilder::new(desc, body) .owner(owner) + .create_time(bucky_time_now()) .build(); let block_id = GroupConsensusBlockId::try_from(block.desc().object_id()).unwrap(); diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e0353cace..e3acbd581 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, sync::Arc, time::SystemTime}; +use std::{collections::HashMap, sync::Arc, time::{SystemTime, Duration}}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ @@ -15,7 +15,7 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::synchronizer::Synchronizer, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, @@ -352,7 +352,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote).await + self.process_block(block, remote, &proposals).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -603,6 +603,7 @@ impl HotstuffRunner { &mut self, block: &GroupConsensusBlock, remote: ObjectId, + proposals: &HashMap ) -> BuckyResult<()> { /** * 验证过的块执行这个函数 @@ -668,7 +669,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block).await { + if let Some(vote) = self.make_vote(block, proposals).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -836,7 +837,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -844,7 +845,19 @@ impl HotstuffRunner { return None; } - // TODO: 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(_) => return None + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + if !Self::check_timestamp_precision(block, proposals) { + return None; + } // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); @@ -899,6 +912,27 @@ impl HotstuffRunner { Some(vote) } + fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + let now = SystemTime::now(); + let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); + if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + false + } else { + for proposal in block.proposals() { + let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); + if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + return false + } + } + true + } + } + + fn calc_time_delta(t1: SystemTime, t2: SystemTime) -> Duration { + t1.duration_since(t2).or(t2.duration_since(t1)).unwrap() + } + async fn handle_vote( &mut self, vote: &HotstuffBlockQCVote, @@ -1359,10 +1393,7 @@ impl HotstuffRunner { } let create_time = bucky_time_to_system_time(proposal.desc().create_time()); - if now - .duration_since(create_time) - .or(create_time.duration_since(now)) - .unwrap() + if Self::calc_time_delta(now, create_time) > TIME_PRECISION { // 时间误差太大 @@ -1763,7 +1794,7 @@ impl HotstuffRunner { message = self.rx_message.recv().fuse() => match message { Ok((HotstuffMessage::Block(block), remote)) => { if remote == self.local_id { - self.process_block(&block, remote).await + self.process_block(&block, remote, &HashMap::new()).await } else { self.handle_block(&block, remote).await } diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index abb185d80..7863cf60c 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -26,19 +26,28 @@ impl Listener { Ok(pkgs) => { for datagram in pkgs { let remote = datagram.source.remote.object_id().clone(); - if let Ok((pkg, remain)) = - HotstuffPackage::raw_decode(datagram.data.as_slice()) - { - log::debug!( - "[group-listener] {:?}-{} recv message from {:?}, msg: {:?}, len: {}", - pkg.rpath(), - local_device_id, - remote, - pkg, - datagram.data.len() - ); - assert_eq!(remain.len(), 0); - processor.on_message(pkg, remote).await; + match HotstuffPackage::raw_decode(datagram.data.as_slice()) { + Ok((pkg, remain)) => { + log::debug!( + "[group-listener] {:?}-{} recv message from {:?}, msg: {:?}, len: {}", + pkg.rpath(), + local_device_id, + remote, + pkg, + datagram.data.len() + ); + assert_eq!(remain.len(), 0); + processor.on_message(pkg, remote).await; + } + Err(err) => { + log::debug!( + "[group-listener] {} recv message from {:?}, len: {} decode failed {:?}", + local_device_id, + remote, + datagram.data.len(), + err + ); + } } } } diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 9d617d149..dac80b276 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use cyfs_base::{ AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, @@ -153,4 +153,44 @@ impl NONDriverHelper { Err(BuckyError::new(BuckyErrorCode::Unmatch, "not device-id")) } } + + pub async fn load_all_proposals_for_block( + &self, + block: &GroupConsensusBlock, + proposals_map: &mut HashMap, + ) -> BuckyResult<()> { + let non_driver = self.clone(); + let block_owner = block.owner().clone(); + + let load_futs = block.proposals().iter().map(|proposal| { + let proposal_id = proposal.proposal; + let non_driver = non_driver.clone(); + async move { + non_driver + .get_proposal(&proposal_id, Some(&block_owner)) + .await + } + }); + + let mut results = futures::future::join_all(load_futs).await; + let proposal_count = results.len(); + + for i in 0..proposal_count { + let result = results.pop().unwrap(); + let proposal_id = block + .proposals() + .get(proposal_count - i - 1) + .unwrap() + .proposal; + match result { + Ok(proposal) => { + assert_eq!(proposal_id, proposal.desc().object_id()); + proposals_map.insert(proposal_id, proposal); + } + Err(err) => return Err(err), + } + } + + Ok(()) + } } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index a10bca787..bf1c98da1 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -1,3 +1,5 @@ +use std::sync::{atomic::AtomicU32, Arc}; + use cyfs_base::{DeviceId, ObjectId, PeopleId, RawEncode}; use cyfs_bdt::{DatagramOptions, DatagramTunnelGuard}; use cyfs_core::GroupRPath; @@ -12,6 +14,7 @@ pub struct Sender { vport: u16, non_driver: NONDriverHelper, local_device_id: ObjectId, + sequence: Arc, } impl Sender { @@ -26,6 +29,7 @@ impl Sender { vport, non_driver, local_device_id, + sequence: Arc::new(AtomicU32::new(rand::random::() & 0x80000000)), } } @@ -68,6 +72,10 @@ impl Sender { ); let mut options = DatagramOptions::default(); + options.sequence = Some(cyfs_bdt::TempSeq::from( + self.sequence + .fetch_add(1, std::sync::atomic::Ordering::SeqCst), + )); self.datagram .send_to(buf.as_slice(), &mut options, &remote, self.vport); diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index b17550c4e..1620ec23d 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -3,6 +3,7 @@ use cyfs_base::*; use cyfs_lib::*; use std::path::{Path, PathBuf}; +use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, @@ -44,6 +45,12 @@ impl FileBlobStorage { _ => second, }; + #[cfg(target_os = "windows")] + let first = match first { + "con" | "aux" | "nul" | "prn" => Cow::Owned(format!("{}_", first)), + _ => Cow::Borrowed(first), + }; + let path = self.root.join(format!("{}/{}", first, second)); if auto_create && !path.exists() { async_std::fs::create_dir_all(&path).await.map_err(|e| { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index eab4eb1d5..c661ac51f 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -347,6 +347,9 @@ mod Client { } mod GroupDecService { + use std::{collections::HashSet, sync::Arc}; + + use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, @@ -417,11 +420,15 @@ mod GroupDecService { pub struct MyRPathDelegate { local_name: String, + finished_proposals: Arc>>, } impl MyRPathDelegate { pub fn new(local_name: String) -> Self { - MyRPathDelegate { local_name } + MyRPathDelegate { + local_name, + finished_proposals: Arc::new(Mutex::new(HashSet::new())), + } } } @@ -545,15 +552,21 @@ mod GroupDecService { u64::from_be_bytes(result_value) }); + let proposal_id = proposal.desc().object_id(); + log::info!( - "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, block: {}, local: {}", + "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, pre_value, result_value, + proposal_id, block.block_id(), self.local_name ); + + let has_finished = self.finished_proposals.lock().await.insert(proposal_id); + assert!(!has_finished); } async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { @@ -673,7 +686,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 4 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; } } From cd6a23431fab2177ddf8aa6aaec5c180e22d53cd Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Feb 2023 16:25:59 +0800 Subject: [PATCH 064/553] add cache between above NOC --- .../src/consensus/hotstuff/hotstuff.rs | 56 ++++++++----- src/component/cyfs-group/src/constant.rs | 2 + .../cyfs-group/src/network/listener.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 80 ++++++++++++++++++- .../cyfs-group/src/network/sender.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 6 files changed, 120 insertions(+), 28 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e3acbd581..850e80c8e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -636,7 +636,32 @@ impl HotstuffRunner { * */ self.cleanup_proposal(&header_block).await; - self.notify_block_committed(header_block).await; + let (_, qc_block) = self + .store + .pre_commits() + .iter() + .next() + .expect("the pre-commit block must exist."); + + self.notify_block_committed(header_block.clone(), qc_block).await; + + let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get leader in round {} failed {:?}", + self, self.round, err + ); + + err + }); + + // notify by leader + if let Ok(leader) = leader { + if self.local_device_id == leader { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; + } + } } match self.vote_mgr.add_voting_block(block).await { @@ -675,7 +700,7 @@ impl HotstuffRunner { let next_leader = self.committee.get_leader(None, self.round + 1).await.map_err(|err| { log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", + "[hotstuff] local: {:?}, get next leader in round {} failed {:?}", self, self.round + 1, err ); @@ -698,15 +723,8 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock) -> BuckyResult<()> { - let (_, qc_block) = self - .store - .pre_commits() - .iter() - .next() - .expect("the pre-commit block must exist."); - - let pre_state_id = match new_header.prev_block_id() { + async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + let mut pre_state_id = match new_header.prev_block_id() { Some(block_id) => self .non_driver .get_block(block_id, None) @@ -754,19 +772,17 @@ impl HotstuffRunner { &proposal_obj, pre_state_id, &ExecuteResult { - result_state_id: new_header.result_state_id().clone(), + result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, &new_header, ) .await; + + pre_state_id = proposal.result_state.clone(); } - self.state_pusher - .notify_block_commit(new_header, qc_block.clone()) - .await; - Ok(()) } @@ -820,10 +836,10 @@ impl HotstuffRunner { .proposals() .iter() .map(|proposal| proposal.proposal) - .collect(); + .collect::>(); log::debug!("[hotstuff] local: {:?}, remove proposals: {:?}", - self, proposals); + self, proposals.len()); self.proposal_consumer.remove_proposals(proposals).await } @@ -1573,8 +1589,8 @@ impl HotstuffRunner { self.local_id, ); - log::debug!( - "[hotstuff] local: {:?}, generate_block new block {}/{}/{}, proposals: {}", + log::info!( + "[hotstuff] local: {:?}, generate_block new block {}/{}/{}, with proposals: {}", self, block.block_id(), block.height(), block.round(), proposal_count ); diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 42460e055..aa7babc44 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -19,3 +19,5 @@ pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; +pub const MEMORY_CACHE_SIZE: usize = 1024; +pub const MEMORY_CACHE_DURATION: Duration = Duration::from_secs(300); diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 7863cf60c..905eb0e61 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -29,7 +29,7 @@ impl Listener { match HotstuffPackage::raw_decode(datagram.data.as_slice()) { Ok((pkg, remain)) => { log::debug!( - "[group-listener] {:?}-{} recv message from {:?}, msg: {:?}, len: {}", + "[group-listener] {:?}-{} recv group message from {:?}, msg: {:?}, len: {}", pkg.rpath(), local_device_id, remote, diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index dac80b276..7e4c99476 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -1,5 +1,6 @@ -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, sync::Arc, time::Instant}; +use async_std::sync::RwLock; use cyfs_base::{ AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, @@ -9,6 +10,8 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::NONObjectInfo; +use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; + #[async_trait::async_trait] pub trait NONDriver: Send + Sync { async fn get_object( @@ -32,11 +35,16 @@ pub trait NONDriver: Send + Sync { pub(crate) struct NONDriverHelper { driver: Arc>, dec_id: ObjectId, + cache: NONObjectCache, } impl NONDriverHelper { pub fn new(driver: Arc>, dec_id: ObjectId) -> Self { - Self { driver, dec_id } + Self { + driver, + dec_id, + cache: NONObjectCache::new(), + } } pub async fn get_object( @@ -44,7 +52,20 @@ impl NONDriverHelper { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { - self.driver.get_object(&self.dec_id, object_id, from).await + if let Some(obj) = self.cache.find_in_cache(object_id).await { + return Ok(obj); + } + + { + let result = self + .driver + .get_object(&self.dec_id, object_id, from) + .await?; + + self.cache.insert_cache(&result).await; + + Ok(result) + } } pub async fn put_object(&self, obj: NONObjectInfo) -> BuckyResult<()> { @@ -194,3 +215,56 @@ impl NONDriverHelper { Ok(()) } } + +#[derive(Clone)] +struct NONObjectCache { + cache: Arc, Instant)>>, + cache_1: Arc>>, +} + +impl NONObjectCache { + fn new() -> Self { + Self { + cache: Arc::new(RwLock::new((HashMap::new(), Instant::now()))), + cache_1: Arc::new(RwLock::new(HashMap::new())), + } + } + + async fn find_in_cache(&self, object_id: &ObjectId) -> Option { + { + let cache = self.cache.read().await; + if let Some(obj) = cache.0.get(object_id) { + return Some(obj.clone()); + } + } + + { + let cache = self.cache_1.read().await; + cache.get(object_id).cloned() + } + } + + async fn insert_cache(&self, obj: &NONObjectInfo) { + let new_cache_1 = { + let mut cache = self.cache.write().await; + let now = Instant::now(); + if now.duration_since(cache.1) > MEMORY_CACHE_DURATION + || cache.0.len() > MEMORY_CACHE_SIZE + { + let mut new_cache = HashMap::new(); + std::mem::swap(&mut new_cache, &mut cache.0); + cache.1 = now; + cache.0.insert(obj.object_id, obj.clone()); + new_cache + } else { + cache.0.insert(obj.object_id, obj.clone()); + return; + } + }; + + { + let mut cache_1 = self.cache_1.write().await; + *cache_1 = new_cache_1; + } + } +} diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index bf1c98da1..673660bad 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -63,7 +63,7 @@ impl Sender { assert_eq!(remain.len(), 0); log::debug!( - "[group-sender] {:?}-{} post message to {:?}, pkg: {:?}, len: {}", + "[group-sender] {:?}-{} post group message to {:?}, pkg: {:?}, len: {}", pkg.rpath(), self.local_device_id, remote, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index c661ac51f..85484c172 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -565,8 +565,8 @@ mod GroupDecService { self.local_name ); - let has_finished = self.finished_proposals.lock().await.insert(proposal_id); - assert!(!has_finished); + let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); + assert!(is_new_finished); } async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { @@ -686,7 +686,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 50 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; } } From 31ee735be3fdf8db74df84e3cd8df527c1134546 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Feb 2023 12:12:05 +0800 Subject: [PATCH 065/553] add logs --- .../src/consensus/hotstuff/hotstuff.rs | 34 +++++++- .../src/consensus/vote/committee.rs | 28 ++++++- .../cyfs-group/src/dec/rpath_control.rs | 6 +- src/component/cyfs-group/src/dec/rpath_mgr.rs | 11 ++- .../cyfs-group/src/network/listener.rs | 7 +- .../cyfs-group/src/network/sender.rs | 6 +- .../cyfs-group/src/storage/group_storage.rs | 27 +++++++ src/tests/group-example/src/main.rs | 77 +++++++++++++------ 8 files changed, 163 insertions(+), 33 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 850e80c8e..7d48de899 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -308,6 +308,10 @@ impl HotstuffRunner { */ Self::check_block_result_state(block)?; + log::debug!("[hotstuff] local: {:?}, handle_block-step2: {:?}", + self, + block.block_id()); + { // check leader let leader_owner = self.get_leader_owner(Some(block.group_chunk_id()), block.round()).await?; @@ -328,6 +332,10 @@ impl HotstuffRunner { Err(err) => return err }; + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + self.committee .verify_block(block, remote) .await @@ -341,6 +349,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", + self, + block.block_id()); + self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) .await?; @@ -636,6 +648,11 @@ impl HotstuffRunner { * */ self.cleanup_proposal(&header_block).await; + log::debug!( + "[hotstuff] local: {:?}, process_block-step1 {:?}", + self, block.block_id() + ); + let (_, qc_block) = self .store .pre_commits() @@ -644,7 +661,12 @@ impl HotstuffRunner { .expect("the pre-commit block must exist."); self.notify_block_committed(header_block.clone(), qc_block).await; - + + log::debug!( + "[hotstuff] local: {:?}, process_block-step2 {:?}", + self, block.block_id() + ); + let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader in round {} failed {:?}", @@ -662,6 +684,11 @@ impl HotstuffRunner { .await; } } + + log::debug!( + "[hotstuff] local: {:?}, process_block-step3 {:?}", + self, block.block_id() + ); } match self.vote_mgr.add_voting_block(block).await { @@ -685,6 +712,11 @@ impl HotstuffRunner { VoteThresholded::None => {} } + log::debug!( + "[hotstuff] local: {:?}, process_block-step4 {:?}", + self, block.block_id() + ); + if block.round() != self.round { log::debug!( "[hotstuff] local: {:?}, not my round {}, expect {}", diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 43cc7a882..d3fbd489c 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -18,15 +18,17 @@ use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; pub(crate) struct Committee { group_id: ObjectId, non_driver: NONDriverHelper, + local_device_id: ObjectId, group_cache: Arc>>, // (group_chunk_id, group) } impl Committee { - pub fn new(group_id: ObjectId, non_driver: NONDriverHelper) -> Self { + pub fn new(group_id: ObjectId, non_driver: NONDriverHelper, local_device_id: ObjectId) -> Self { Committee { group_id, non_driver, group_cache: Arc::new(RwLock::new(HashMap::new())), + local_device_id, } } @@ -80,6 +82,12 @@ impl Committee { ) } + log::debug!( + "[group committee] {} verify block {} step1", + self.local_device_id, + block.block_id() + ); + let group = self .check_group(Some(block.group_chunk_id()), Some(&from)) .await?; @@ -95,6 +103,12 @@ impl Committee { )); } + log::debug!( + "[group committee] {} verify block {} step2", + self.local_device_id, + block.block_id() + ); + let prev_block = if let Some(qc) = block.qc() { let prev_block = self.non_driver.get_block(&qc.block_id, None).await?; self.verify_qc(qc, &prev_block).await?; @@ -103,10 +117,22 @@ impl Committee { None }; + log::debug!( + "[group committee] {} verify block {} step3", + self.local_device_id, + block.block_id() + ); + if let Some(tc) = block.tc() { self.verify_tc(tc, prev_block.as_ref()).await?; } + log::debug!( + "[group committee] {} verify block {} step4", + self.local_device_id, + block.block_id() + ); + Ok(()) } diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index cc1436555..101b34075 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -31,7 +31,11 @@ impl RPathControl { store: GroupStorage, ) -> BuckyResult { let (pending_proposal_handle, pending_proposal_consumer) = PendingProposalMgr::new(); - let committee = Committee::new(rpath.group_id().clone(), non_driver.clone()); + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); let hotstuff = Hotstuff::new( local_id, local_device_id, diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/rpath_mgr.rs index bf1f0b27a..644fc2fcf 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/rpath_mgr.rs @@ -419,8 +419,15 @@ impl GroupRPathMgr { IsCreateRPath::Yes(init_state) => init_state, _ => unreachable!(), }; - GroupStorage::create(group_id, dec_id, rpath, init_state, non_driver.clone()) - .await? + GroupStorage::create( + group_id, + dec_id, + rpath, + init_state, + non_driver.clone(), + local_device_id.object_id().clone(), + ) + .await? } }; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 905eb0e61..6a6d7b549 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -1,3 +1,5 @@ +use std::time::{Duration, Instant}; + use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; @@ -29,12 +31,13 @@ impl Listener { match HotstuffPackage::raw_decode(datagram.data.as_slice()) { Ok((pkg, remain)) => { log::debug!( - "[group-listener] {:?}-{} recv group message from {:?}, msg: {:?}, len: {}", + "[group-listener] {:?}-{} recv group message from {:?}, msg: {:?}, len: {}, delay: {}", pkg.rpath(), local_device_id, remote, pkg, - datagram.data.len() + datagram.data.len(), + Instant::now().elapsed().as_millis() as u64 - datagram.options.create_time.unwrap() ); assert_eq!(remain.len(), 0); processor.on_message(pkg, remote).await; diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index 673660bad..dcbc64a53 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -1,4 +1,7 @@ -use std::sync::{atomic::AtomicU32, Arc}; +use std::{ + sync::{atomic::AtomicU32, Arc}, + time::Instant, +}; use cyfs_base::{DeviceId, ObjectId, PeopleId, RawEncode}; use cyfs_bdt::{DatagramOptions, DatagramTunnelGuard}; @@ -72,6 +75,7 @@ impl Sender { ); let mut options = DatagramOptions::default(); + options.create_time = Some(Instant::now().elapsed().as_millis() as u64); options.sequence = Some(cyfs_bdt::TempSeq::from( self.sequence .fetch_add(1, std::sync::atomic::Ordering::SeqCst), diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 796fe26e0..81ec45e58 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -28,6 +28,7 @@ pub struct GroupStorage { group_id: ObjectId, dec_id: ObjectId, rpath: String, + local_device_id: ObjectId, non_driver: NONDriverHelper, dec_state_id: Option, // commited/header state id @@ -48,6 +49,7 @@ impl GroupStorage { rpath: &str, init_state_id: Option, non_driver: NONDriverHelper, + local_device_id: ObjectId, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); @@ -67,6 +69,7 @@ impl GroupStorage { prepares: HashMap::new(), pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), + local_device_id, }) } @@ -315,6 +318,12 @@ impl GroupStorage { } pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { + log::debug!( + "[group storage] {} block_linked {} step1", + self.local_device_id, + block.block_id() + ); + let header_height = self.header_height(); if block.height() <= header_height { return Ok(BlockLinkState::Expired); @@ -346,6 +355,12 @@ impl GroupStorage { } } + log::debug!( + "[group storage] {} block_linked {} step2", + self.local_device_id, + block.block_id() + ); + let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.find_block_in_cache(prev_block_id) { Ok(prev_block) => { @@ -386,6 +401,12 @@ impl GroupStorage { } }; + log::debug!( + "[group storage] {} block_linked {} step3", + self.local_device_id, + block.block_id() + ); + let mut proposals = HashMap::new(); for proposal_result in block.proposals().as_slice() { if proposals.get(&proposal_result.proposal).is_some() { @@ -422,6 +443,12 @@ impl GroupStorage { proposals.insert(proposal_result.proposal, proposal); } + log::debug!( + "[group storage] {} block_linked {} step4", + self.local_device_id, + block.block_id() + ); + Ok(BlockLinkState::Link(prev_block, proposals)) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 85484c172..ffb45ccec 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -69,7 +69,7 @@ mod Common { endpoint.set_protocol(Protocol::Udp); endpoint .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))); + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); endpoint.mut_addr().set_port(port_begin + i as u16); endpoint.set_area(EndpointArea::Wan); @@ -640,7 +640,12 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(30000)).await; - for i in 1..100000000 { + let mut proposals: Vec = vec![]; + + log::info!("proposals will be prepared."); + + let PROPOSAL_COUNT = 1000usize; + for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; let proposal = create_proposal(i as u64, owner.desc().object_id()); @@ -658,36 +663,58 @@ async fn main_run() { let noc = stack.noc_manager().clone(); - async_std::task::spawn(async move { - let buf = proposal.to_vec().unwrap(); - let proposal_any = Arc::new(AnyNamedObject::Core( - TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), - )); - noc.put_object(&NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), - verified: None, + let buf = proposal.to_vec().unwrap(); + let proposal_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let req = NamedObjectCachePutObjectRequest { + source: RequestSourceInfo { + protocol: RequestProtocol::DatagramBdt, + zone: DeviceZoneInfo { + device: None, + zone: None, + zone_category: DeviceZoneCategory::CurrentDevice, }, - object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: None, - }) + dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + verified: None, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), + storage_category: NamedObjectStorageCategory::Storage, + context: None, + last_access_rpath: None, + access_string: None, + }; + noc.put_object(&req).await; + proposals.push(proposal); + } + + // futures::future::join_all(prepare_futures).await; + + log::info!("proposals prepared."); + + for i in 0..(PROPOSAL_COUNT - 1) { + let proposal = proposals.get(i).unwrap().clone(); + let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + + let control = stack + .group_mgr() + .find_rpath_control( + &EXAMPLE_GROUP.desc().object_id(), + EXAMPLE_DEC_APP_ID.object_id(), + &EXAMPLE_RPATH, + IsCreateRPath::Yes(None), + ) .await .unwrap(); + async_std::task::spawn(async move { control.push_proposal(proposal).await.unwrap(); }); - if i % 50 == 0 { - async_std::task::sleep(Duration::from_millis(1000)).await; + if i % 10 == 0 { + async_std::task::sleep(Duration::from_millis(200)).await; + log::info!("will push new proposals, i: {}", i); } } } From e9ca4a0b5ab8444434b9693617e870ee874dd66d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Feb 2023 19:49:29 +0800 Subject: [PATCH 066/553] optimization --- .../src/consensus/hotstuff/hotstuff.rs | 61 +++++++++++----- .../cyfs-group/src/network/non_driver.rs | 22 +++++- .../cyfs-group/src/objects/protocol.rs | 19 ++++- .../cyfs-group/src/storage/group_storage.rs | 73 ++++++++++++------- 4 files changed, 125 insertions(+), 50 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7d48de899..ff4e06380 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -204,6 +204,8 @@ struct HotstuffRunner { non_driver: crate::network::NONDriverHelper, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, + tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, + rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, delegate: Arc>, synchronizer: Synchronizer, @@ -254,6 +256,8 @@ impl HotstuffRunner { tx_message.clone(), ); + let (tx_block_gen, rx_block_gen) = async_std::channel::bounded(1); + Self { local_id, local_device_id, @@ -275,6 +279,8 @@ impl HotstuffRunner { rx_proposal_waiter: None, tc: None, state_pusher, + tx_block_gen, + rx_block_gen, } } @@ -740,7 +746,7 @@ impl HotstuffRunner { })?; if self.local_device_id == next_leader { - self.handle_vote(&vote, Some(block), remote).await?; + self.handle_vote(&vote, Some(block), self.local_device_id).await?; } else { self.network_sender .post_message( @@ -940,8 +946,16 @@ impl HotstuffRunner { } } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", + self, block.block_id(), block.round()); + let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { - Ok(vote) => vote, + Ok(vote) => { + log::debug!("[hotstuff] local: {:?}, make-vote after sign {}, round: {}", + self, block.block_id(), block.round()); + + vote + }, Err(e) => { log::warn!( "[hotstuff] local: {:?}, signature for block-vote failed, block: {}, err: {}", @@ -1226,7 +1240,6 @@ impl HotstuffRunner { })?; self.broadcast(HotstuffMessage::Timeout(tc), &latest_group) - .await } } @@ -1368,10 +1381,8 @@ impl HotstuffRunner { self.store.set_last_vote_round(self.round).await?; - self.handle_timeout(&timeout, self.local_id).await; - - self.broadcast(HotstuffMessage::TimeoutVote(timeout), &latest_group) - .await; + self.broadcast(HotstuffMessage::TimeoutVote(timeout.clone()), &latest_group); + self.tx_message.send((HotstuffMessage::TimeoutVote(timeout), self.local_device_id)).await; Ok(()) } @@ -1486,14 +1497,15 @@ impl HotstuffRunner { return Ok(()); } + let proposals_map = HashMap::from_iter( + executed_proposals.iter() + .map(|(proposal, _)| (proposal.desc().object_id(), proposal.clone())) + ); + let block = self.package_block_with_proposals(executed_proposals, &latest_group, result_state_id, &prev_block, tc).await?; - self.tx_message - .send((HotstuffMessage::Block(block.clone()), self.local_id)) - .await; - - self.broadcast(HotstuffMessage::Block(block), &latest_group) - .await; + self.broadcast(HotstuffMessage::Block(block.clone()), &latest_group); + self.tx_block_gen.send((block, proposals_map)).await; self.rx_proposal_waiter = None; Ok(()) @@ -1659,7 +1671,7 @@ impl HotstuffRunner { Ok(()) } - async fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { + fn broadcast(&self, msg: HotstuffMessage, group: &Group) -> BuckyResult<()> { let targets: Vec = group .ood_list() .iter() @@ -1667,9 +1679,12 @@ impl HotstuffRunner { .map(|ood_id| ood_id.object_id().clone()) .collect(); - self.network_sender - .broadcast(msg, self.rpath.clone(), targets.as_slice()) - .await; + let network_sender = self.network_sender.clone(); + let rpath = self.rpath.clone(); + + async_std::task::spawn(async move { + network_sender.broadcast(msg, rpath.clone(), targets.as_slice()).await + }); Ok(()) } @@ -1809,8 +1824,7 @@ impl HotstuffRunner { self.broadcast( HotstuffMessage::Block(max_round_block), &latest_group.unwrap(), - ) - .await; + ); } _ => { self.generate_block(None).await; @@ -1841,7 +1855,7 @@ impl HotstuffRunner { let result = futures::select! { message = self.rx_message.recv().fuse() => match message { Ok((HotstuffMessage::Block(block), remote)) => { - if remote == self.local_id { + if remote == self.local_device_id { self.process_block(&block, remote, &HashMap::new()).await } else { self.handle_block(&block, remote).await @@ -1861,6 +1875,13 @@ impl HotstuffRunner { Ok(()) }, }, + block = self.rx_block_gen.recv().fuse() => match block { + Ok((block, proposals)) => self.process_block(&block, self.local_device_id, &proposals).await, + Err(e) => { + log::warn!("[hotstuff] rx_block_gen closed."); + Ok(()) + } + }, () = self.timer.wait_next().fuse() => self.local_timeout_round().await, wait_round = Self::proposal_waiter(self.rx_proposal_waiter.clone()).fuse() => { self.rx_proposal_waiter = None; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 7e4c99476..4212a0355 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -183,12 +183,32 @@ impl NONDriverHelper { let non_driver = self.clone(); let block_owner = block.owner().clone(); + let remote = match block_owner.obj_type_code() { + cyfs_base::ObjectTypeCode::Device => DeviceId::try_from(block_owner).unwrap(), + cyfs_base::ObjectTypeCode::People => { + let people_id = PeopleId::try_from(block_owner).unwrap(); + match self.get_ood(&people_id).await { + Ok(device_id) => device_id, + Err(e) => { + log::warn!( + "[non driver] load_all_proposals_for_block get ood of {}, failed err: {:?}", + block_owner, + e + ); + return Err(e); + } + } + } + _ => panic!("invalid remote type: {:?}", block_owner.obj_type_code()), + }; + let load_futs = block.proposals().iter().map(|proposal| { let proposal_id = proposal.proposal; let non_driver = non_driver.clone(); + let remote = remote.clone(); async move { non_driver - .get_proposal(&proposal_id, Some(&block_owner)) + .get_proposal(&proposal_id, Some(remote.object_id())) .await } }); diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index dcc44f499..3e5f513df 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -653,9 +653,26 @@ impl HotstuffBlockQCVote { ) -> BuckyResult { let block_id = block.block_id().object_id(); let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + let signature = signer .sign( - Self::hash_content(block_id, block.prev_block_id(), round).as_slice(), + hash.as_slice(), &SignatureSource::Object(ObjectLink { obj_id: local_device_id, obj_owner: None, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 81ec45e58..440613f51 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -408,39 +408,56 @@ impl GroupStorage { ); let mut proposals = HashMap::new(); - for proposal_result in block.proposals().as_slice() { - if proposals.get(&proposal_result.proposal).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + if let Some(prev_block_id) = block.prev_block_id() { + if self + .is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await? + { + return Ok(BlockLinkState::DuplicateProposal); + } + } - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? + let proposal = self + .non_driver + .get_proposal(&proposal_result.proposal, Some(block.owner())) + .await?; + + let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); + if block_time + .duration_since(proposal_time) + .or(proposal_time.duration_since(block_time)) + .unwrap() + > TIME_PRECISION { - return Ok(BlockLinkState::DuplicateProposal); + return Err(BuckyError::new( + BuckyErrorCode::ErrorTimestamp, + "error timestamp", + )); } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); + Ok(BlockLinkState::Link( + None, + HashMap::from([(proposal_result.proposal, proposal)]), + )) + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok(result) => match result { + BlockLinkState::Link(_, proposal) => { + let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); + if proposals.get(&proposal_id).is_some() { + return Ok(BlockLinkState::DuplicateProposal); + } + proposals.insert(proposal_id, proposal); + } + _ => return Ok(result), + }, + _ => return check_result, } - - proposals.insert(proposal_result.proposal, proposal); } log::debug!( From 81eb6d3f254aac06b57800e6d3e5a206fca4f4c6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 13:15:27 +0800 Subject: [PATCH 067/553] update version of prost-build --- src/component/cyfs-group/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 82d58c3a1..599e13b51 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -8,7 +8,7 @@ license = 'BSD-2-Clause' description = 'Rust cyfs-group package' [build-dependencies] -prost-build = { version = '0.11.5' } +prost-build = { version = '0.9.0' } protoc-rust = '2' chrono = '0.4' protoc-bin-vendored = '3' From f85299b72484c1f71c4da28a662edd81e9c2f1b6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:13:38 +0800 Subject: [PATCH 068/553] merge from buckyos --- src/component/cyfs-group/Cargo.toml | 2 +- src/component/cyfs-noc/src/blob/file.rs | 1 - src/component/cyfs-stack/Cargo.toml | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 599e13b51..aaab4ed76 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -28,7 +28,7 @@ async-recursion = '1.0' rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } -cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index 13838c174..9417d1377 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -4,7 +4,6 @@ use cyfs_lib::*; use std::borrow::Cow; use std::path::{Path, PathBuf}; -use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 7912c5a5b..d1815a2be 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -15,6 +15,7 @@ cyfs-bdt = { path = "../../component/cyfs-bdt" } cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } +cyfs-group = { path = "../../component/cyfs-group" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } From 9c1ff5f757e3867fa4bf080c2bda08d1c8e9eecc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:22:30 +0800 Subject: [PATCH 069/553] rename GroupRPathMgr to GroupManager --- .../src/dec/{rpath_mgr.rs => group_manager.rs} | 4 ++-- src/component/cyfs-group/src/dec/mod.rs | 4 ++-- src/component/cyfs-group/src/network/listener.rs | 6 +++--- src/component/cyfs-stack/src/stack/cyfs_stack.rs | 14 ++++++-------- 4 files changed, 13 insertions(+), 15 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_mgr.rs => group_manager.rs} (99%) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/group_manager.rs similarity index 99% rename from src/component/cyfs-group/src/dec/rpath_mgr.rs rename to src/component/cyfs-group/src/dec/group_manager.rs index 644fc2fcf..56ef5e7d9 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -34,9 +34,9 @@ struct LocalInfo { } #[derive(Clone)] -pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); +pub struct GroupManager(Arc<(LocalInfo, RwLock)>); -impl GroupRPathMgr { +impl GroupManager { pub fn new( signer: RsaCPUObjectSigner, non_driver: Box, diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index a1f964e95..b4e753a27 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod delegate_factory; mod rpath_client; mod rpath_control; -mod rpath_mgr; +mod group_manager; pub use delegate_factory::*; pub use rpath_client::*; pub use rpath_control::*; -pub use rpath_mgr::*; +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6a6d7b549..e66ef8a43 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; -use crate::{GroupRPathMgr, HotstuffPackage}; +use crate::{GroupManager, HotstuffPackage}; pub struct Listener; impl Listener { pub fn spawn( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { async_std::task::spawn(async move { @@ -20,7 +20,7 @@ impl Listener { async fn run( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { loop { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index da928fbe3..2fb131a5a 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,9 +35,9 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; -use cyfs_group::GroupRPathMgr; +use cyfs_bdt::{DeviceCache, SnStatus, StackGuard}; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; +use cyfs_group::GroupManager; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -45,7 +45,6 @@ use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; use once_cell::sync::OnceCell; use std::sync::Arc; - #[derive(Clone)] pub(crate) struct ObjectServices { pub ndn_service: Arc, @@ -106,7 +105,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupRPathMgr, + group_manager: GroupManager, } impl CyfsStackImpl { @@ -429,7 +428,7 @@ impl CyfsStackImpl { config.clone(), ); - let group_manager = GroupRPathMgr::new( + let group_manager = GroupManager::new( signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), @@ -773,7 +772,6 @@ impl CyfsStackImpl { let task = async_std::task::spawn(async move { // 初始化known_objects for object in known_objects.list.into_iter() { - let req = NamedObjectCachePutObjectRequest { source: RequestSourceInfo::new_local_system(), object, @@ -789,7 +787,7 @@ impl CyfsStackImpl { if known_objects.mode == CyfsStackKnownObjectsInitMode::Sync { task.await; } - + Ok(noc) } @@ -1119,7 +1117,7 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupRPathMgr { + pub fn group_mgr(&self) -> &GroupManager { &self.stack.group_manager } From 793e8ecbcadbd1704b8274acf4a64e3ba1856842 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 21:19:34 +0800 Subject: [PATCH 070/553] integrate GroupState, not finish --- .../cyfs-base/src/objects/object_map/mod.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 4 + .../cyfs-group/src/statepath/design.md | 26 +-- .../src/storage/engine/group_state_path.rs | 178 +++++++++++++++ .../cyfs-group/src/storage/engine/mod.rs | 9 + .../src/storage/engine/storage_engine.rs | 23 ++ .../engine/storage_engine_group_state.rs | 207 ++++++++++++++++++ .../storage_engine_mock.rs} | 53 ++--- .../cyfs-group/src/storage/group_storage.rs | 71 +++++- src/component/cyfs-group/src/storage/mod.rs | 4 +- 12 files changed, 524 insertions(+), 70 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs create mode 100644 src/component/cyfs-group/src/storage/engine/mod.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs rename src/component/cyfs-group/src/storage/{storage_engine.rs => engine/storage_engine_mock.rs} (76%) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index be52c2ea5..3bbc5f131 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -2,6 +2,7 @@ mod access; mod cache; mod check; mod diff; +mod isolate_path_env; mod iterator; mod lock; mod object_map; @@ -13,7 +14,6 @@ mod path_iterator; mod root; mod single_env; mod visitor; -mod isolate_path_env; pub use access::*; pub use cache::*; @@ -25,4 +25,5 @@ pub use path::*; pub use path_env::*; pub use path_iterator::*; pub use root::*; +pub use single_env::*; pub use visitor::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ff4e06380..e89498b83 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -18,7 +18,7 @@ use crate::{ consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** @@ -1461,12 +1461,13 @@ impl HotstuffRunner { continue; } - if let Some(ending) = proposal.effective_ending() { - if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.desc().object_id()); - timeout_proposals.push(proposal); - continue; - } + let ending = proposal.effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), + |ending| bucky_time_to_system_time(ending)); + if now >= ending { + remove_proposals.push(proposal.desc().object_id()); + timeout_proposals.push(proposal); + continue; } match self.delegate.on_execute(&proposal, result_state_id).await { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index aa7babc44..1170176b2 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,6 +14,7 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 56ef5e7d9..95c931720 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,6 +6,7 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, @@ -31,6 +32,7 @@ struct LocalInfo { non_driver: Arc>, datagram: DatagramTunnelGuard, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl GroupManager { signer: RsaCPUObjectSigner, non_driver: Box, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); @@ -50,6 +53,7 @@ impl GroupManager { non_driver: Arc::new(non_driver), datagram: datagram.clone(), bdt_stack, + global_state_mgr, }; let raw = GroupRPathMgrRaw { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index b73a46939..7ec71d4d5 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -7,22 +7,18 @@ | |--list-->Set | |--option-->GroupOption | -|--.dec-state // for dec;各Group的dec状态放这里 -| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 -| |--${dec-id} | .group // 一个dec管理的${r-path}状态 -| | | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | -| -|--.link // 区块链结构,记录状态变更链条 -| |--${group-id} -| |--${dec-id} | .group // .group表示group本身的演变共识 +|--${group-id} +| |--${dec-id} +| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 +| | // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-chunk-->Chunk(Group) +| |--group-blob-->BLOB(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs new file mode 100644 index 000000000..4e67d6e1f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/group_state_path.rs @@ -0,0 +1,178 @@ +use cyfs_base::ObjectId; + +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; + +pub struct GroupStatePath { + rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, +} + +impl GroupStatePath { + pub fn new(rpath: String) -> Self { + Self { + rpath, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.rpath.as_str() + } + + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() + } + + pub fn link(&self) -> &str { + self.link.as_str() + } + + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() + } + + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() + } + + pub fn range(&self) -> &str { + self.range.as_str() + } + + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) + } + + pub fn commit_block(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn commit_proposals(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_PROPOSALS, + ]) + } + + pub fn prepares(&self) -> &str { + self.prepares.as_str() + } + + pub fn prepare_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() + } + + pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.pre_commits.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() + } + + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() + } + + pub fn recycle(&self) -> &str { + self.recycle.as_str() + } + + pub fn adding(&self) -> &str { + self.adding.as_str() + } +} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs new file mode 100644 index 000000000..71d5cc49f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -0,0 +1,9 @@ +mod group_state_path; +mod storage_engine; +mod storage_engine_group_state; +mod storage_engine_mock; + +pub(super) use group_state_path::*; +pub(super) use storage_engine::*; +pub(super) use storage_engine_group_state::*; +pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs new file mode 100644 index 000000000..e48e607bc --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -0,0 +1,23 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Send + Sync + Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs new file mode 100644 index 000000000..3aba73e31 --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -0,0 +1,207 @@ +use std::{collections::HashSet, sync::Arc}; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, +}; + +use crate::StatePath; + +use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; + +const ACCESS: Option = None; + +#[derive(Clone)] +pub struct StorageEngineGroupState { + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, +} + +impl StorageEngineGroupState { + pub async fn load( + dec_group_state: ObjectMapRootManagerRef, + state_path: GroupStatePath, + ) -> BuckyResult { + Ok(Self { + state_mgr: todo!(), + state_path: Arc::new(state_path), + }) + } + + pub async fn create_writer(&self) -> BuckyResult { + Ok( + StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) + .await?, + ) + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineGroupState { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + let op_env = self.state_mgr.create_op_env(ACCESS)?; + let block_id = op_env + .get_by_path(self.state_path.commit_block(height).as_str()) + .await?; + block_id.map_or( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), + |block_id| Ok(block_id), + ) + } +} + +#[derive(Clone)] +pub struct StorageEngineGroupStateWriter { + state_mgr: ObjectMapRootManagerRef, + op_env: ObjectMapPathOpEnvRef, + prepare_op_env: ObjectMapSingleOpEnvRef, + prepare_map_id: Option, + state_path: Arc, +} + +impl StorageEngineGroupStateWriter { + async fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; + let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; + match prepare_map_id.as_ref() { + Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, + None => { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await? + } + }; + + Ok(Self { + op_env, + prepare_op_env, + state_path, + state_mgr, + prepare_map_id, + }) + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; + new_prepare + .create_new(ObjectMapSimpleContentType::Map) + .await?; + new_prepare + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + let new_prepare_block = new_prepare.commit().await?; + + self.prepare_op_env + .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .await + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str()) + .await? + .is_some() + { + assert!(false); + } + + // TODO + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineGroupStateWriter<'a> { + fn drop(&mut self) {} +} diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs similarity index 76% rename from src/component/cyfs-group/src/storage/storage_engine.rs rename to src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b9376618b..6208b0680 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -2,28 +2,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -#[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; - async fn push_proposals( - &mut self, - proposal_ids: &[ObjectId], - timestamp: u64, - ) -> BuckyResult<()>; - - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; -} - -#[async_trait::async_trait] -pub trait StorageEngine { - async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult; - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; -} +use super::{StorageEngine, StorageWriter}; struct StorageEngineMockFinishProposalMgr { flip_timestamp: u64, @@ -58,6 +37,10 @@ impl StorageEngineMock { }, } } + + pub async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) + } } #[async_trait::async_trait] @@ -69,19 +52,15 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult { - Ok(StorageEngineMockWriter { engine: self }) - } - - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { - let is_finished = self - .finish_proposals - .adding - .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) - .is_some(); - Ok(is_finished) - } + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + // let is_finished = self + // .finish_proposals + // .adding + // .get(proposal_id) + // .or(self.finish_proposals.over.get(proposal_id)) + // .is_some(); + // Ok(is_finished) + // } } pub struct StorageEngineMockWriter<'a> { @@ -164,9 +143,9 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: u64, + timestamp: Option, ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + if let Some(timestamp) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 440613f51..bc9fc6009 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, time::SystemTime}; +use std::{ + collections::{HashMap, HashSet}, + time::SystemTime, +}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, @@ -6,10 +9,13 @@ use cyfs_base::{ }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; + +use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; +use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; -use super::{storage_engine::StorageEngineMock, StorageEngine}; +const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; pub enum BlockLinkState { Expired, @@ -23,6 +29,12 @@ pub enum BlockLinkState { InvalidBranch, } +struct FinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -39,6 +51,8 @@ pub struct GroupStorage { prepares: HashMap, pre_commits: HashMap, + finish_proposals: FinishProposalMgr, + storage_engine: StorageEngineMock, } @@ -50,11 +64,19 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + // let group_state = root_state_mgr + // .load_root_state(group_id, Some(group_id.clone()), true) + // .await? + // .expect("create group state failed."); + + // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + Ok(Self { group, group_id: group_id.clone(), @@ -70,6 +92,11 @@ impl GroupStorage { pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), local_device_id, + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, }) } @@ -78,6 +105,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -240,10 +268,17 @@ impl GroupStorage { .iter() .map(|p| p.proposal.clone()) .collect(); - writer.push_proposals( - finish_proposals.as_slice(), - new_header.named_object().desc().create_time(), - ); + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + writer + .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } // update memory @@ -276,6 +311,20 @@ impl GroupStorage { if self.first_block.is_none() { self.first_block = self.header_block.clone(); } + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.finish_proposals.over); + self.finish_proposals.flip_timestamp = timestamp; + } + + for proposal in new_header.proposals() { + let is_new = self.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -551,7 +600,13 @@ impl GroupStorage { // find in storage - self.storage_engine.is_proposal_finished(proposal_id).await + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d95cf7ddd..d4440419e 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,7 @@ mod dec_storage; +mod engine; mod group_storage; -mod storage_engine; pub use dec_storage::*; +use engine::*; pub use group_storage::*; -pub(crate) use storage_engine::*; From 3cdea18832b6887641f83847ec7483a4306acad8 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 17:28:17 +0800 Subject: [PATCH 071/553] integrate GroupState update --- .../cyfs-group/src/statepath/design.md | 11 +- .../src/statepath/group_statepath.rs | 257 +++++------- .../src/storage/engine/group_state_path.rs | 178 --------- .../cyfs-group/src/storage/engine/mod.rs | 2 - .../src/storage/engine/storage_engine.rs | 17 +- .../engine/storage_engine_group_state.rs | 367 +++++++++++++----- .../src/storage/engine/storage_engine_mock.rs | 30 +- .../cyfs-group/src/storage/group_storage.rs | 30 +- .../cyfs-stack/src/stack/cyfs_stack.rs | 1 + 9 files changed, 439 insertions(+), 454 deletions(-) delete mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 7ec71d4d5..70a61e428 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -25,15 +25,10 @@ | |--last-vote-round-->u64 // 最后一次投票的轮次 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height}) -| | |--block-->GroupConsensusBlock +| |--str(${height})->block | | -| |--prepares // Prepare状态的block -| | |--${block.id} -| | |--block -| |--pre-commits // pre-commit状态的block -| | |--${block.id} -| | |--block +| |--prepares->Set // Prepare状态的block +| |--pre-commits->Set // pre-commit状态的block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index c0daef478..eade0f9e4 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,19 +1,17 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; -pub const STATEPATH_SEPARATOR: &str = "/"; - -pub const STATEPATH_GROUPS: &str = "groups"; - -pub const STATEPATH_DEC_STATE: &str = ".dec-state"; - -pub const STATEPATH_LINK: &str = ".link"; -pub const STATEPATH_GROUP_HASH: &str = "group-hash"; -pub const STATEPATH_USERS: &str = "users"; -pub const STATEPATH_USERS_NONCE: &str = "nonce"; -pub const STATEPATH_RANGE: &str = "range"; -pub const STATEPATH_BLOCK: &str = "block"; - -pub const STATEPATH_RPATHS: &str = ".r-paths"; +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; @@ -23,180 +21,131 @@ lazy_static::lazy_static! { pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } -pub struct StatePath { - group_id: ObjectId, - group_id_str: String, - dec_id: ObjectId, - dec_id_str: String, +pub struct GroupStatePath { rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, } -impl StatePath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { +impl GroupStatePath { + pub fn new(rpath: String) -> Self { Self { - group_id_str: group_id.to_string(), - group_id, - dec_id_str: dec_id.to_string(), - dec_id, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), rpath, } } pub fn join(fields: &[&str]) -> String { - fields.join(STATEPATH_SEPARATOR) - } - - pub fn dec_state() -> String { - STATEPATH_DEC_STATE.to_string() - } - - pub fn dec_state_group(&self) -> String { - Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) - } - - pub fn dec_state_dec(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + fields.join(STATE_PATH_SEPARATOR) } - pub fn dec_state_rpath(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn root(&self) -> &str { + self.rpath.as_str() } - pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - sub_path, - ]) + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() } - pub fn link() -> String { - STATEPATH_LINK.to_string() + pub fn link(&self) -> &str { + self.link.as_str() } - pub fn link_group(&self) -> String { - Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() } - pub fn link_dec(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() } - pub fn link_rpath(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn range(&self) -> &str { + self.range.as_str() } - pub fn link_group_hash(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_GROUP_HASH, - ]) + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) } - pub fn link_users(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - ]) + pub fn prepares(&self) -> &str { + self.prepares.as_str() } - pub fn link_user(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - ]) + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() } - pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - STATEPATH_USERS_NONCE, - ]) + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() } - pub fn link_range(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_RANGE, - ]) - } - - pub fn link_height(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - ]) - } - - pub fn link_block(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - STATEPATH_BLOCK, - ]) - } - - pub fn rpaths(&self) -> String { - STATEPATH_RPATHS.to_string() - } -} - -pub struct GroupUpdateStatePath; - -impl GroupUpdateStatePath { - pub fn latest_version() -> &'static str { - STATEPATH_GROUP_DEC_LATEST_VERSION + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() } - pub fn version_seq(version_seq: u64) -> String { - version_seq.to_string() + pub fn recycle(&self) -> &str { + self.recycle.as_str() } - pub fn group_hash(group_hash: &ObjectId) -> String { - group_hash.to_string() + pub fn adding(&self) -> &str { + self.adding.as_str() } } diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs deleted file mode 100644 index 4e67d6e1f..000000000 --- a/src/component/cyfs-group/src/storage/engine/group_state_path.rs +++ /dev/null @@ -1,178 +0,0 @@ -use cyfs_base::ObjectId; - -pub const STATE_PATH_SEPARATOR: &str = "/"; -pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; -pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; -pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; -pub const GROUP_STATE_PATH_RANGE: &str = "range"; -pub const GROUP_STATE_PATH_BLOCK: &str = "block"; -pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; -pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; -pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; -pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; -pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; -pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; -pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; -pub const GROUP_STATE_PATH_ADDING: &str = "adding"; - -pub struct GroupStatePath { - rpath: String, - dec_state: String, - link: String, - group_blob: String, - last_vote_round: String, - range: String, - prepares: String, - pre_commits: String, - finish_proposals: String, - flip_time: String, - recycle: String, - adding: String, -} - -impl GroupStatePath { - pub fn new(rpath: String) -> Self { - Self { - rpath, - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, - ]), - last_vote_round: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, - ]), - range: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_RANGE, - ]), - prepares: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PREPARES, - ]), - pre_commits: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PRE_COMMITS, - ]), - finish_proposals: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - ]), - flip_time: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_FLIP_TIME, - ]), - recycle: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_RECYCLE, - ]), - adding: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_ADDING, - ]), - } - } - - pub fn join(fields: &[&str]) -> String { - fields.join(STATE_PATH_SEPARATOR) - } - - pub fn root(&self) -> &str { - self.rpath.as_str() - } - - pub fn dec_state(&self) -> &str { - self.dec_state.as_str() - } - - pub fn link(&self) -> &str { - self.link.as_str() - } - - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() - } - - pub fn last_vote_round(&self) -> &str { - self.last_vote_round.as_str() - } - - pub fn range(&self) -> &str { - self.range.as_str() - } - - pub fn commit_height(&self, height: u64) -> String { - Self::join(&[self.link.as_str(), height.to_string().as_str()]) - } - - pub fn commit_block(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn commit_proposals(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_PROPOSALS, - ]) - } - - pub fn prepares(&self) -> &str { - self.prepares.as_str() - } - - pub fn prepare_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.prepares.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn pre_commits(&self) -> &str { - self.pre_commits.as_str() - } - - pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.pre_commits.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn finish_proposals(&self) -> &str { - self.finish_proposals.as_str() - } - - pub fn flip_time(&self) -> &str { - self.flip_time.as_str() - } - - pub fn recycle(&self) -> &str { - self.recycle.as_str() - } - - pub fn adding(&self) -> &str { - self.adding.as_str() - } -} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs index 71d5cc49f..c185cb24c 100644 --- a/src/component/cyfs-group/src/storage/engine/mod.rs +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -1,9 +1,7 @@ -mod group_state_path; mod storage_engine; mod storage_engine_group_state; mod storage_engine_mock; -pub(super) use group_state_path::*; pub(super) use storage_engine::*; pub(super) use storage_engine_group_state::*; pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e48e607bc..e19c46b81 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,19 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { +pub trait StorageWriter: Send + Sync { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()>; async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()>; - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + + async fn commit(mut self) -> BuckyResult<()>; } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 3aba73e31..731725e95 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use crate::StatePath; +use crate::{ + GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, +}; -use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; +use super::{StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -41,7 +44,7 @@ impl StorageEngine for StorageEngineGroupState { async fn find_block_by_height(&self, height: u64) -> BuckyResult { let op_env = self.state_mgr.create_op_env(ACCESS)?; let block_id = op_env - .get_by_path(self.state_path.commit_block(height).as_str()) + .get_by_path(self.state_path.commit_height(height).as_str()) .await?; block_id.map_or( Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), @@ -57,6 +60,7 @@ pub struct StorageEngineGroupStateWriter { prepare_op_env: ObjectMapSingleOpEnvRef, prepare_map_id: Option, state_path: Arc, + write_result: BuckyResult<()>, } impl StorageEngineGroupStateWriter { @@ -65,16 +69,20 @@ impl StorageEngineGroupStateWriter { state_path: Arc, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; - let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; - match prepare_map_id.as_ref() { - Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, - None => { - prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await? - } - }; + let prepare_map_id = + if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { + if err.code() == BuckyErrorCode::NotFound { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + None + } else { + return Err(err); + } + } else { + prepare_op_env.get_current_root().await + }; Ok(Self { op_env, @@ -82,126 +90,299 @@ impl StorageEngineGroupStateWriter { state_path, state_mgr, prepare_map_id, + write_result: Ok(()), }) } -} - -#[async_trait::async_trait] -impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { - let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; - new_prepare - .create_new(ObjectMapSimpleContentType::Map) - .await?; - new_prepare - .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) - .await?; - let new_prepare_block = new_prepare.commit().await?; + async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { self.prepare_op_env - .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .insert(block_id) .await + .map(|is_changed| assert!(is_changed)) } - async fn insert_pre_commit( + async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, is_instead: bool, ) -> BuckyResult<()> { - if !self - .prepare_op_env - .remove_with_key(block_id.to_string().as_str()) - .await? - .is_some() - { - assert!(false); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); - // TODO if is_instead { - self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); - } else { - if !self.engine.pre_commit_blocks.insert(block_id.clone()) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block pre-commit twice", - )); - } + self.op_env + .remove_with_path(self.state_path.pre_commits(), &None) + .await?; } - Ok(()) + self.op_env + .insert_with_path(self.state_path.pre_commits(), block_id) + .await } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if self - .engine - .commit_blocks - .insert(height, block_id.clone()) - .is_some() - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block commit twice", - )); - } + async fn push_commit_inner( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.op_env + .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) + .await?; - self.engine.block_height_range.1 = height; + let range_obj = make_range_obj(min_height, height); + if height == 1 { + self.op_env + .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) + .await?; + } else { + let prev_range = make_range_obj(min_height, height - 1); + let prev_value = self + .op_env + .set_with_key( + self.state_path.link(), + GROUP_STATE_PATH_RANGE, + &range_obj, + &Some(prev_range), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_range); + }; + + // update state from dec-app + if result_state_id == prev_result_state_id { + return Ok(()); + } else { + match result_state_id { + Some(result_state_id) => { + if prev_result_state_id.is_none() { + self.op_env + .insert_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + ) + .await?; + } else { + let prev_value = self + .op_env + .set_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + prev_result_state_id, + false, + ) + .await?; + assert_eq!(&prev_value, prev_result_state_id); + } + } + None => { + self.op_env + .remove_with_path(self.state_path.dec_state(), prev_result_state_id) + .await?; + } + } + } Ok(()) } - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - if !self.engine.prepare_blocks.remove(block_id) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "try remove prepare not exists", - )); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); } Ok(()) } - async fn push_proposals( + async fn push_proposals_inner( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); - self.engine.finish_proposals.flip_timestamp = timestamp; + if proposal_ids.is_empty() { + return Ok(()); } - for proposal_id in proposal_ids { - if !self - .engine - .finish_proposals - .adding - .insert(proposal_id.clone()) - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "dup finish proposal", - )); + let add_single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + + if let Some((timestamp, prev_timestamp)) = timestamp { + let new_over = self + .op_env + .remove_with_path(self.state_path.adding(), &None) + .await?; + + if let Some(new_over) = new_over.as_ref() { + self.op_env + .set_with_path(self.state_path.recycle(), new_over, &None, true) + .await?; } + + let timestamp_obj = make_u64_obj(timestamp); + if prev_timestamp != 0 { + let prev_timestamp_obj = make_u64_obj(prev_timestamp); + let prev_value = self + .op_env + .set_with_path( + self.state_path.flip_time(), + ×tamp_obj, + &Some(prev_timestamp_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_timestamp_obj); + } else { + self.op_env + .insert_with_key( + self.state_path.finish_proposals(), + GROUP_STATE_PATH_FLIP_TIME, + ×tamp_obj, + ) + .await?; + } + + add_single_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + } else { + add_single_op_env + .load_by_path(self.state_path.adding()) + .await?; } + for proposal_id in proposal_ids { + let is_new = add_single_op_env.insert(proposal_id).await?; + assert!(is_new); + } + let adding_set_id = add_single_op_env.commit().await?; + let prev_value = self + .op_env + .set_with_path(self.state_path.adding(), &adding_set_id, &None, true) + .await?; + Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - self.engine.last_vote_round = round; + async fn set_last_vote_round_inner(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert!(round > prev_value); + if round == prev_value { + return Ok(()); + } - Ok(()) + let round_obj = make_u64_obj(round); + + if prev_value == 0 { + self.op_env + .insert_with_path(self.state_path.last_vote_round(), &round_obj) + .await + } else { + let prev_obj = make_u64_obj(prev_value); + let prev_value = self + .op_env + .set_with_path( + self.state_path.last_vote_round(), + &round_obj, + &Some(prev_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_obj); + Ok(()) + } + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result.clone() + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result.clone() + } + + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self + .push_commit_inner( + height, + block_id, + result_state_id, + prev_result_state_id, + min_height, + ) + .await; + self.write_result.clone() + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.remove_prepares_inner(block_ids).await; + self.write_result.clone() + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.push_proposals_inner(proposal_ids, timestamp).await; + self.write_result.clone() + } + + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.set_last_vote_round_inner(round, prev_value).await; + self.write_result.clone() + } + + async fn commit(mut self) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + + let prepare_map_id = self.prepare_op_env.commit().await?; + self.op_env + .set_with_path( + self.state_path.prepares(), + &prepare_map_id, + &self.prepare_map_id, + self.prepare_map_id.is_none(), + ) + .await?; + self.op_env.commit().await.map(|_| ()) } } -impl<'a> Drop for StorageEngineGroupStateWriter<'a> { - fn drop(&mut self) {} +fn make_range_obj(min: u64, max: u64) -> ObjectId { + let mut range_buf = [0u8; 24]; + let (low, high) = range_buf.split_at_mut(12); + low.copy_from_slice(&min.to_le_bytes()); + high.copy_from_slice(&max.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() +} + +fn make_u64_obj(value: u64) -> ObjectId { + let mut range_buf = [0u8; 8]; + range_buf.copy_from_slice(&value.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 6208b0680..b944d3735 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -13,6 +13,7 @@ struct StorageEngineMockFinishProposalMgr { pub struct StorageEngineMock { last_vote_round: u64, + result_state_id: Option, block_height_range: (u64, u64), commit_blocks: HashMap, @@ -30,6 +31,7 @@ impl StorageEngineMock { commit_blocks: HashMap::new(), prepare_blocks: HashSet::new(), pre_commit_blocks: HashSet::new(), + result_state_id: None, finish_proposals: StorageEngineMockFinishProposalMgr { flip_timestamp: 0, over: HashSet::new(), @@ -108,7 +110,18 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + assert!(height > min_height); + assert_eq!(height, self.engine.block_height_range.1 + 1); + assert_eq!(prev_result_state_id, &self.engine.result_state_id); + if self .engine .commit_blocks @@ -123,6 +136,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } self.engine.block_height_range.1 = height; + self.engine.result_state_id = result_state_id.clone(); Ok(()) } @@ -143,12 +157,13 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if let Some(timestamp) = timestamp { + if let Some((timestamp, prev_timestamp)) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + assert_eq!(prev_timestamp, self.engine.finish_proposals.flip_timestamp); self.engine.finish_proposals.flip_timestamp = timestamp; } @@ -170,13 +185,14 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert_eq!(self.engine.last_vote_round, prev_value); self.engine.last_vote_round = round; Ok(()) } -} -impl<'a> Drop for StorageEngineMockWriter<'a> { - fn drop(&mut self) {} + async fn commit(mut self) -> BuckyResult<()> { + Ok(()) + } } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index bc9fc6009..a7284f403 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -13,7 +13,7 @@ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; +use super::{engine::StorageEngineMock, StorageEngine}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -42,15 +42,14 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, + group_chunk_id: ObjectId, dec_state_id: Option, // commited/header state id - group_chunk_id: ObjectId, last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, prepares: HashMap, pre_commits: HashMap, - finish_proposals: FinishProposalMgr, storage_engine: StorageEngineMock, @@ -258,7 +257,15 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit(new_header.height(), new_header.block_id().object_id()) + .push_commit( + new_header.height(), + new_header.block_id().object_id(), + new_header.result_state_id(), + self.header_block + .as_ref() + .map_or(&None, |b| b.result_state_id()), + self.first_block.as_ref().map_or(0, |b| b.height()), + ) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -272,7 +279,10 @@ impl GroupStorage { let timestamp = new_header.named_object().desc().create_time(); if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer - .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.finish_proposals.flip_timestamp)), + ) .await?; } else { writer @@ -281,6 +291,8 @@ impl GroupStorage { } } + writer.commit().await?; + // update memory if self .prepares @@ -293,7 +305,6 @@ impl GroupStorage { match new_header { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); - self.header_block = Some(new_header); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); self.prepares.remove(&new_pre_commit.0); @@ -309,7 +320,7 @@ impl GroupStorage { } if self.first_block.is_none() { - self.first_block = self.header_block.clone(); + self.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); @@ -325,6 +336,7 @@ impl GroupStorage { assert!(is_new); } + self.header_block = Some(new_header); return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -359,7 +371,9 @@ impl GroupStorage { // storage let mut writer = self.storage_engine.create_writer().await?; - writer.set_last_vote_round(round).await?; + writer + .set_last_vote_round(round, self.last_vote_round) + .await?; self.last_vote_round = round; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 2fb131a5a..23b3c6c4b 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -432,6 +432,7 @@ impl CyfsStackImpl { signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), + global_state_manager.clone_processor(), )?; let mut stack = Self { From 53789314c92357d09ccb7e89ec5fc8648c87f67d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 20:15:19 +0800 Subject: [PATCH 072/553] integrate GroupState load --- .../cyfs-group/src/dec/group_manager.rs | 12 +- .../src/storage/engine/storage_engine.rs | 37 ++++ .../engine/storage_engine_group_state.rs | 180 ++++++++++++++-- .../cyfs-group/src/storage/group_storage.rs | 198 ++++++++++-------- 4 files changed, 327 insertions(+), 100 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95c931720..5ecfcdba2 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -372,6 +372,7 @@ impl GroupManager { let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -379,7 +380,15 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; + let store = GroupStorage::load( + group_id, + dec_id, + rpath, + non_driver.clone(), + local_device_id.object_id().clone(), + &root_state_mgr, + ) + .await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -430,6 +439,7 @@ impl GroupManager { init_state, non_driver.clone(), local_device_id.object_id().clone(), + &root_state_mgr, ) .await? } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e19c46b81..735277a3a 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,4 +1,41 @@ +use std::collections::{HashMap, HashSet}; + use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct FinishProposalMgr { + pub flip_timestamp: u64, + pub over: HashSet, + pub adding: HashSet, +} + +pub struct StorageCacheInfo { + pub dec_state_id: Option, // commited/header state id + pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub header_block: Option, + pub first_block: Option, + pub prepares: HashMap, + pub pre_commits: HashMap, + pub finish_proposals: FinishProposalMgr, +} + +impl StorageCacheInfo { + pub fn new(init_state_id: Option) -> Self { + Self { + dec_state_id: init_state_id, + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 731725e95..ee429a78f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,16 +1,18 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, - ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, + ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_RANGE, }; -use super::{StorageEngine, StorageWriter}; +use super::{StorageCacheInfo, StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -21,14 +23,110 @@ pub struct StorageEngineGroupState { } impl StorageEngineGroupState { - pub async fn load( - dec_group_state: ObjectMapRootManagerRef, - state_path: GroupStatePath, - ) -> BuckyResult { - Ok(Self { - state_mgr: todo!(), + pub(crate) async fn load_cache( + state_mgr: &ObjectMapRootManagerRef, + non_driver: &NONDriverHelper, + state_path: &GroupStatePath, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; + + let last_vote_round = op_env + .get_by_path(state_path.last_vote_round()) + .await? + .map(|id| parse_u64_obj(&id)); + + let mut first_header_block_ids: Vec = vec![]; + let commit_range = op_env + .get_by_path(state_path.range()) + .await? + .map(|id| parse_range_obj(&id)); + let commit_block = match commit_range { + Some((first_height, header_height)) => { + let first_block_id = op_env + .get_by_path(state_path.commit_height(first_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(first_block_id); + + if header_height == first_height { + Some((first_block_id, first_block_id)) + } else { + let header_block_id = op_env + .get_by_path(state_path.commit_height(header_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(header_block_id); + Some((first_block_id, header_block_id)) + } + } + None => None, + }; + + let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let pre_commit_block_ids = + load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + + let flip_timestamp = op_env + .get_by_path(state_path.flip_time()) + .await? + .map_or(0, |id| parse_u64_obj(&id)); + + let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; + let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + + let load_block_ids = [ + first_header_block_ids.as_slice(), + prepare_block_ids.as_slice(), + pre_commit_block_ids.as_slice(), + ] + .concat(); + + let load_blocks = futures::future::join_all( + load_block_ids + .iter() + .map(|id| non_driver.get_block(id, None)), + ) + .await; + + let mut cache = StorageCacheInfo::new(dec_state_id); + cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); + cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); + cache.finish_proposals.flip_timestamp = flip_timestamp; + + let prepare_block_pos = match commit_block { + Some((first_block_id, header_block_id)) => { + cache.first_block = Some(load_blocks.get(0).unwrap().clone()?); + if header_block_id == first_block_id { + cache.header_block = cache.first_block.clone(); + 1 + } else { + cache.header_block = Some(load_blocks.get(1).unwrap().clone()?); + 2 + } + } + None => 0, + }; + + let (prepare_blocks, pre_commit_blocks) = + load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); + for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { + cache.prepares.insert(block_id, block.clone()?); + } + for (block, block_id) in pre_commit_blocks.iter().zip(pre_commit_block_ids) { + cache.pre_commits.insert(block_id, block.clone()?); + } + + Ok(cache) + } + + pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + Self { + state_mgr, state_path: Arc::new(state_path), - }) + } } pub async fn create_writer(&self) -> BuckyResult { @@ -132,12 +230,14 @@ impl StorageEngineGroupStateWriter { .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) .await?; - let range_obj = make_range_obj(min_height, height); if height == 1 { + let range_obj = make_range_obj(1, height); self.op_env .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) .await?; } else { + assert!(min_height < height); + let range_obj = make_range_obj(min_height, height); let prev_range = make_range_obj(min_height, height - 1); let prev_value = self .op_env @@ -376,13 +476,63 @@ impl StorageWriter for StorageEngineGroupStateWriter { fn make_range_obj(min: u64, max: u64) -> ObjectId { let mut range_buf = [0u8; 24]; let (low, high) = range_buf.split_at_mut(12); - low.copy_from_slice(&min.to_le_bytes()); - high.copy_from_slice(&max.to_le_bytes()); + low[..8].copy_from_slice(&min.to_le_bytes()); + high[..8].copy_from_slice(&max.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } +fn parse_range_obj(obj: &ObjectId) -> (u64, u64) { + let range_buf = obj.data(); + assert_eq!(range_buf.len(), 24); + let (low_buf, high_buf) = range_buf.split_at(12); + let mut low = [0u8; 8]; + low.copy_from_slice(&low_buf[..8]); + let mut high = [0u8; 8]; + high.copy_from_slice(&high_buf[..8]); + + (u64::from_le_bytes(low), u64::from_le_bytes(high)) +} + fn make_u64_obj(value: u64) -> ObjectId { let mut range_buf = [0u8; 8]; range_buf.copy_from_slice(&value.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } + +fn parse_u64_obj(obj: &ObjectId) -> u64 { + let mut buf = [0u8; 8]; + buf.copy_from_slice(obj.data()); + u64::from_le_bytes(buf) +} + +async fn load_object_ids_with_path( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Set(id) => object_ids.push(id.clone()), + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a7284f403..5ad19ea15 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -11,9 +11,14 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::GlobalStateManagerRawProcessorRef; -use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; +use crate::{ + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, +}; -use super::{engine::StorageEngineMock, StorageEngine}; +use super::{ + engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + StorageEngine, +}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -29,12 +34,6 @@ pub enum BlockLinkState { InvalidBranch, } -struct FinishProposalMgr { - flip_timestamp: u64, - over: HashSet, - adding: HashSet, -} - pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -44,15 +43,9 @@ pub struct GroupStorage { non_driver: NONDriverHelper, group_chunk_id: ObjectId, - dec_state_id: Option, // commited/header state id - last_vote_round: u64, // 参与投票的最后一个轮次 - header_block: Option, - first_block: Option, - prepares: HashMap, - pre_commits: HashMap, - finish_proposals: FinishProposalMgr, + cache: StorageCacheInfo, - storage_engine: StorageEngineMock, + storage_engine: StorageEngineGroupState, } impl GroupStorage { @@ -63,18 +56,18 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); - // let group_state = root_state_mgr - // .load_root_state(group_id, Some(group_id.clone()), true) - // .await? - // .expect("create group state failed."); + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); - // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; Ok(Self { group, @@ -82,20 +75,13 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - dec_state_id: init_state_id, group_chunk_id: group_chunk_id.object_id(), - last_vote_round: 0, - header_block: None, - first_block: None, - prepares: HashMap::new(), - pre_commits: HashMap::new(), - storage_engine: StorageEngineMock::new(), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + GroupStatePath::new(rpath.to_string()), + ), local_device_id, - finish_proposals: FinishProposalMgr { - flip_timestamp: 0, - over: HashSet::new(), - adding: HashSet::new(), - }, + cache: StorageCacheInfo::new(init_state_id), }) } @@ -104,37 +90,62 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - // unimplemented!() - Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); + + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + + let state_path = GroupStatePath::new(rpath.to_string()); + let cache = + StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + group_chunk_id: group_chunk_id.object_id(), + storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + local_device_id, + cache: cache, + }) } pub fn header_block(&self) -> &Option { - &self.header_block + &self.cache.header_block } pub fn header_round(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.round()) + self.cache.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.height()) + self.cache.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - &self.first_block + &self.cache.first_block } pub fn prepares(&self) -> &HashMap { - &self.prepares + &self.cache.prepares } pub fn pre_commits(&self) -> &HashMap { - &self.pre_commits + &self.cache.pre_commits } pub fn group(&self) -> &Group { @@ -146,34 +157,37 @@ impl GroupStorage { } pub fn dec_state_id(&self) -> &Option { - &self.dec_state_id + &self.cache.dec_state_id } pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { let header_height = self.header_height(); let block = match height.cmp(&header_height) { std::cmp::Ordering::Less => { - if height == self.first_block.as_ref().map_or(0, |b| b.height()) { - self.first_block.clone() + if height == self.cache.first_block.as_ref().map_or(0, |b| b.height()) { + self.cache.first_block.clone() } else { // find in storage let block_id = self.storage_engine.find_block_by_height(height).await?; Some(self.non_driver.get_block(&block_id, None).await?) } } - std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Equal => self.cache.header_block.clone(), std::cmp::Ordering::Greater => { if height == header_height + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.height() == height) .or(self + .cache .prepares .iter() .find(|(_, block)| block.height() == height)) .map(|(_, block)| block.clone()) } else if height == header_height + 2 { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.height() == height) .map(|(_, block)| block.clone()) @@ -202,16 +216,17 @@ impl GroupStorage { // prepare update memory if let Some(prev_block_id) = prev_block_id { - if let Some(prev_block) = self.prepares.get(prev_block_id) { + if let Some(prev_block) = self.cache.prepares.get(prev_block_id) { new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); if let Some(prev_prev_block_id) = prev_block.prev_block_id() { - if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + if let Some(prev_prev_block) = self.cache.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); assert_eq!( prev_prev_block.prev_block_id(), - self.header_block + self.cache + .header_block .as_ref() .map(|b| b.block_id().object_id().clone()) .as_ref() @@ -220,7 +235,7 @@ impl GroupStorage { new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.block_id().object_id(); - for (id, block) in self.prepares.iter() { + for (id, block) in self.cache.prepares.iter() { if block.prev_block_id().map(|prev_id| { assert_ne!(prev_id, prev_block_id); prev_id == new_header_id @@ -261,10 +276,11 @@ impl GroupStorage { new_header.height(), new_header.block_id().object_id(), new_header.result_state_id(), - self.header_block + self.cache + .header_block .as_ref() .map_or(&None, |b| b.result_state_id()), - self.first_block.as_ref().map_or(0, |b| b.height()), + self.cache.first_block.as_ref().map_or(0, |b| b.height()), ) .await?; @@ -277,11 +293,11 @@ impl GroupStorage { .collect(); let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer .push_proposals( finish_proposals.as_slice(), - Some((timestamp, self.finish_proposals.flip_timestamp)), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), ) .await?; } else { @@ -295,6 +311,7 @@ impl GroupStorage { // update memory if self + .cache .prepares .insert(block_id.object_id().clone(), block) .is_some() @@ -304,53 +321,60 @@ impl GroupStorage { match new_header { Some(new_header) => { - self.dec_state_id = new_header.result_state_id().clone(); + self.cache.dec_state_id = new_header.result_state_id().clone(); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); - self.prepares.remove(&new_pre_commit.0); + self.cache.prepares.remove(&new_pre_commit.0); let mut removed_blocks = HashMap::from([new_pre_commit]); - std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + std::mem::swap(&mut self.cache.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = removed_blocks.into_values().collect(); for id in remove_prepares.iter() { - removed_blocks.push(self.prepares.remove(id).unwrap()); + removed_blocks.push(self.cache.prepares.remove(id).unwrap()); } - if self.first_block.is_none() { - self.first_block = Some(new_header.clone()); + if self.cache.first_block.is_none() { + self.cache.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MS + { let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.finish_proposals.over); - self.finish_proposals.flip_timestamp = timestamp; + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; } for proposal in new_header.proposals() { - let is_new = self.finish_proposals.adding.insert(proposal.proposal); + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); assert!(is_new); } - self.header_block = Some(new_header); - return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + self.cache.header_block = Some(new_header); + return Ok(Some(( + self.cache.header_block.as_ref().unwrap(), + removed_blocks, + ))); } None => { if let Some(new_pre_commit) = new_pre_commit { assert!(remove_prepares.is_empty()); if self + .cache .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) .is_some() { assert!(false); } - self.prepares + self.cache + .prepares .remove(&new_pre_commit.0) .expect("any block in pre-commit should be from prepare"); } @@ -361,21 +385,21 @@ impl GroupStorage { } pub fn last_vote_round(&self) -> u64 { - self.last_vote_round + self.cache.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - if round <= self.last_vote_round { + if round <= self.cache.last_vote_round { return Ok(()); } // storage let mut writer = self.storage_engine.create_writer().await?; writer - .set_last_vote_round(round, self.last_vote_round) + .set_last_vote_round(round, self.cache.last_vote_round) .await?; - self.last_vote_round = round; + self.cache.last_vote_round = round; Ok(()) } @@ -533,15 +557,16 @@ impl GroupStorage { } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { - if let Some(block) = self.header_block.as_ref() { + if let Some(block) = self.cache.header_block.as_ref() { if block.block_id().object_id() == block_id { return Ok(block.clone()); } } - self.prepares + self.cache + .prepares .get(block_id) - .or(self.pre_commits.get(block_id)) + .or(self.cache.pre_commits.get(block_id)) .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) .map(|block| block.clone()) } @@ -553,20 +578,24 @@ impl GroupStorage { std::cmp::Ordering::Less => { return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Equal => self.cache.header_block.as_ref(), std::cmp::Ordering::Greater => if round == header_round + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .prepares .iter() .find(|(_, block)| block.round() == round)) } else { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .pre_commits .iter() .find(|(_, block)| block.round() == round)) @@ -615,10 +644,11 @@ impl GroupStorage { // find in storage let is_finished = self + .cache .finish_proposals .adding .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) + .or(self.cache.finish_proposals.over.get(proposal_id)) .is_some(); Ok(is_finished) } @@ -647,7 +677,7 @@ impl GroupStorage { &self, round: u64, ) -> (BuckyResult, Vec) { - if self.header_block.is_none() { + if self.cache.header_block.is_none() { return ( Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), vec![], @@ -655,7 +685,7 @@ impl GroupStorage { } let mut blocks = vec![]; - let mut block = self.header_block.clone().unwrap(); + let mut block = self.cache.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; let mut max_height = block.height(); From df9220f59d8ffcf676a37f06dae8ea446624ad91 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 15:20:55 +0800 Subject: [PATCH 073/553] update example for GroupState --- src/tests/group-example/src/main.rs | 479 +++++++++++++++++++--------- 1 file changed, 332 insertions(+), 147 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ffb45ccec..e7948f740 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -3,27 +3,28 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, }; use cyfs_stack::CyfsStack; -use Common::{ - create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, - EXAMPLE_RPATH, -}; +use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; + mod Common { - use std::sync::Arc; + use std::{fmt::format, io::ErrorKind, sync::Arc}; + use async_std::{fs, stream::StreamExt}; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, - UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -35,113 +36,109 @@ mod Common { CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, }; - use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members( + fn create_member( name_prefix: &str, - count: usize, - ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + index: usize, + port: u16, + ) -> ((People, PrivateKey), (Device, PrivateKey)) { log::info!("create members"); - let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); - let mut members = vec![]; + let name = format!("{}-{}", name_prefix, index); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); + endpoint.mut_addr().set_port(port); + endpoint.set_area(EndpointArea::Wan); + + let mut device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + device_private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); - for i in 0..count { - let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_rsa(1024).unwrap(); - let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); - let mut owner = - People::new(None, vec![], private_key.public(), None, Some(name), None).build(); - - let mut endpoint = Endpoint::default(); - endpoint.set_protocol(Protocol::Udp); - endpoint - .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); - endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_area(EndpointArea::Wan); - - let mut device = Device::new( - Some(owner.desc().object_id()), - UniqueId::create_with_random(), - vec![endpoint], - vec![], // TODO: 当前版本是否支持无SN? - vec![], - device_private_key.public(), - Area::default(), - DeviceCategory::PC, - ) - .build(); - - owner - .ood_list_mut() - .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - - let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); - let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); - let device_desc_hash = device.desc().raw_hash_value().unwrap(); - let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); - - let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = - async_std::task::block_on(async move { - let owner_desc_signature = signer - .sign( - owner_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let owner_body_signature = signer - .sign( - owner_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let desc_signature = signer - .sign( - device_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - let body_signature = signer - .sign( - device_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - ( - owner_desc_signature, - owner_body_signature, - desc_signature, - body_signature, + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), ) - }); + .await + .unwrap(); - device.signs_mut().set_desc_sign(desc_signature.clone()); - device.signs_mut().set_body_sign(body_signature); + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); - log::info!( + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", owner.name().unwrap(), owner.desc().object_id(), @@ -152,12 +149,9 @@ mod Common { owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() ); - owner.signs_mut().set_desc_sign(owner_desc_signature); - owner.signs_mut().set_body_sign(owner_body_signature); - members.push(((owner, private_key), (device, device_private_key))); - } - - members + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + ((owner, private_key), (device, device_private_key)) } fn create_group( @@ -194,16 +188,167 @@ mod Common { group } + // (succ, not-found) + fn check_read_buf(file_path: &str, result: &std::io::Result>) -> (bool, bool) { + match result.as_ref() { + Ok(b) => { + if b.len() == 0 { + (false, true) + } else { + (true, false) + } + } + Err(err) if ErrorKind::NotFound == err.kind() => (false, true), + Err(err) => { + log::warn!("read file {} failed: {:?}", file_path, err); + (false, false) + } + } + } + + async fn init_member_from_dir( + save_path: &str, + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + fs::create_dir_all(save_path) + .await + .expect(format!("create dir {} failed", save_path).as_str()); + + let min_port = 30217_u16; + + let mut members = vec![]; + + for i in 0..count { + let index = i + 1; + let people_desc_file_path = format!("{}/people-{}.desc", save_path, index); + let people_sec_file_path = format!("{}/people-{}.sec", save_path, index); + let device_desc_file_path = format!("{}/device-{}.desc", save_path, index); + let device_sec_file_path = format!("{}/device-{}.sec", save_path, index); + + let people_desc_r = fs::read(people_desc_file_path.clone()).await; + let people_sec_r = fs::read(people_sec_file_path.clone()).await; + let device_desc_r = fs::read(device_desc_file_path.clone()).await; + let device_sec_r = fs::read(device_sec_file_path.clone()).await; + + let (is_people_desc_succ, is_people_desc_not_found) = + check_read_buf(people_desc_file_path.as_str(), &people_desc_r); + let (is_people_sec_succ, is_people_sec_not_found) = + check_read_buf(people_sec_file_path.as_str(), &people_sec_r); + let (is_device_desc_succ, is_device_desc_not_found) = + check_read_buf(device_desc_file_path.as_str(), &device_desc_r); + let (is_device_sec_succ, is_device_sec_not_found) = + check_read_buf(device_sec_file_path.as_str(), &device_sec_r); + + if is_people_desc_succ + && is_people_sec_succ + && is_device_desc_succ + && is_device_sec_succ + { + // decode + let people_desc = People::raw_decode(people_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_desc_file_path).as_str()) + .0; + let people_sec = PrivateKey::raw_decode(people_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_sec_file_path).as_str()) + .0; + let device_desc = Device::raw_decode(device_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_desc_file_path).as_str()) + .0; + let device_sec = PrivateKey::raw_decode(device_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_sec_file_path).as_str()) + .0; + members.push(((people_desc, people_sec), (device_desc, device_sec))); + } else if is_people_desc_not_found + && is_people_sec_not_found + && is_device_desc_not_found + && is_device_sec_not_found + { + // create & save + let member = create_member(name_prefix, index, min_port + i as u16); + fs::write( + people_desc_file_path.as_str(), + member.0 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", people_desc_file_path).as_str()); + fs::write(people_sec_file_path.as_str(), member.0 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", people_sec_file_path).as_str()); + fs::write( + device_desc_file_path.as_str(), + member.1 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", device_desc_file_path).as_str()); + fs::write(device_sec_file_path.as_str(), member.1 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", device_sec_file_path).as_str()); + + members.push(member); + } else { + println!("read members failed!"); + std::process::exit(-1); + } + } + + members + } + + pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/admins", "admin", 4).await + } + + pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/members", "member", 9).await + } + + pub async fn init_group( + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + fs::create_dir_all("./test-group") + .await + .expect("create dir ./test-group failed"); + + let read_group_r = fs::read("./test-group/group.desc").await; + match read_group_r { + Ok(buf) => { + if buf.len() > 0 { + return Group::raw_decode(buf.as_slice()) + .expect("decode ./test-group/group.desc failed") + .0; + } + } + Err(err) => { + if ErrorKind::NotFound != err.kind() { + println!("read group failed: {:?}", err); + std::process::exit(-1); + } + } + } + + let group = create_group(admins.get(0).unwrap(), admins, members, oods); + fs::write("./test-group/group.desc", group.to_vec().unwrap()) + .await + .expect("save file ./test-group/group.desc failed"); + group + } + fn init_stack_params( people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); - let mut member_device: Vec = - EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); + let mut admin_device: Vec = admins.iter().map(|m| m.1.clone()).collect(); + let mut member_device: Vec = members.iter().map(|m| m.1.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { @@ -242,7 +387,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { + for (member, device) in admins.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -260,7 +405,7 @@ mod Common { )); } - for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { + for (member, device) in members.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -279,17 +424,17 @@ mod Common { } known_objects.list.push(NONObjectInfo::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_GROUP.to_vec().unwrap(), + group.desc().object_id(), + group.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( - EXAMPLE_GROUP.clone(), + group.clone(), )))), )); - let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( - EXAMPLE_DEC_APP.desc().object_id(), + dec_app.desc().object_id(), dec_app_vec, Some(Arc::new(AnyNamedObject::Core(typeless))), )); @@ -301,8 +446,13 @@ mod Common { people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> CyfsStack { - let params = init_stack_params(people, private_key, device); + let params = + init_stack_params(people, private_key, device, admins, members, group, dec_app); log::info!("cyfs-stack.open"); @@ -316,10 +466,6 @@ mod Common { stack } - - pub fn dummy(people: People, device: Device) { - log::info!("common::dummy"); - } } mod Client { @@ -352,22 +498,21 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + GroupProposalObject, }; use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; use cyfs_stack::CyfsStack; - use crate::Common::EXAMPLE_DEC_APP_ID; - pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { let group_mgr = cyfs_stack.group_mgr(); group_mgr .register( - EXAMPLE_DEC_APP_ID.clone(), + dec_app_id.clone(), Box::new(GroupRPathDelegateFactory { local_name }), ) .await @@ -575,13 +720,14 @@ mod GroupDecService { } } -fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { +fn create_proposal( + delta: u64, + owner: ObjectId, + group_id: ObjectId, + dec_id: ObjectId, +) -> GroupProposal { GroupProposal::create( - GroupRPath::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id().clone(), - EXAMPLE_RPATH.clone(), - ), + GroupRPath::new(group_id, dec_id, EXAMPLE_RPATH.to_string()), "add".to_string(), Some(Vec::from(delta.to_be_bytes())), None, @@ -614,23 +760,57 @@ async fn main_run() { log::info!("will open stacks"); + let admins = init_admins().await; + let members = init_members().await; + let group = init_group( + admins.iter().map(|m| &m.0 .0).collect(), + members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| &m.1 .0).collect(), + ) + .await; + let group_id = group.desc().object_id(); + let dec_app = DecApp::create( + admins.get(0).unwrap().0 .0.desc().object_id(), + EXAMPLE_APP_NAME.as_str(), + ); + let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); + let mut admin_stacks: Vec = vec![]; - for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { - // dummy(admin.clone(), device.clone()); - let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; + for ((admin, _), (device, private_key)) in admins.iter() { + let cyfs_stack = create_stack( + admin.clone(), + private_key, + device.clone(), + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + group.clone(), + dec_app.clone(), + ) + .await; admin_stacks.push(cyfs_stack); } for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); - DecService::run(&stack, admin.name().unwrap().to_string()).await; + let ((admin, _), _) = admins.get(i).unwrap(); + DecService::run( + &stack, + admin.name().unwrap().to_string(), + dec_app_id.clone(), + ) + .await; let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group.desc().object_id(), + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -647,14 +827,19 @@ async fn main_run() { let PROPOSAL_COUNT = 1000usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; - let proposal = create_proposal(i as u64, owner.desc().object_id()); + let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let proposal = create_proposal( + i as u64, + owner.desc().object_id(), + group_id, + dec_app_id.object_id().clone(), + ); let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -676,7 +861,7 @@ async fn main_run() { zone: None, zone_category: DeviceZoneCategory::CurrentDevice, }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + dec: dec_app_id.object_id().clone(), verified: None, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), @@ -700,8 +885,8 @@ async fn main_run() { let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) From 0e6a1a680b6173a1f4de7991129b880b2899da74 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 17:36:21 +0800 Subject: [PATCH 074/553] fix: path error --- .../src/statepath/group_statepath.rs | 13 ++++++++-- src/tests/group-example/src/main.rs | 26 +++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eade0f9e4..280fb6948 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -39,51 +39,60 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_GROUP_BLOB, ]), last_vote_round: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), range: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_RANGE, ]), prepares: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PREPARES, ]), pre_commits: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PRE_COMMITS, ]), finish_proposals: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, ]), flip_time: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_FLIP_TIME, ]), recycle: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_RECYCLE, ]), adding: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e7948f740..e29b1be6d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -337,13 +337,13 @@ mod Common { } fn init_stack_params( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -443,13 +443,13 @@ mod Common { } pub async fn create_stack( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> CyfsStack { let params = init_stack_params(people, private_key, device, admins, members, group, dec_app); @@ -778,9 +778,9 @@ async fn main_run() { let mut admin_stacks: Vec = vec![]; for ((admin, _), (device, private_key)) in admins.iter() { let cyfs_stack = create_stack( - admin.clone(), + admin, private_key, - device.clone(), + device, admins .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) @@ -789,8 +789,8 @@ async fn main_run() { .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) .collect(), - group.clone(), - dec_app.clone(), + &group, + &dec_app, ) .await; admin_stacks.push(cyfs_stack); @@ -898,7 +898,7 @@ async fn main_run() { }); if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(200)).await; + async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } From 2de12ea5f219c72fa3338944167a799e9cc78215 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 18:34:11 +0800 Subject: [PATCH 075/553] fix: commit storage --- src/component/cyfs-group/src/storage/group_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 5ad19ea15..30fc08cad 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -398,6 +398,7 @@ impl GroupStorage { writer .set_last_vote_round(round, self.cache.last_vote_round) .await?; + writer.commit().await?; self.cache.last_vote_round = round; From c9cc2d32a08d06283f85cd75f92019da991071b5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 076/553] fix: type of pre-commits --- .../cyfs-group/src/dec/group_manager.rs | 21 ++++++++++--------- .../engine/storage_engine_group_state.rs | 20 +++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5ecfcdba2..7ba376368 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,16 +289,17 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - let rpath = header_block.r_path(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::StateChangeNotify(header_block, qc_block), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = header_block.r_path(); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::StateChangeNotify(header_block, qc_block), + // remote, + // ) + // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index ee429a78f..c6acb7b52 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,7 +5,6 @@ use cyfs_base::{ ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -213,9 +212,11 @@ impl StorageEngineGroupStateWriter { .await?; } - self.op_env - .insert_with_path(self.state_path.pre_commits(), block_id) - .await + let is_changed = self.op_env + .insert(self.state_path.pre_commits(), block_id) + .await?; + assert!(is_changed); + Ok(()) } async fn push_commit_inner( @@ -469,7 +470,16 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.prepare_map_id.is_none(), ) .await?; - self.op_env.commit().await.map(|_| ()) + self.op_env.commit().await.map_or_else( + |err| { + if err.code() == BuckyErrorCode::AlreadyExists { + Ok(()) + } else { + Err(err) + } + }, + |_| Ok(()), + ) } } From b4d5c48b7731d348f7f5cda6b63f4823b3908510 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:42:12 +0800 Subject: [PATCH 077/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e29b1be6d..316630f6a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: None, + isolate: Some(device.desc().object_id()), sync_service: false, shared_stack: false, }, From 2d7aa655fb1cac2209963063d5958a2d647230d1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:49:08 +0800 Subject: [PATCH 078/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 316630f6a..d69fcae2d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: Some(device.desc().object_id()), + isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: false, }, From 8d204b06b6e12e699ab163a38f6a76d684ec8050 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 21 Feb 2023 19:52:57 +0800 Subject: [PATCH 079/553] fix: the round for the first block when restart --- src/component/cyfs-core/src/coreobj.rs | 1 + .../src/group/group_quorum_certificate.rs | 144 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 2 + .../src/consensus/hotstuff/hotstuff.rs | 60 +++++++- .../cyfs-group/src/dec/group_manager.rs | 34 +++-- .../cyfs-group/src/network/non_driver.rs | 30 +++- .../cyfs-group/src/statepath/design.md | 1 + .../src/statepath/group_statepath.rs | 16 +- .../src/storage/engine/storage_engine.rs | 5 +- .../engine/storage_engine_group_state.rs | 130 ++++++++++++---- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 136 ++++++++++++----- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- src/tests/group-example/src/main.rs | 24 +-- 14 files changed, 493 insertions(+), 100 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_quorum_certificate.rs diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 724f0debb..30bf0e013 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupRPathStatus = 703, GroupAction = 704, + GroupQuorumCertificate = 705, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs new file mode 100644 index 000000000..7c3ad77fc --- /dev/null +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -0,0 +1,144 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, DescContent, EmptyBodyContent, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBuilder, NamedObjectId, RawDecode, RawEncode, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_RAW, +}; + +use crate::{CoreObjectType, HotstuffBlockQC, HotstuffTimeout}; + +#[derive(Clone)] +pub enum GroupQuorumCertificateDescContent { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), +} + +impl DescContent for GroupQuorumCertificateDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupQuorumCertificate as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupQuorumCertificateDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +pub type GroupQuorumCertificateType = + NamedObjType; +pub type GroupQuorumCertificateBuilder = + NamedObjectBuilder; + +pub type GroupQuorumCertificateId = NamedObjectId; +pub type GroupQuorumCertificate = NamedObjectBase; + +pub trait GroupQuorumCertificateObject { + fn quorum_round(&self) -> u64; +} + +impl GroupQuorumCertificateObject for GroupQuorumCertificate { + fn quorum_round(&self) -> u64 { + match self.desc().content() { + GroupQuorumCertificateDescContent::QC(qc) => qc.round, + GroupQuorumCertificateDescContent::TC(tc) => tc.round, + } + } +} + +impl RawEncode for GroupQuorumCertificateDescContent { + fn raw_measure( + &self, + purpose: &Option, + ) -> cyfs_base::BuckyResult { + let len = match self { + GroupQuorumCertificateDescContent::QC(qc) => qc.raw_measure(purpose)?, + GroupQuorumCertificateDescContent::TC(tc) => tc.raw_measure(purpose)?, + }; + + Ok(len + 1) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> cyfs_base::BuckyResult<&'a mut [u8]> { + match self { + GroupQuorumCertificateDescContent::QC(qc) => { + buf[0] = 0; + let buf = &mut buf[1..]; + qc.raw_encode(buf, purpose) + } + GroupQuorumCertificateDescContent::TC(tc) => { + buf[0] = 1; + let buf = &mut buf[1..]; + tc.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for GroupQuorumCertificateDescContent { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let obj_type = buf[0]; + let buf = &buf[1..]; + match obj_type { + 0 => { + let (qc, remain) = HotstuffBlockQC::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::QC(qc), remain)) + } + 1 => { + let (qc, remain) = HotstuffTimeout::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::TC(qc), remain)) + } + _ => Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown qc")), + } + } +} + +impl From for GroupQuorumCertificate { + fn from(qc: HotstuffBlockQC) -> Self { + let desc = GroupQuorumCertificateDescContent::QC(qc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl From for GroupQuorumCertificate { + fn from(tc: HotstuffTimeout) -> Self { + let desc = GroupQuorumCertificateDescContent::TC(tc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::QC(qc) => Ok(qc), + GroupQuorumCertificateDescContent::TC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is tc, expect qc")) + } + } + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::TC(tc) => Ok(tc), + GroupQuorumCertificateDescContent::QC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is qc, expect tc")) + } + } + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4c315c090..c153ab1ba 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,6 +1,7 @@ mod group_consensus_block; mod group_proposal; mod group_proposal_decide_param; +mod group_quorum_certificate; mod group_rpath; mod group_rpath_status; mod group_update_group_proposal_param; @@ -8,6 +9,7 @@ mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; pub use group_proposal_decide_param::*; +pub use group_quorum_certificate::*; pub use group_rpath::*; pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e89498b83..7868a7f90 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,7 +9,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; @@ -238,11 +238,36 @@ impl HotstuffRunner { rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); + let last_qc = store.last_qc(); + let (tc, qc) = last_qc + .as_ref() + .map_or((None, None), |qc| { + match qc.desc().content() { + cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), + cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), + } + }); - let round = store - .last_vote_round() - .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let last_vote_round = store + .last_vote_round(); + let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); + let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); + + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" + , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + + let max_round_qc_round = max_round_block + .as_ref() + .map_or(0, |block| + block.qc().as_ref().map_or(0, |qc| qc.round) + ); + let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); + let high_qc = if max_round_qc_round >= last_qc_round { + max_round_block.map_or(None, |b| b.qc().clone()) + } else { + qc + }; let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); @@ -277,7 +302,7 @@ impl HotstuffRunner { rpath, proposal_consumer, rx_proposal_waiter: None, - tc: None, + tc, state_pusher, tx_block_gen, rx_block_gen, @@ -627,6 +652,16 @@ impl HotstuffRunner { * 验证过的块执行这个函数 */ + if let Err(err) = self.non_driver.put_block(block).await { + if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + log::warn!( + "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", + self, block.block_id(), block.height(), block.round() + ); + return Err(err); + } + } + log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", self, block.block_id(), block.height(), block.round() @@ -1072,6 +1107,10 @@ impl HotstuffRunner { let qc_round = qc.round; let qc_prev_block_id = qc.prev_block_id; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); + + self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.process_qc(&Some(qc)).await; let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { @@ -1211,10 +1250,14 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", @@ -1324,6 +1367,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1814,6 +1861,7 @@ impl HotstuffRunner { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id + && max_round_block.round() == self.round && latest_group.is_ok() && last_group.is_ok() && last_group diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7ba376368..70fb10ba6 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -302,22 +302,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.r_path(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); @@ -397,6 +398,7 @@ impl GroupManager { return Err(e); } if let BuckyErrorCode::NotFound = e.code() { + log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); None } else { return Err(e); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4212a0355..979451b79 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,7 +7,9 @@ use cyfs_base::{ TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, +}; use cyfs_lib::NONObjectInfo; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -106,6 +108,32 @@ impl NONDriverHelper { Ok(()) } + pub async fn get_qc( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupQuorumCertificate::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn put_qc(&self, qc: &GroupQuorumCertificate) -> BuckyResult<()> { + let buf = qc.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let qc = NONObjectInfo { + object_id: qc.desc().object_id(), + object_raw: qc.to_vec()?, + object: Some(block_any), + }; + self.put_object(qc).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 70a61e428..cb964e066 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -23,6 +23,7 @@ | | |--${user-id} | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 280fb6948..0e6a887b0 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -5,6 +5,7 @@ pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -23,10 +24,12 @@ lazy_static::lazy_static! { pub struct GroupStatePath { rpath: String, + root: String, dec_state: String, link: String, group_blob: String, last_vote_round: String, + last_qc: String, range: String, prepares: String, pre_commits: String, @@ -39,6 +42,7 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { + root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ @@ -53,6 +57,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), + last_qc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_QC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -107,7 +117,7 @@ impl GroupStatePath { } pub fn root(&self) -> &str { - self.rpath.as_str() + self.root.as_str() } pub fn dec_state(&self) -> &str { @@ -126,6 +136,10 @@ impl GroupStatePath { self.last_vote_round.as_str() } + pub fn last_qc(&self) -> &str { + self.last_qc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index 735277a3a..aebf6fb96 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,6 +12,7 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub last_qc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -33,6 +34,7 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, + last_qc: None, } } } @@ -58,6 +60,7 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index c6acb7b52..2b61dbc47 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, }; use crate::{ @@ -27,26 +27,35 @@ impl StorageEngineGroupState { non_driver: &NONDriverHelper, state_path: &GroupStatePath, ) -> BuckyResult { - let op_env = state_mgr.create_op_env(ACCESS)?; - - let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; - - let last_vote_round = op_env - .get_by_path(state_path.last_vote_round()) - .await? - .map(|id| parse_u64_obj(&id)); + let op_env = state_mgr.create_op_env(ACCESS).map_err(|err| { + log::warn!("create_op_env failed {:?}", err); + err + })?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await; + let dec_state_id = map_not_found_option_to_option(dec_state_id)?; + + let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; + let last_vote_round = + map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; + let last_qc = map_not_found_option_to_option(last_qc)?; + let last_qc = match last_qc.as_ref() { + Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + None => None, + }; let mut first_header_block_ids: Vec = vec![]; - let commit_range = op_env - .get_by_path(state_path.range()) - .await? - .map(|id| parse_range_obj(&id)); + let commit_range = op_env.get_by_path(state_path.range()).await; + let commit_range = + map_not_found_option_to_option(commit_range)?.map(|id| parse_range_obj(&id)); let commit_block = match commit_range { Some((first_height, header_height)) => { let first_block_id = op_env .get_by_path(state_path.commit_height(first_height).as_str()) - .await? - .expect("first block is lost"); + .await; + let first_block_id = + map_not_found_option_to_option(first_block_id)?.expect("first block is lost"); first_header_block_ids.push(first_block_id); if header_height == first_height { @@ -54,7 +63,8 @@ impl StorageEngineGroupState { } else { let header_block_id = op_env .get_by_path(state_path.commit_height(header_height).as_str()) - .await? + .await; + let header_block_id = map_not_found_option_to_option(header_block_id)? .expect("first block is lost"); first_header_block_ids.push(header_block_id); Some((first_block_id, header_block_id)) @@ -64,13 +74,27 @@ impl StorageEngineGroupState { }; let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + if prepare_block_ids.len() == 0 && commit_range.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "not found in storage", + )); + } + let pre_commit_block_ids = load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; - let flip_timestamp = op_env - .get_by_path(state_path.flip_time()) - .await? - .map_or(0, |id| parse_u64_obj(&id)); + let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; + let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { + let n = parse_u64_obj(&id); + // log::debug!( + // "load flip timestamp {}/{} -> {}", + // id, + // id.to_hex().unwrap(), + // n + // ); + n + }); let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; @@ -82,15 +106,18 @@ impl StorageEngineGroupState { ] .concat(); - let load_blocks = futures::future::join_all( - load_block_ids - .iter() - .map(|id| non_driver.get_block(id, None)), - ) + let load_blocks = futures::future::join_all(load_block_ids.iter().map(|id| async { + let id = id.clone(); + non_driver.get_block(&id, None).await.map_err(|err| { + log::warn!("get block {} failed {:?}", id, err); + err + }) + })) .await; let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.last_qc = last_qc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -212,7 +239,8 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self.op_env + let is_changed = self + .op_env .insert(self.state_path.pre_commits(), block_id) .await?; assert!(is_changed); @@ -326,6 +354,15 @@ impl StorageEngineGroupStateWriter { let timestamp_obj = make_u64_obj(timestamp); if prev_timestamp != 0 { let prev_timestamp_obj = make_u64_obj(prev_timestamp); + // log::debug!( + // "will update flip-time from {} -> {}/{} to {} -> {}/{}", + // prev_timestamp, + // prev_timestamp_obj, + // prev_timestamp_obj.to_hex().unwrap(), + // timestamp, + // timestamp_obj, + // timestamp_obj.to_hex().unwrap(), + // ); let prev_value = self .op_env .set_with_path( @@ -337,6 +374,7 @@ impl StorageEngineGroupStateWriter { .await?; assert_eq!(prev_value.unwrap(), prev_timestamp_obj); } else { + // log::debug!("will update flip-time from None to {}", timestamp); self.op_env .insert_with_key( self.state_path.finish_proposals(), @@ -395,6 +433,13 @@ impl StorageEngineGroupStateWriter { Ok(()) } } + + async fn save_last_qc_inner(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_qc(), qc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -458,6 +503,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_qc_inner(qc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; @@ -522,6 +573,7 @@ async fn load_object_ids_with_path( let content = match op_env.list(full_path).await { Ok(content) => content, Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); if err.code() == BuckyErrorCode::NotFound { return Ok(vec![]); } else { @@ -546,3 +598,29 @@ async fn load_object_ids_with_path( Ok(object_ids) } + +fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { + match r { + Ok(t) => Ok(Some(t)), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} + +fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult> { + match r { + Ok(t) => Ok(t), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b944d3735..79491b186 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -192,6 +192,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 30fc08cad..3f9fc9910 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -8,7 +8,10 @@ use cyfs_base::{ ObjectDesc, ObjectId, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupQuorumCertificateObject, HotstuffTimeout, +}; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ @@ -20,7 +23,7 @@ use super::{ StorageEngine, }; -const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; +const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() as u64; pub enum BlockLinkState { Expired, @@ -96,16 +99,32 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver.get_group(group_id, None, None).await?; + let group = non_driver + .get_group(group_id, None, None) + .await + .map_err(|err| { + log::warn!("get group {} from noc failed {:?}", group_id, err); + err + })?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) - .await? + .await + .map_err(|err| { + log::warn!("load root state for group {} failed {:?}", group_id, err); + err + })? .expect("create group state failed."); - let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state + .get_dec_root_manager(dec_id, true) + .await + .map_err(|err| { + log::warn!("get root state manager for dec {} failed {:?}", dec_id, err); + err + })?; let state_path = GroupStatePath::new(rpath.to_string()); let cache = @@ -120,7 +139,7 @@ impl GroupStorage { group_chunk_id: group_chunk_id.object_id(), storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, - cache: cache, + cache, }) } @@ -286,24 +305,33 @@ impl GroupStorage { writer.remove_prepares(remove_prepares.as_slice()).await?; - let finish_proposals: Vec = new_header - .proposals() - .iter() - .map(|p| p.proposal.clone()) - .collect(); - - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { - writer - .push_proposals( - finish_proposals.as_slice(), - Some((timestamp, self.cache.finish_proposals.flip_timestamp)), - ) - .await?; - } else { - writer - .push_proposals(finish_proposals.as_slice(), None) - .await?; + if new_header.proposals().len() > 0 { + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + + let timestamp = new_header.named_object().desc().create_time(); + // log::debug!( + // "push proposals storage flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + writer + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), + ) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } } @@ -340,19 +368,28 @@ impl GroupStorage { self.cache.first_block = Some(new_header.clone()); } - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp - > PROPOSAL_MAX_TIMEOUT_AS_MS - { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); - self.cache.finish_proposals.flip_timestamp = timestamp; - } + if new_header.proposals().len() > 0 { + let timestamp = new_header.named_object().desc().create_time(); + + // log::debug!( + // "push proposals flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; + } - for proposal in new_header.proposals() { - let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); - assert!(is_new); + for proposal in new_header.proposals() { + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } } self.cache.header_block = Some(new_header); @@ -405,6 +442,33 @@ impl GroupStorage { Ok(()) } + pub fn last_qc(&self) -> &Option { + &self.cache.last_qc + } + + pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { + let quorum_round = qc.quorum_round(); + if quorum_round < self.cache.last_vote_round + || quorum_round + <= self + .cache + .last_qc + .as_ref() + .map_or(0, |qc| qc.quorum_round()) + { + return Ok(()); + } + + self.non_driver.put_qc(&qc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_qc(&qc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_qc = Some(qc); + Ok(()) + } + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { log::debug!( "[group storage] {} block_linked {} step1", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9414cda7c..fcb0dd6da 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, @@ -55,6 +55,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { } async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let access = AccessString::full(); + log::debug!("put object {} with access {}", obj.object_id, access); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { @@ -76,7 +78,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { flags: 0, }, object: obj, - access: None, // TODO access + access: Some(AccessString::full()), // TODO access }) .await .map(|_| ()) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d69fcae2d..b5b6f4ce4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,7 +1,8 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ - AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; @@ -23,8 +24,8 @@ mod Common { AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, - TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, - SIGNATURE_SOURCE_REFINDEX_SELF, + TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -210,13 +211,12 @@ mod Common { save_path: &str, name_prefix: &str, count: usize, + min_port: u16, ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { fs::create_dir_all(save_path) .await .expect(format!("create dir {} failed", save_path).as_str()); - let min_port = 30217_u16; - let mut members = vec![]; for i in 0..count { @@ -296,11 +296,13 @@ mod Common { } pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/admins", "admin", 4).await + let min_port = 30217_u16; + init_member_from_dir("./test-group/admins", "admin", 4, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/members", "member", 9).await + let min_port = 31217_u16; + init_member_from_dir("./test-group/members", "member", 9, min_port).await } pub async fn init_group( @@ -369,7 +371,7 @@ mod Common { }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { - bdt_listeners: vec![], + bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], tcp_listeners: vec![], ws_listener: None, }, @@ -868,7 +870,7 @@ async fn main_run() { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: Some(AccessString::full().value()), }; noc.put_object(&req).await; proposals.push(proposal); @@ -878,8 +880,8 @@ async fn main_run() { log::info!("proposals prepared."); - for i in 0..(PROPOSAL_COUNT - 1) { - let proposal = proposals.get(i).unwrap().clone(); + for i in 1..PROPOSAL_COUNT { + let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let control = stack From f4104dab79c5b80e7fa9ac442b02007f5577f64a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 16:04:16 +0800 Subject: [PATCH 080/553] fix: first block with tc --- .../src/consensus/hotstuff/hotstuff.rs | 75 ++++++++++--------- .../src/statepath/group_statepath.rs | 12 +++ .../src/storage/engine/storage_engine.rs | 9 ++- .../engine/storage_engine_group_state.rs | 35 ++++++++- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 41 +++++++--- src/tests/group-example/src/main.rs | 2 + 7 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7868a7f90..a2a5e8f70 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -239,36 +239,30 @@ impl HotstuffRunner { ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); - let (tc, qc) = last_qc - .as_ref() - .map_or((None, None), |qc| { - match qc.desc().content() { - cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), - cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), - } - }); + let last_tc = store.last_tc(); let last_vote_round = store .last_vote_round(); - let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); - let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); + let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); + let quorum_round = block_quorum_round.max(timeout_quorum_round); + let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" - , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" + , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); - let max_round_qc_round = max_round_block - .as_ref() - .map_or(0, |block| - block.qc().as_ref().map_or(0, |qc| qc.round) - ); - let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); - let high_qc = if max_round_qc_round >= last_qc_round { + let high_qc = if max_round_qc_round >= block_quorum_round { max_round_block.map_or(None, |b| b.qc().clone()) } else { - qc + last_qc.clone() }; + let tc = last_tc.clone(); + let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; @@ -954,18 +948,22 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && qc_round - >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; if !is_valid_round { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {:?}", self, block.block_id(), block.round(), qc_round, - block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + block.tc().as_ref().map_or((0, 0), |tc| { + let qc_round = tc.votes.iter().map(|v| v.high_qc_round).max().unwrap(); + (tc.round, qc_round) + })); return None; } @@ -1109,7 +1107,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); - self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.store.save_qc(&qc).await?; self.process_qc(&Some(qc)).await; @@ -1125,7 +1123,7 @@ impl HotstuffRunner { })?; if self.local_device_id == new_leader { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } Ok(()) } @@ -1251,12 +1249,12 @@ impl HotstuffRunner { max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( @@ -1367,9 +1365,9 @@ impl HotstuffRunner { err })?; - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1535,7 +1533,7 @@ impl HotstuffRunner { self.remove_pending_proposals(remove_proposals).await; if self - .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .try_wait_proposals(executed_proposals.len(), &prev_block) .await { log::debug!( @@ -1739,12 +1737,12 @@ impl HotstuffRunner { async fn try_wait_proposals( &mut self, - executed_proposals: &[(GroupProposal, ExecuteResult)], + proposal_count: usize, pre_block: &Option, ) -> bool { // empty block, qc only, it's unuseful when no block to qc let mut will_wait_proposals = false; - if executed_proposals.len() == 0 { + if proposal_count == 0 { match pre_block.as_ref() { None => { log::warn!( @@ -1814,14 +1812,17 @@ impl HotstuffRunner { assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); - let tc = self.tc.as_ref().map_or(None, |tc| { + self.generate_block(self.with_tc()).await + } + + fn with_tc(&self) -> Option { + self.tc.as_ref().map_or(None, |tc| { if tc.round + 1 == self.round { Some(tc.clone()) } else { None } - }); - self.generate_block(tc).await + }) } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { @@ -1876,7 +1877,7 @@ impl HotstuffRunner { ); } _ => { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } } } diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0e6a887b0..72f48e601 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -6,6 +6,7 @@ pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; +pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -30,6 +31,7 @@ pub struct GroupStatePath { group_blob: String, last_vote_round: String, last_qc: String, + last_tc: String, range: String, prepares: String, pre_commits: String, @@ -63,6 +65,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_QC, ]), + last_tc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_TC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -140,6 +148,10 @@ impl GroupStatePath { self.last_qc.as_str() } + pub fn last_tc(&self) -> &str { + self.last_tc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index aebf6fb96..c4803d6ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,7 +12,8 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 - pub last_qc: Option, + pub last_qc: Option, + pub last_tc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -25,6 +26,8 @@ impl StorageCacheInfo { Self { dec_state_id: init_state_id, last_vote_round: 0, + last_qc: None, + last_tc: None, header_block: None, first_block: None, prepares: HashMap::new(), @@ -34,7 +37,6 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, - last_qc: None, } } } @@ -61,6 +63,7 @@ pub trait StorageWriter: Send + Sync { async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 2b61dbc47..b3a01fd60 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -38,10 +39,26 @@ impl StorageEngineGroupState { let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; let last_vote_round = map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; let last_qc = map_not_found_option_to_option(last_qc)?; let last_qc = match last_qc.as_ref() { - Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + Some(qc_id) => non_driver + .get_qc(qc_id, None) + .await? + .try_into() + .map_or(None, |qc| Some(qc)), + None => None, + }; + + let last_tc = op_env.get_by_path(state_path.last_tc()).await; + let last_tc = map_not_found_option_to_option(last_tc)?; + let last_tc = match last_tc.as_ref() { + Some(tc_id) => non_driver + .get_qc(tc_id, None) + .await? + .try_into() + .map_or(None, |tc| Some(tc)), None => None, }; @@ -118,6 +135,7 @@ impl StorageEngineGroupState { let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); cache.last_qc = last_qc; + cache.last_tc = last_tc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -440,6 +458,13 @@ impl StorageEngineGroupStateWriter { .await .map(|_| ()) } + + async fn save_last_tc_inner(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_tc(), tc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -509,6 +534,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_tc_inner(tc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 79491b186..ebeedd7ca 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -196,6 +196,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3f9fc9910..ee2618cde 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -10,7 +10,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffTimeout, + GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; @@ -442,30 +442,49 @@ impl GroupStorage { Ok(()) } - pub fn last_qc(&self) -> &Option { + pub fn last_qc(&self) -> &Option { &self.cache.last_qc } - pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { - let quorum_round = qc.quorum_round(); + pub async fn save_qc(&mut self, qc: &HotstuffBlockQC) -> BuckyResult<()> { + let quorum_round = qc.round; if quorum_round < self.cache.last_vote_round - || quorum_round - <= self - .cache - .last_qc - .as_ref() - .map_or(0, |qc| qc.quorum_round()) + || quorum_round <= self.cache.last_qc.as_ref().map_or(0, |qc| qc.round) { return Ok(()); } + let qc = GroupQuorumCertificate::from(qc.clone()); self.non_driver.put_qc(&qc).await?; let mut writer = self.storage_engine.create_writer().await?; writer.save_last_qc(&qc.desc().object_id()).await?; writer.commit().await?; - self.cache.last_qc = Some(qc); + self.cache.last_qc = Some(qc.try_into().unwrap()); + Ok(()) + } + + pub fn last_tc(&self) -> &Option { + &self.cache.last_tc + } + + pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + let quorum_round = tc.round; + if quorum_round < self.cache.last_vote_round + || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) + { + return Ok(()); + } + + let tc = GroupQuorumCertificate::from(tc.clone()); + self.non_driver.put_qc(&tc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_tc(&tc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_tc = Some(tc.try_into().unwrap()); Ok(()) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b5b6f4ce4..2ba99716e 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -798,6 +798,8 @@ async fn main_run() { admin_stacks.push(cyfs_stack); } + async_std::task::sleep(Duration::from_millis(10000)).await; + for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); From 66a13aef6fe1b9dfccf6bd66b0046a1358cb79de Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:23:03 +0800 Subject: [PATCH 081/553] prepare for verify --- .../cyfs-core/protos/core_objects.proto | 14 -- src/component/cyfs-core/src/coreobj.rs | 1 - .../src/group/group_consensus_block.rs | 23 +++ .../cyfs-core/src/group/group_rpath_status.rs | 17 --- src/component/cyfs-core/src/group/mod.rs | 2 - .../protos/group_bft_protocol.proto | 6 + src/component/cyfs-group/src/crypto/crypto.rs | 14 -- src/component/cyfs-group/src/crypto/mod.rs | 3 - .../cyfs-group/src/dec/group_manager.rs | 35 +++-- .../src/dec_state/dec_state_requestor.rs | 32 ++-- src/component/cyfs-group/src/helper/verify.rs | 6 +- src/component/cyfs-group/src/lib.rs | 2 - .../src/objects/group_rpath_status.rs | 89 +++++++++++ src/component/cyfs-group/src/objects/mod.rs | 2 + .../cyfs-group/src/objects/protocol.rs | 140 +++++++++++++----- .../cyfs-group/src/storage/dec_storage.rs | 6 +- 16 files changed, 259 insertions(+), 133 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs delete mode 100644 src/component/cyfs-group/src/crypto/crypto.rs delete mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/objects/group_rpath_status.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 164c6bcd6..487ece4bd 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -431,20 +431,6 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } -message GroupRPathSubStatus { - string sub_path = 1; - repeated bytes state_id = 2; // for set -} - -message GroupRPathStatusDescContent { - bytes block_id = 1; - optional bytes sub_status_hash = 2; -} - -message GroupRPathStatusBodyContent { - repeated GroupRPathSubStatus sub_status = 1; -} - message GroupActionDescContent { // target GroupRPath r_path = 1; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 30bf0e013..3d53a082f 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -64,7 +64,6 @@ pub enum CoreObjectType { GroupProposal = 700, GroupUpdateGroup = 701, GroupConsensusBlock = 702, - GroupRPathStatus = 703, GroupAction = 704, GroupQuorumCertificate = 705, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 5d6d114c0..35c418552 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -38,6 +38,28 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } +impl GroupConsensusBlockDescContent { + pub fn rpath(&self) -> &GroupRPath { + &self.r_path + } + + pub fn result_state_id(&self) -> &Option { + &self.result_state_id + } + + pub fn height(&self) -> u64 { + self.height + } + + pub fn round(&self) -> u64 { + self.round + } + + pub fn group_chunk_id(&self) -> &ObjectId { + &self.group_chunk_id + } +} + #[derive(Clone, ProtobufTransformType)] #[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] pub struct HotstuffBlockQCSign { @@ -175,6 +197,7 @@ impl BodyContent for GroupConsensusBlockBodyContent { } } +pub type GroupConsensusBlockDesc = NamedObjectDesc; type GroupConsensusBlockType = NamedObjType; type GroupConsensusBlockBuilder = diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs deleted file mode 100644 index c55c41243..000000000 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::atomic::{AtomicU8, Ordering}; - -use crate::CoreObjectType; -use cyfs_base::*; -use serde::Serialize; -use sha2::Digest; - -// TODO: 后面再封装这个对象 -#[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus { - pub value_object_id: ObjectId, - pub block_id: ObjectId, - pub qc_block_id: ObjectId, -} - -#[cfg(test)] -mod test {} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index c153ab1ba..b2885d637 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -3,7 +3,6 @@ mod group_proposal; mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_rpath_status; mod group_update_group_proposal_param; pub use group_consensus_block::*; @@ -11,5 +10,4 @@ pub use group_proposal::*; pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 6ed8c3afe..621186522 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -15,3 +15,9 @@ message HotstuffTimeoutVote { bytes voter = 3; bytes signature = 4; } + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs deleted file mode 100644 index 9949f7a67..000000000 --- a/src/component/cyfs-group/src/crypto/crypto.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cyfs_base::{HashValue, ObjectId, Signature}; - -#[derive(Clone)] -pub struct Crypto {} - -impl Crypto { - pub fn sign(&self, hash: &HashValue) -> Signature { - unimplemented!() - } - - pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs deleted file mode 100644 index 066e79b6b..000000000 --- a/src/component/cyfs-group/src/crypto/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod crypto; - -pub use crypto::*; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 70fb10ba6..2f2229890 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,7 +289,7 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - // TODO: 暂时不实现 + // TODO: unimplemented // let rpath = header_block.r_path(); // let client = self // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) @@ -302,23 +302,22 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - // TODO: 暂时不实现 - // let rpath = result.as_ref().map_or_else( - // |(_, target)| target.check_rpath(), - // |(_, block, _)| block.r_path(), - // ); - // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - // .await?; - // client - // .on_message( - // HotstuffMessage::ProposalResult( - // proposal_id, - // result.map_err(|(err, _)| err), - // ), - // remote, - // ) - // .await; + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) + .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e30c0a5a7..369b3db6e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,10 +3,13 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; -use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; +use crate::{ + helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + CHANNEL_CAPACITY, +}; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -143,7 +146,7 @@ impl DecStateRequestorRunner { let result = self .verify_verifiable_state(sub_path.as_str(), &result, &remote) .await - .map(|_| result.value_object_id); + .map(|_| unimplemented!()); // TODO: 搜索目标值 self.query_state_notifier.reply(&sub_path, result).await } @@ -157,25 +160,22 @@ impl DecStateRequestorRunner { result: &GroupRPathStatus, remote: &ObjectId, ) -> BuckyResult<()> { - let header_block = self - .non_driver - .get_block(&result.block_id, Some(remote)) - .await?; - let qc_block = self - .non_driver - .get_block(&result.qc_block_id, Some(remote)) - .await?; + // let header_block = self + // .non_driver + // .get_block(&result.block_id, Some(remote)) + // .await?; + // let qc_block = self + // .non_driver + // .get_block(&result.qc_block_id, Some(remote)) + // .await?; - let qc = match qc_block.qc() { - Some(qc) => qc, - None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), - }; + let qc = &result.certificate; let group = self .non_driver .get_group( self.rpath.group_id(), - Some(header_block.group_chunk_id()), + Some(result.block_desc.content().group_chunk_id()), Some(&remote), ) .await?; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 2a384d1cf..b8ab12b69 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; + +use crate::GroupRPathStatus; pub async fn verify_block( block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index fefe3f808..ba8e83569 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -1,6 +1,5 @@ mod consensus; mod constant; -mod crypto; mod dec; mod dec_state; mod helper; @@ -12,7 +11,6 @@ mod utils; pub use consensus::*; pub use constant::*; -pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs new file mode 100644 index 000000000..f266d3dbd --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use cyfs_base::*; +use cyfs_core::{GroupConsensusBlockDesc, HotstuffBlockQC}; +use cyfs_lib::NONObjectInfo; +use prost::Message; + +#[derive(Clone)] +pub struct GroupRPathStatus { + pub block_desc: GroupConsensusBlockDesc, + pub certificate: HotstuffBlockQC, + pub status_map: HashMap, +} + +impl RawEncode for GroupRPathStatus { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + Ok(proto.encoded_len()) + } + + fn raw_encode<'a>( + &self, + mut buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + proto.encode_raw(&mut buf); + + Ok(buf) + } +} + +impl<'de> RawDecode<'de> for GroupRPathStatus { + fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + let (block_desc, remain) = + GroupConsensusBlockDesc::raw_decode(proto.block_desc.as_slice())?; + assert_eq!(remain.len(), 0); + let (certificate, remain) = HotstuffBlockQC::raw_decode(proto.certificate.as_slice())?; + assert_eq!(remain.len(), 0); + let mut status_map = HashMap::new(); + for obj_buf in proto.status_list.iter() { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status_map.insert(status.object_id, status); + } + + Ok(( + Self { + block_desc, + certificate, + status_map, + }, + buf, + )) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs index d6de55d79..5d1a8b13f 100644 --- a/src/component/cyfs-group/src/objects/mod.rs +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -1,7 +1,9 @@ mod group_decide_proposal; +mod group_rpath_status; mod group_update_proposal; mod protocol; pub use group_decide_proposal::*; +pub use group_rpath_status::*; pub use group_update_proposal::*; pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 3e5f513df..6c9f89e96 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,16 +2,15 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } -use std::result; - use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; +use crate::GroupRPathStatus; + #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), @@ -163,20 +162,16 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::ProposalResult({}, {:?})", proposal_id, - result.as_ref().map_or_else( - |err| { Err(err) }, - |(obj, block, qc)| { - let ok = format!( - "({:?}, {}/{}, {}/{})", - obj.as_ref().map(|o| o.object_id), - block.block_id(), - block.round(), - qc.block_id(), - qc.round() - ); - Ok(ok) - } - ) + result.as_ref().map(|(obj, block, qc)| { + format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + }) ) } Self::QueryState(sub_path) => { @@ -187,7 +182,17 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map(|status| { + let desc = status.block_desc.content(); + format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ) + }) ) } } @@ -196,6 +201,7 @@ impl std::fmt::Debug for HotstuffMessage { const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; +const PACKAGE_FLAG_QUERY_STATE_RESULT_OK: u8 = 0x80u8; #[derive(Clone)] pub(crate) enum HotstuffPackage { @@ -220,7 +226,10 @@ pub(crate) enum HotstuffPackage { >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, String, BuckyResult), + VerifiableState( + String, + Result, + ), } impl std::fmt::Debug for HotstuffPackage { @@ -296,12 +305,26 @@ impl std::fmt::Debug for HotstuffPackage { Self::QueryState(_, sub_path) => { write!(f, "HotstuffPackage::QueryState({})", sub_path) } - Self::VerifiableState(_, sub_path, result) => { + Self::VerifiableState(sub_path, result) => { write!( f, "HotstuffPackage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |status| { + let desc = status.block_desc.content(); + let ok = format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ); + Ok(ok) + } + ) ) } } @@ -323,7 +346,10 @@ impl HotstuffPackage { |(_, block, _)| block.r_path(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), - HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |status| status.block_desc.content().rpath(), + ), } } } @@ -399,10 +425,14 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::QueryState(addr, sub_path) => { addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { - 2 + addr.raw_measure(purpose)? - + sub_path.raw_measure(purpose)? - + result.raw_measure(purpose)? + HotstuffPackage::VerifiableState(sub_path, result) => { + sub_path.raw_measure(purpose)? + + match result { + Ok(status) => status.raw_measure(purpose)?, + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } } }; @@ -459,7 +489,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; if result.is_ok() { - buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + buf[0] |= PACKAGE_FLAG_PROPOSAL_RESULT_OK; } let buf = &mut buf[1..]; @@ -482,12 +512,20 @@ impl RawEncode for HotstuffPackage { let buf = sub_path.raw_encode(buf, purpose)?; addr.raw_encode(buf, purpose) } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { + HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; + if result.is_ok() { + buf[0] |= PACKAGE_FLAG_QUERY_STATE_RESULT_OK; + } let buf = &mut buf[1..]; - let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = sub_path.raw_encode(buf, purpose)?; - result.raw_encode(buf, purpose) + match result { + Ok(status) => status.raw_encode(buf, purpose), + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } } } } @@ -502,24 +540,28 @@ impl<'de> RawDecode<'de> for HotstuffPackage { 0 => { let buf = &buf[1..]; let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { @@ -527,17 +569,20 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } 7 => { @@ -549,6 +594,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), buf, @@ -557,6 +603,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { false => { let (err, buf) = BuckyError::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } } @@ -565,17 +612,29 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let buf = &buf[1..]; let (sub_path, buf) = String::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } 9 => { + let is_ok = (buf[0] & PACKAGE_FLAG_QUERY_STATE_RESULT_OK) != 0; let buf = &buf[1..]; - let (addr, buf) = decode_with_length(buf, 3)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (result, buf) = BuckyResult::::raw_decode(buf)?; - Ok(( - HotstuffPackage::VerifiableState(addr, sub_path, result), - buf, - )) + match is_ok { + true => { + let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok(( + HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), + buf, + )) + } + } } _ => unreachable!("unknown protocol"), } @@ -613,9 +672,10 @@ impl HotstuffPackage { HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) } - HotstuffMessage::VerifiableState(sub_path, result) => { - HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) - } + HotstuffMessage::VerifiableState(sub_path, result) => HotstuffPackage::VerifiableState( + sub_path, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ), } } } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 12e3629d8..cce00e736 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use async_std::sync::RwLock; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; +use cyfs_core::GroupConsensusBlock; + +use crate::GroupRPathStatus; #[derive(Clone)] pub struct DecStorageCache { @@ -11,8 +13,6 @@ pub struct DecStorageCache { pub qc_block: GroupConsensusBlock, } -// TODO: storage - #[derive(Clone)] pub struct DecStorage { cache: Arc>>, From f8c0fee789d4713f6c1c9a4143a6643a10a2c954 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:28:28 +0800 Subject: [PATCH 082/553] compile --- .../cyfs-group/src/dec/group_manager.rs | 12 +++++++++--- .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 14 +++++++++----- src/component/cyfs-group/src/helper/verify.rs | 16 +++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 2f2229890..0d863e17b 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -328,13 +328,19 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - HotstuffPackage::VerifiableState(target, sub_path, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::VerifiableState(sub_path, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |status| status.block_desc.content().rpath(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .on_message( + HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), + remote, + ) .await; } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 369b3db6e..b5c3b107e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -180,7 +180,7 @@ impl DecStateRequestorRunner { ) .await?; - if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { Err(BuckyError::new( BuckyErrorCode::InvalidSignature, "verify failed", diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f33ec5fa..73afb0ad0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -315,10 +315,7 @@ impl DecStateSynchronizerRunner { remote: ObjectId, ) -> BuckyResult<()> { if qc_block.qc().is_none() { - log::warn!( - "the qc is none for qc-block({})", - qc_block.block_id() - ); + log::warn!("the qc is none for qc-block({})", qc_block.block_id()); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } @@ -365,7 +362,14 @@ impl DecStateSynchronizerRunner { } }; - if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + if header_block.check() + && verify_block( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + &group.1, + ) + .await? + { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index b8ab12b69..759bf2c4a 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,15 +1,17 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, +}; use crate::GroupRPathStatus; pub async fn verify_block( - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.block_id().object_id(); - if qc.round != block.round() || &qc.block_id != block_id { + let block_id = block_desc.object_id(); + if qc.round != block_desc.content().round() || qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, @@ -18,17 +20,13 @@ pub async fn verify_block( return Ok(false); } - if !block.check() { - return Ok(false); - } - unimplemented!() } pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { From ddd6c5da9858552622c062949f7bd641753f302b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 23 Feb 2023 21:02:07 +0800 Subject: [PATCH 083/553] Verify the value on sub-path from anyone OOD in group --- .../src/consensus/hotstuff/hotstuff.rs | 28 ++++- .../src/consensus/vote/committee.rs | 66 ++++++++++- .../cyfs-group/src/dec/group_manager.rs | 54 ++++++--- .../cyfs-group/src/dec/rpath_client.rs | 34 ++++-- .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../src/dec_state/dec_state_requestor.rs | 73 ++++++------ .../src/dec_state/dec_state_synchronizer.rs | 80 ++++++-------- src/component/cyfs-group/src/helper/verify.rs | 18 --- .../src/objects/group_rpath_status.rs | 4 +- .../cyfs-group/src/storage/dec_storage.rs | 76 ++++++++++++- .../src/storage/engine/storage_engine.rs | 4 +- .../engine/storage_engine_group_state.rs | 23 +++- .../cyfs-group/src/storage/group_storage.rs | 104 +++++++++++++++++- src/component/cyfs-group/src/utils.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 15 files changed, 410 insertions(+), 166 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index a2a5e8f70..667966a6c 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -187,6 +187,19 @@ impl Hotstuff { self.state_pusher.request_last_state(remote).await; } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_query_state: sub_path: {}, remote: {:?},", + self, + sub_path, + remote + ); + + self.tx_message + .send((HotstuffMessage::QueryState(sub_path), remote)) + .await; + } } struct HotstuffRunner { @@ -1834,6 +1847,19 @@ impl HotstuffRunner { Ok(()) } + async fn handle_query_state(&self, sub_path: String, remote: ObjectId) -> BuckyResult<()> { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + + Ok(()) + } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; @@ -1918,7 +1944,7 @@ impl HotstuffRunner { Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), - Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d3fbd489c..ad3a21e35 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,9 +10,13 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { @@ -136,6 +140,47 @@ impl Committee { Ok(()) } + pub async fn verify_block_desc_with_qc( + &self, + block_desc: &GroupConsensusBlockDesc, + qc: &HotstuffBlockQC, + from: ObjectId, + ) -> BuckyResult<()> { + let block_id = block_desc.object_id(); + + log::debug!( + "[group committee] {} verify block desc {} step1", + self.local_device_id, + block_id + ); + + if block_id != qc.block_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the block id is unmatch with the qc", + )); + } + + self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + .await?; + + log::debug!( + "[group committee] {} verify block desc {} step2", + self.local_device_id, + block_id + ); + + self.verify_qc_with_desc(qc, block_desc.content()).await?; + + log::debug!( + "[group committee] {} verify block desc {} step3", + self.local_device_id, + block_id + ); + + Ok(()) + } + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { let hash = vote.hash(); let device = self.non_driver.get_device(&vote.voter).await?; @@ -250,8 +295,17 @@ impl Committee { qc: &HotstuffBlockQC, prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { - if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); + self.verify_qc_with_desc(qc, prev_block.named_object().desc().content()) + .await + } + + pub async fn verify_qc_with_desc( + &self, + qc: &HotstuffBlockQC, + prev_block_desc: &GroupConsensusBlockDescContent, + ) -> BuckyResult<()> { + if qc.round != prev_block_desc.round() { + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block_desc.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, "round not match in qc", @@ -261,7 +315,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block.group_chunk_id()), + Some(prev_block_desc.group_chunk_id()), ) .await?; @@ -291,7 +345,7 @@ impl Committee { .map_or(Ok(()), |e| e) } - async fn check_group( + pub async fn check_group( &self, chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 0d863e17b..f7b7fbbbe 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -123,6 +123,7 @@ impl GroupManager { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); + let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), @@ -143,9 +144,13 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let state_proccessor = state_mgr + .load_root_state(local_device_id.object_id(), Some(local_id), true) + .await?; let client = RPathClient::load( - local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + state_proccessor.unwrap(), non_driver, network_sender, ) @@ -199,7 +204,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, Some(&block), Some(&remote), ) @@ -215,7 +220,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -231,7 +236,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -247,7 +252,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -263,7 +268,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -279,7 +284,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -321,12 +326,32 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message(HotstuffMessage::QueryState(sub_path), remote) + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + IsCreateRPath::No, + None, + Some(&remote), + ) .await; + + match control { + Ok(control) => { + control + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + _ => { + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + } } HotstuffPackage::VerifiableState(sub_path, result) => { let rpath = result.as_ref().map_or_else( @@ -436,15 +461,10 @@ impl GroupManager { let store = match store { Some(store) => store, None => { - let init_state = match is_auto_create { - IsCreateRPath::Yes(init_state) => init_state, - _ => unreachable!(), - }; GroupStorage::create( group_id, dec_id, rpath, - init_state, non_driver.clone(), local_device_id.object_id().clone(), &root_state_mgr, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 9f1d08579..8a1dd34a7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -5,18 +5,18 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, storage::DecStorage, - HotstuffMessage, CLIENT_POLL_TIMEOUT, + Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; struct RPathClientRaw { rpath: GroupRPath, - local_id: ObjectId, + local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, @@ -28,22 +28,31 @@ pub struct RPathClient(Arc); impl RPathClient { pub(crate) async fn load( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { - let dec_store = DecStorage::load().await?; + let dec_store = DecStorage::load(state_processor).await?; + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); + let state_sync = DecStateSynchronizer::new( - local_id, + local_device_id, rpath.clone(), + committee.clone(), non_driver.clone(), dec_store.clone(), ); let state_requestor = DecStateRequestor::new( - local_id, + local_device_id, rpath.clone(), + committee, network_sender.clone(), non_driver.clone(), dec_store.clone(), @@ -53,7 +62,7 @@ impl RPathClient { rpath, non_driver, network_sender, - local_id, + local_device_id, state_sync, state_requestor, }; @@ -77,7 +86,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -143,7 +152,7 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let random = rand::thread_rng().gen_range(0..oods.len()); let ood = oods.get(random).unwrap().clone(); @@ -154,14 +163,15 @@ impl RPathClient { Ok(()) } - pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 .non_driver .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); + let members = + group.select_members_with_distance(&self.0.local_device_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 101b34075..7abff1ec1 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -89,7 +89,9 @@ impl RPathControl { HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), HotstuffMessage::ProposalResult(_, _) => unreachable!(), - HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::QueryState(sub_path) => { + self.0.hotstuff.on_query_state(sub_path, remote).await + } HotstuffMessage::VerifiableState(_, _) => unreachable!(), } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index b5c3b107e..0a3544c09 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,10 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, CHANNEL_CAPACITY, }; @@ -19,9 +20,9 @@ enum DecStateRequestorMessage { } struct DecStateRequestorRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } #[derive(Clone)] @@ -29,8 +30,9 @@ pub struct DecStateRequestor(Arc); impl DecStateRequestor { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, store: DecStorage, @@ -39,8 +41,9 @@ impl DecStateRequestor { let notifier = CallReplyNotifier::new(); let mut runner = DecStateRequestorRunner::new( - local_id, + local_device_id, rpath, + committee, rx, store, network_sender, @@ -51,7 +54,7 @@ impl DecStateRequestor { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateRequestorRaw { - local_id, + local_device_id, tx_dec_state_req_message: tx, query_state_notifier: notifier, })) @@ -60,7 +63,7 @@ impl DecStateRequestor { pub async fn wait_query_state( &self, sub_path: String, - ) -> CallReplyWaiter> { + ) -> CallReplyWaiter>> { self.0.query_state_notifier.prepare(sub_path).await } @@ -88,21 +91,23 @@ impl DecStateRequestor { } struct DecStateRequestorRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, // timer: Timer, store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } impl DecStateRequestorRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<( DecStateRequestorMessage, ObjectId, @@ -110,10 +115,10 @@ impl DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, rx_dec_state_req_message, // timer: Timer::new(SYNCHRONIZER_TIMEOUT), @@ -121,6 +126,7 @@ impl DecStateRequestorRunner { query_state_notifier, network_sender, non_driver, + committee, } } @@ -144,9 +150,9 @@ impl DecStateRequestorRunner { match result { Ok(result) => { let result = self - .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .check_sub_path_value(sub_path.as_str(), &result, &remote) .await - .map(|_| unimplemented!()); // TODO: 搜索目标值 + .map(|r| r.cloned()); self.query_state_notifier.reply(&sub_path, result).await } @@ -154,40 +160,23 @@ impl DecStateRequestorRunner { } } - async fn verify_verifiable_state( + async fn check_sub_path_value<'a>( &self, sub_path: &str, - result: &GroupRPathStatus, + verifiable_status: &'a GroupRPathStatus, remote: &ObjectId, - ) -> BuckyResult<()> { - // let header_block = self - // .non_driver - // .get_block(&result.block_id, Some(remote)) - // .await?; - // let qc_block = self - // .non_driver - // .get_block(&result.qc_block_id, Some(remote)) - // .await?; - - let qc = &result.certificate; - - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(result.block_desc.content().group_chunk_id()), - Some(&remote), + ) -> BuckyResult> { + self.committee + .verify_block_desc_with_qc( + &verifiable_status.block_desc, + &verifiable_status.certificate, + remote.clone(), ) .await?; - if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "verify failed", - )) - } else { - Ok(()) - } + self.store + .check_sub_path_value(sub_path, verifiable_status) + .await } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 73afb0ad0..7272b3882 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -10,10 +10,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::{verify_block, Timer}, + helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, + Committee, CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -32,7 +32,7 @@ enum DecStateSynchronizerMessage { } struct DecStateSynchronizerRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, proposal_result_notifier: CallReplyNotifier>>, } @@ -42,8 +42,9 @@ pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { @@ -51,8 +52,9 @@ impl DecStateSynchronizer { let notifier = CallReplyNotifier::new(); let mut runner = DecStateSynchronizerRunner::new( - local_id, + local_device_id, rpath, + committee, tx.clone(), rx, store, @@ -63,7 +65,7 @@ impl DecStateSynchronizer { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateSynchronizerRaw { - local_id, + local_device_id, tx_dec_state_sync_message: tx, proposal_result_notifier: notifier, })) @@ -126,8 +128,9 @@ struct UpdateNotifyInfo { } struct DecStateSynchronizerRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, @@ -142,8 +145,9 @@ struct DecStateSynchronizerRunner { impl DecStateSynchronizerRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<( DecStateSynchronizerMessage, ObjectId, @@ -157,7 +161,7 @@ impl DecStateSynchronizerRunner { proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, tx_dec_state_sync_message, rx_dec_state_sync_message, @@ -167,6 +171,7 @@ impl DecStateSynchronizerRunner { update_notifies: None, non_driver, proposal_result_notifier, + committee, } } @@ -330,52 +335,29 @@ impl DecStateSynchronizerRunner { } } - let group = match self.update_notifies.as_ref() { - Some(n) => Some((n.group_chunk_id, n.group.clone())), - None => self - .check_cache() - .await - .as_ref() - .map(|c| (c.group_chunk_id, c.group.clone())), - } - .map_or(None, |(chunk_id, group)| { - if &chunk_id == header_block.group_chunk_id() { - Some((chunk_id, group)) - } else { - None - } - }); - - // group changed - let group = match group { - Some(group) => group, - None => { - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(header_block.group_chunk_id()), - Some(&remote), - ) - .await?; - (header_block.group_chunk_id().clone(), group) - } - }; - if header_block.check() - && verify_block( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - &group.1, - ) - .await? + && self + .committee + .verify_block_desc_with_qc( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + remote, + ) + .await + .is_ok() { + let group = self + .committee + .check_group(Some(header_block.group_chunk_id()), None) + .await?; + let group_chunk_id = header_block.group_chunk_id().clone(); + self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, remotes: HashSet::from([remote]), - group_chunk_id: group.0, - group: group.1, + group_chunk_id, + group, }); }; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 759bf2c4a..ef3e34495 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -5,24 +5,6 @@ use cyfs_core::{ use crate::GroupRPathStatus; -pub async fn verify_block( - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - let block_id = block_desc.object_id(); - if qc.round != block_desc.content().round() || qc.block_id != block_id { - log::error!( - "the qc-block({}) should be next block({})", - qc.round, - block_id - ); - return Ok(false); - } - - unimplemented!() -} - pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index f266d3dbd..858c37fff 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -13,7 +13,7 @@ pub struct GroupRPathStatus { } impl RawEncode for GroupRPathStatus { - fn raw_measure(&self, purpose: &Option) -> BuckyResult { + fn raw_measure(&self, _purpose: &Option) -> BuckyResult { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; let mut status_list = vec![]; @@ -33,7 +33,7 @@ impl RawEncode for GroupRPathStatus { fn raw_encode<'a>( &self, mut buf: &'a mut [u8], - purpose: &Option, + _purpose: &Option, ) -> BuckyResult<&'a mut [u8]> { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index cce00e736..de5a0fd4a 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -1,10 +1,14 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, + ObjectTypeCode, RawDecode, +}; use cyfs_core::GroupConsensusBlock; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::GroupRPathStatus; +use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; #[derive(Clone)] pub struct DecStorageCache { @@ -16,13 +20,15 @@ pub struct DecStorageCache { #[derive(Clone)] pub struct DecStorage { cache: Arc>>, + pub state_processor: GlobalStateRawProcessorRef, } impl DecStorage { - pub async fn load() -> BuckyResult { - unimplemented!(); + pub async fn load(state_processor: GlobalStateRawProcessorRef) -> BuckyResult { + // unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), + state_processor, }; Ok(obj) @@ -45,4 +51,64 @@ impl DecStorage { pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } + + pub async fn check_sub_path_value<'a>( + &self, + sub_path: &str, + verifiable_status: &'a GroupRPathStatus, + ) -> BuckyResult> { + let block_desc = &verifiable_status.block_desc; + let qc = &verifiable_status.certificate; + + let mut parent_state_id = match block_desc.content().result_state_id() { + Some(state_id) => state_id.clone(), + None => return Ok(None), + }; + + let root_cache = self.state_processor.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { + Some(state) => state, + None => return Ok(None), + }; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(None); + } + } + } + + Ok(verifiable_status.status_map.get(&parent_state_id)) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index c4803d6ff..eb0ede98f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -22,9 +22,9 @@ pub struct StorageCacheInfo { } impl StorageCacheInfo { - pub fn new(init_state_id: Option) -> Self { + pub fn new(dec_state_id: Option) -> Self { Self { - dec_state_id: init_state_id, + dec_state_id, last_vote_round: 0, last_qc: None, last_tc: None, diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index b3a01fd60..604e44744 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,10 +2,10 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, + ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -154,6 +154,19 @@ impl StorageEngineGroupState { None => 0, }; + let dec_state_id_in_header = cache + .header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); + + assert_eq!(dec_state_id, dec_state_id_in_header); + if dec_state_id != dec_state_id_in_header { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the state should same as it in header-block", + )); + } + let (prepare_blocks, pre_commit_blocks) = load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { @@ -179,6 +192,10 @@ impl StorageEngineGroupState { .await?, ) } + + pub fn root_cache(&self) -> &ObjectMapRootCacheRef { + self.state_mgr.root_cache() + } } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index ee2618cde..d233025ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -5,7 +5,7 @@ use std::{ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, + ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -15,7 +15,8 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ @@ -56,7 +57,6 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, @@ -84,7 +84,7 @@ impl GroupStorage { GroupStatePath::new(rpath.to_string()), ), local_device_id, - cache: StorageCacheInfo::new(init_state_id), + cache: StorageCacheInfo::new(None), }) } @@ -809,4 +809,100 @@ impl GroupStorage { ) } } + + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let (header_block, qc) = match self.cache.header_block.as_ref() { + Some(block) => { + let (_, qc_block) = self + .cache + .pre_commits + .iter() + .next() + .expect("pre-commit should not be empty"); + + assert_eq!( + qc_block.prev_block_id().unwrap(), + block.block_id().object_id(), + "the prev-block for all pre-commits should be the header" + ); + + (block, qc_block.qc().as_ref().unwrap()) + } + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "the header block is none", + )); + } + }; + + let mut parent_state_id = match header_block.result_state_id() { + Some(state_id) => state_id.clone(), + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map: HashMap::new(), + }) + } + }; + + let mut status_map = HashMap::new(); + + let root_cache = self.storage_engine.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + status_map.insert(parent_state_id, parent_state); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } + } + } + + let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + status_map.insert(parent_state_id, leaf_state); + + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } } diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 9fbc4eb4f..5d005a726 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), // init state + Yes, } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 2ba99716e..0401c55a0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -816,7 +816,7 @@ async fn main_run() { &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -845,7 +845,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -892,7 +892,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); From ad6c6f5509374473b12ddf4edb341f89f5dc45a5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 17:03:44 +0800 Subject: [PATCH 084/553] Example for APP-State as tree --- .../src/consensus/hotstuff/hotstuff.rs | 9 +- .../cyfs-group/src/dec/delegate_factory.rs | 10 +- .../src/storage/engine/storage_engine.rs | 2 +- .../engine/storage_engine_group_state.rs | 23 ++- .../cyfs-group/src/storage/group_storage.rs | 18 +- src/tests/group-example/src/main.rs | 155 +++++++++++++++--- 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 667966a6c..d9773bd88 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,13 +9,13 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, @@ -499,7 +499,7 @@ impl HotstuffRunner { if self .delegate - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -851,6 +851,7 @@ impl HotstuffRunner { .on_commited( &proposal_obj, pre_state_id, + self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1528,7 +1529,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id).await { + match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index bdcb98f60..0b13d97ce 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -34,12 +34,14 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult; @@ -47,7 +49,13 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ); } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index eb0ede98f..cbb5d99df 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 604e44744..aae81394b 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -8,8 +8,8 @@ use cyfs_base::{ use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -672,3 +672,22 @@ fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult Self { + Self { + state_mgr: state_mgr.clone(), + } + } +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { + async fn create_single_op_env(&self) -> BuckyResult { + self.state_mgr.create_single_op_env(ACCESS) + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d233025ab..3a1c20f2a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,12 +15,15 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ - engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + engine::{ + GroupObjectMapProcessorGroupState, StorageCacheInfo, StorageEngineGroupState, + StorageEngineMock, + }, StorageEngine, }; @@ -50,6 +53,7 @@ pub struct GroupStorage { cache: StorageCacheInfo, storage_engine: StorageEngineGroupState, + object_map_processor: GroupObjectMapProcessorGroupState, } impl GroupStorage { @@ -71,6 +75,7 @@ impl GroupStorage { .expect("create group state failed."); let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -85,6 +90,7 @@ impl GroupStorage { ), local_device_id, cache: StorageCacheInfo::new(None), + object_map_processor, }) } @@ -129,6 +135,7 @@ impl GroupStorage { let state_path = GroupStatePath::new(rpath.to_string()); let cache = StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -140,6 +147,7 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, cache, + object_map_processor, }) } @@ -905,4 +913,8 @@ impl GroupStorage { status_map, }); } + + pub fn get_object_map_processor(&self) -> &dyn GroupObjectMapProcessor { + &self.object_map_processor + } } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0401c55a0..0fae6dd53 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -38,16 +38,18 @@ mod Common { CyfsStackNOCParams, CyfsStackParams, }; - lazy_static::lazy_static! { - // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + /** + * |--root + * |--folder1 + * |--folder2 + * |--value-->u64 + */ - // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); + pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } fn create_member( @@ -495,7 +497,7 @@ mod Client { } mod GroupDecService { - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, fmt::format, sync::Arc}; use async_std::sync::Mutex; use cyfs_base::*; @@ -503,9 +505,11 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; use cyfs_stack::CyfsStack; + use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; + pub struct DecService {} impl DecService { @@ -580,17 +584,78 @@ mod GroupDecService { } impl MyRPathDelegate { - pub fn execute( + pub async fn get_value_from_state_tree_with_single_op_envs( + pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<( + Option, + Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + )> { + let mut single_op_envs = vec![]; + let mut parent_map_id = pre_state_id; + for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + let single_op_env = object_map_processor.create_single_op_env().await.expect( + format!( + "create_single_op_env load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + parent_map_id = match parent_map_id { + Some(parent_map_id) => { + single_op_env.load(&parent_map_id).await.expect( + format!( + "load folder {} parent with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + single_op_env.get_by_key(folder).await.expect( + format!( + "load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ) + } + None => { + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!( + "create folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + None + } + }; + single_op_envs.push((single_op_env, folder, parent_map_id)); + } + + Ok((parent_map_id, single_op_envs)) + } + + pub async fn execute( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let result_state_id = { + let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await?; + + let result_value = { /** * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); + let pre_value = pre_value.map_or(0, |pre_value| { + let buf = pre_value.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -608,6 +673,32 @@ mod GroupDecService { .unwrap() }; + let result_state_id = { + let mut sub_folder_value = result_value; + for (parent_single_op_env, folder, sub_folder_prev_value) in + single_op_envs.into_iter().rev() + { + parent_single_op_env + .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + .await + .expect( + format!( + "update folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + sub_folder_value = parent_single_op_env.commit().await.expect( + format!( + "commit folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + } + sub_folder_value + }; + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? @@ -623,7 +714,7 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_state_id + proposal + context + * (result_state_id, return_object) = pre_value + proposal + context */ Ok(ExecuteResult { context, @@ -632,17 +723,20 @@ mod GroupDecService { }) } - pub fn verify( + pub async fn verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context */ - let result = self.execute(proposal, pre_state_id)?; + let result = self + .execute(proposal, pre_state_id, object_map_processor) + .await?; let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() @@ -658,23 +752,28 @@ mod GroupDecService { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id) + self.execute(proposal, pre_state_id, object_map_processor) + .await } async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) + self.verify(proposal, pre_state_id, object_map_processor, execute_result) + .await } async fn on_commited( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { @@ -685,14 +784,28 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let pre_value = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); - let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let result_value = Self::get_value_from_state_tree_with_single_op_envs( + execute_result.result_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); @@ -901,7 +1014,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } From 9dc22318f644890c8d57a4e38c571f78c7e0b453 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 19:51:46 +0800 Subject: [PATCH 085/553] Fix: Update the state structure, mount the template dec-state of blocks in prepare/pre-commit, to avoid it's recycled. --- .../cyfs-base/src/objects/object_map/mod.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 5 +- .../cyfs-group/src/statepath/design.md | 12 +- .../src/statepath/group_statepath.rs | 34 +++ .../src/storage/engine/storage_engine.rs | 20 +- .../engine/storage_engine_group_state.rs | 139 ++++++++-- .../src/storage/engine/storage_engine_mock.rs | 7 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 248 +++++++++++------- 9 files changed, 351 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index 3bbc5f131..75589834b 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -18,6 +18,7 @@ mod visitor; pub use access::*; pub use cache::*; pub use diff::*; +pub use isolate_path_env::*; pub use iterator::*; pub use object_map::*; pub use op_env::*; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 0b13d97ce..f5092dbfc 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,6 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -58,4 +60,5 @@ pub trait RPathDelegate: Sync + Send { #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; } diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index cb964e066..885888d5b 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -22,14 +22,20 @@ | |--users | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-vote-round-->u64 // 最后一次投票的 轮次 | |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block | | -| |--prepares->Set // Prepare状态的block -| |--pre-commits->Set // pre-commit状态的block +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 72f48e601..0ed0abd25 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -10,6 +10,8 @@ pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; @@ -164,10 +166,42 @@ impl GroupStatePath { self.prepares.as_str() } + pub fn prepares_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn prepares_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn pre_commits(&self) -> &str { self.pre_commits.as_str() } + pub fn pre_commits_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn finish_proposals(&self) -> &str { self.finish_proposals.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index cbb5d99df..e14445695 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -43,9 +43,19 @@ impl StorageCacheInfo { #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()>; + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + is_instead: bool, + ) -> BuckyResult<()>; + async fn push_commit( &mut self, height: u64, @@ -54,7 +64,9 @@ pub trait StorageWriter: Send + Sync { prev_result_state_id: &Option, min_height: u64, ) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( &mut self, proposal_ids: &[ObjectId], @@ -62,7 +74,9 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index aae81394b..8b8799207 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,14 +2,15 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, - ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -90,7 +91,8 @@ impl StorageEngineGroupState { None => None, }; - let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let prepare_block_ids = + load_object_ids_with_path_map_key(&op_env, state_path.prepares()).await?; if prepare_block_ids.len() == 0 && commit_range.is_none() { return Err(BuckyError::new( BuckyErrorCode::NotFound, @@ -99,7 +101,7 @@ impl StorageEngineGroupState { } let pre_commit_block_ids = - load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + load_object_ids_with_path_map_key(&op_env, state_path.pre_commits()).await?; let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { @@ -113,8 +115,10 @@ impl StorageEngineGroupState { n }); - let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; - let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + let adding_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.adding()).await?; + let over_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.recycle()).await?; let load_block_ids = [ first_header_block_ids.as_slice(), @@ -233,7 +237,7 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new(ObjectMapSimpleContentType::Map) .await?; None } else { @@ -253,20 +257,51 @@ impl StorageEngineGroupStateWriter { }) } - async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn create_block_result_object_map( + &self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult { + let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await?; + single_op_env + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + if let Some(state_id) = result_state_id.as_ref() { + single_op_env + .insert_with_key(GROUP_STATE_PATH_RESULT_STATE, state_id) + .await?; + } + + single_op_env.commit().await + } + + async fn insert_prepares_inner( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) + .await?; self.prepare_op_env - .insert(block_id) + .insert_with_key(block_id.to_string().as_str(), &block_result_pair) .await - .map(|is_changed| assert!(is_changed)) } async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); if is_instead { self.op_env @@ -274,12 +309,17 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self - .op_env - .insert(self.state_path.pre_commits(), block_id) + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) .await?; - assert!(is_changed); - Ok(()) + + self.op_env + .insert_with_key( + self.state_path.pre_commits(), + block_id.to_string().as_str(), + &block_result_pair, + ) + .await } async fn push_commit_inner( @@ -357,8 +397,11 @@ impl StorageEngineGroupStateWriter { async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); } Ok(()) } @@ -486,19 +529,26 @@ impl StorageEngineGroupStateWriter { #[async_trait::async_trait] impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result = self.insert_prepares_inner(block_id, result_state_id).await; self.write_result.clone() } async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result = self + .insert_pre_commit_inner(block_id, result_state_id, is_instead) + .await; self.write_result.clone() } @@ -614,7 +664,7 @@ fn parse_u64_obj(obj: &ObjectId) -> u64 { u64::from_le_bytes(buf) } -async fn load_object_ids_with_path( +async fn load_object_ids_with_path_set( op_env: &ObjectMapPathOpEnvRef, full_path: &str, ) -> BuckyResult> { @@ -647,6 +697,41 @@ async fn load_object_ids_with_path( Ok(object_ids) } +async fn load_object_ids_with_path_map_key( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Map((key_id_base58, _)) => { + object_ids.push(ObjectId::from_base58(key_id_base58)?) + } + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} + fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { match r { Ok(t) => Ok(Some(t)), @@ -690,4 +775,8 @@ impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { async fn create_single_op_env(&self) -> BuckyResult { self.state_mgr.create_single_op_env(ACCESS) } + + async fn create_sub_tree_op_env(&self) -> BuckyResult { + self.state_mgr.create_isolate_path_op_env(ACCESS) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index ebeedd7ca..fbc7cafdc 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -71,7 +71,11 @@ pub struct StorageEngineMockWriter<'a> { #[async_trait::async_trait] impl<'a> StorageWriter for StorageEngineMockWriter<'a> { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { if !self.engine.prepare_blocks.insert(block_id.clone()) { assert!(false); return Err(BuckyError::new( @@ -85,6 +89,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { if !self.engine.prepare_blocks.remove(block_id) { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a1c20f2a..491d029dd 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -291,10 +291,16 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(block_id.object_id()).await?; - if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_prepares(block_id.object_id(), block.result_state_id()) + .await?; + if let Some((new_pre_commit_id, new_pre_commit)) = new_pre_commit.as_ref() { writer - .insert_pre_commit(new_pre_commit, new_header.is_some()) + .insert_pre_commit( + new_pre_commit_id, + new_pre_commit.result_state_id(), + new_header.is_some(), + ) .await?; } if let Some(new_header) = new_header.as_ref() { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0fae6dd53..394b15acb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -584,59 +584,59 @@ mod GroupDecService { } impl MyRPathDelegate { - pub async fn get_value_from_state_tree_with_single_op_envs( - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, - ) -> BuckyResult<( - Option, - Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - )> { - let mut single_op_envs = vec![]; - let mut parent_map_id = pre_state_id; - for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - let single_op_env = object_map_processor.create_single_op_env().await.expect( - format!( - "create_single_op_env load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - parent_map_id = match parent_map_id { - Some(parent_map_id) => { - single_op_env.load(&parent_map_id).await.expect( - format!( - "load folder {} parent with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - single_op_env.get_by_key(folder).await.expect( - format!( - "load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ) - } - None => { - single_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await - .expect( - format!( - "create folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - None - } - }; - single_op_envs.push((single_op_env, folder, parent_map_id)); - } - - Ok((parent_map_id, single_op_envs)) - } + // pub async fn get_value_from_state_tree_with_single_op_envs( + // pre_state_id: Option, + // object_map_processor: &dyn GroupObjectMapProcessor, + // ) -> BuckyResult<( + // Option, + // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + // )> { + // let mut single_op_envs = vec![]; + // let mut parent_map_id = pre_state_id; + // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + // let single_op_env = object_map_processor.create_single_op_env().await.expect( + // format!( + // "create_single_op_env load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // parent_map_id = match parent_map_id { + // Some(parent_map_id) => { + // single_op_env.load(&parent_map_id).await.expect( + // format!( + // "load folder {} parent with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // single_op_env.get_by_key(folder).await.expect( + // format!( + // "load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ) + // } + // None => { + // single_op_env + // .create_new(ObjectMapSimpleContentType::Map) + // .await + // .expect( + // format!( + // "create folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // None + // } + // }; + // single_op_envs.push((single_op_env, folder, parent_map_id)); + // } + + // Ok((parent_map_id, single_op_envs)) + // } pub async fn execute( &self, @@ -644,11 +644,30 @@ mod GroupDecService { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await?; + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + let pre_value = match pre_state_id { + Some(pre_state_id) => { + state_op_env.load(&pre_state_id).await?; + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ) + } + None => { + state_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ); + None + } + }; let result_value = { /** @@ -674,29 +693,50 @@ mod GroupDecService { }; let result_state_id = { - let mut sub_folder_value = result_value; - for (parent_single_op_env, folder, sub_folder_prev_value) in - single_op_envs.into_iter().rev() - { - parent_single_op_env - .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - .await - .expect( - format!( - "update folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value - ) - .as_str(), - ); - sub_folder_value = parent_single_op_env.commit().await.expect( + state_op_env + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .await + .expect( format!( - "commit folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value + "set_with_path {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value ) .as_str(), ); - } - sub_folder_value + state_op_env.commit().await.expect( + format!( + "commit {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value + ) + .as_str(), + ) + // let mut sub_folder_value = result_value; + // for (parent_single_op_env, folder, sub_folder_prev_value) in + // single_op_envs.into_iter().rev() + // { + // parent_single_op_env + // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + // .await + // .expect( + // format!( + // "update folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // sub_folder_value = parent_single_op_env.commit().await.expect( + // format!( + // "commit folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // } + // sub_folder_value }; let receipt = { @@ -784,13 +824,26 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let pre_value = match pre_state_id { + Some(pre_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&pre_state_id) + .await + .expect(format!("load {} failed", pre_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; @@ -798,13 +851,26 @@ mod GroupDecService { u64::from_be_bytes(pre_value) }); - let result_value = Self::get_value_from_state_tree_with_single_op_envs( - execute_result.result_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let result_value = match execute_result.result_state_id { + Some(result_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&result_state_id) + .await + .expect(format!("load {} failed", result_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; From 1fc6258f5d64d8b4d6d590335dfaa4d30e5aa363 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:00 +0800 Subject: [PATCH 086/553] Accept the invalid block with vote it. --- src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 138 +++++++++++++----- .../cyfs-group/src/storage/group_storage.rs | 102 +------------ 3 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index aaab4ed76..4a7aae6c2 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' +itertools = "0.10.3" cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d9773bd88..511b0b32e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -13,6 +13,7 @@ use cyfs_core::{ }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; +use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, @@ -365,7 +366,7 @@ impl HotstuffRunner { } } - let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, Err(err) => return err }; @@ -391,9 +392,6 @@ impl HotstuffRunner { self, block.block_id()); - self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await?; - self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -402,7 +400,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote, &proposals).await + self.process_block(block, remote, &HashMap::new()).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -574,7 +572,7 @@ impl HotstuffRunner { } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { match self.store.block_linked(block).await .map_err(|err| Err(err))? { @@ -585,16 +583,6 @@ impl HotstuffRunner { ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - Err (Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - ))) - } crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", @@ -605,7 +593,7 @@ impl HotstuffRunner { "duplicate block", ))) } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { + crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", self, @@ -614,7 +602,7 @@ impl HotstuffRunner { // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; - Ok((prev_block, proposals)) + Ok(prev_block) } crate::storage::BlockLinkState::Pending => { log::warn!( @@ -942,20 +930,6 @@ impl HotstuffRunner { return None; } - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 - let mut proposal_temp: HashMap = HashMap::new(); - if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { - Ok(_) => proposals = &proposal_temp, - Err(_) => return None - } - } else { - assert_eq!(proposals.len(), block.proposals().len()); - } - if !Self::check_timestamp_precision(block, proposals) { - return None; - } - // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -982,6 +956,22 @@ impl HotstuffRunner { return None; } + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block.clone()), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None + }, + }, + None => None + }; + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -993,6 +983,77 @@ impl HotstuffRunner { } } + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + return None + } + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + return None; + } + + if proposals.len() != block.proposals().len() { + let mut dup_proposals = block.proposals().clone(); + dup_proposals.sort_unstable_by_key(|p| p.proposal); + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + ); + return None; + } + + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + match block.prev_block_id() { + Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await.map(|is_finished| (is_finished, &proposal_result.proposal)), + None => Ok((false, &proposal_result.proposal)) + } + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok((is_finished, proposal_id)) => { + if is_finished { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + proposal_id + ); + return None; + } + }, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", + self, + block.block_id(), + err + ); + return None; + }, + } + } + + if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await.is_err() { + return None; + } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1021,12 +1082,23 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { false } else { + if let Some(prev_block) = prev_block { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { + if duration > TIME_PRECISION { + return false + } + } + } + for proposal in block.proposals() { let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 491d029dd..04e4c80fc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,22 +1,19 @@ -use std::{ - collections::{HashMap, HashSet}, - time::SystemTime, -}; +use std::collections::{HashMap, HashSet}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ @@ -31,11 +28,10 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, - DuplicateProposal, Duplicate, Link( Option, - HashMap, + // HashMap, ), // Pending, InvalidBranch, @@ -528,18 +524,6 @@ impl GroupStorage { return Ok(BlockLinkState::Duplicate); } - let now = SystemTime::now(); - let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); - - if let Ok(duration) = block_time.duration_since(now) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } - log::debug!( "[group storage] {} block_linked {} step2", self.local_device_id, @@ -554,17 +538,6 @@ impl GroupStorage { } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); - if let Ok(duration) = prev_block_time.duration_since(block_time) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } Some(prev_block) } } @@ -592,66 +565,7 @@ impl GroupStorage { block.block_id() ); - let mut proposals = HashMap::new(); - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? - { - return Ok(BlockLinkState::DuplicateProposal); - } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - - Ok(BlockLinkState::Link( - None, - HashMap::from([(proposal_result.proposal, proposal)]), - )) - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok(result) => match result { - BlockLinkState::Link(_, proposal) => { - let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); - if proposals.get(&proposal_id).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } - proposals.insert(proposal_id, proposal); - } - _ => return Ok(result), - }, - _ => return check_result, - } - } - - log::debug!( - "[group storage] {} block_linked {} step4", - self.local_device_id, - block.block_id() - ); - - Ok(BlockLinkState::Link(prev_block, proposals)) + Ok(BlockLinkState::Link(prev_block)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From 1e7ae1779813ee50ad86890c0d847c9956d614ef Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:55 +0800 Subject: [PATCH 087/553] Chore unused code --- src/component/cyfs-group/src/storage/group_storage.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 04e4c80fc..122ae72ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -29,10 +29,7 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, Duplicate, - Link( - Option, - // HashMap, - ), // + Link(Option), // Pending, InvalidBranch, } From e9f63037465fab73454d6c0321a5e741f78aab2f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 12:20:23 +0800 Subject: [PATCH 088/553] get VerifiableState from the admin --- .../src/consensus/hotstuff/hotstuff.rs | 260 +++++++++++------- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 2 +- src/component/cyfs-group/src/constant.rs | 2 +- .../src/dec_state/dec_state_requestor.rs | 5 + .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../src/objects/group_rpath_status.rs | 21 +- .../cyfs-group/src/objects/protocol.rs | 11 +- .../cyfs-group/src/storage/dec_storage.rs | 6 + .../cyfs-group/src/storage/group_storage.rs | 27 +- src/tests/group-example/Cargo.toml | 3 +- src/tests/group-example/src/main.rs | 79 +++++- 11 files changed, 302 insertions(+), 116 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 511b0b32e..10c5d9635 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -4,7 +4,7 @@ use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, + RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -19,11 +19,13 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * + * synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -212,6 +214,7 @@ struct HotstuffRunner { round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, + max_quorum_round: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -311,6 +314,7 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, + max_quorum_round: round - 1, state_pusher, tx_block_gen, rx_block_gen, @@ -366,15 +370,6 @@ impl HotstuffRunner { } } - let prev_block = match self.check_block_linked(&block, remote).await { - Ok(link) => link, - Err(err) => return err - }; - - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", - self, - block.block_id()); - self.committee .verify_block(block, remote) .await @@ -388,6 +383,18 @@ impl HotstuffRunner { err })?; + let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); + self.update_max_quorum_round(quorum_round); + + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + + let prev_block = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err + }; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", self, block.block_id()); @@ -452,10 +459,19 @@ impl HotstuffRunner { block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, + remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = prev_block - .as_ref() - .map_or(None, |block| block.result_state_id().clone()); + let mut prev_state_id = match prev_block + .as_ref() { + Some(prev_block) => { + let result_state_id = block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; + } + result_state_id.clone() + }, + None => None + }; for proposal_exe_info in block.proposals() { // 去重 @@ -672,7 +688,7 @@ impl HotstuffRunner { err })?; - if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", self, header_block.block_id() @@ -696,29 +712,18 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(header_block.clone(), qc_block).await; + self.notify_block_committed(&header_block, &old_header_block, qc_block).await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", self, block.block_id() ); - let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self, self.round, err - ); - - err - }); - // notify by leader - if let Ok(leader) = leader { - if self.local_device_id == leader { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } + if &self.local_id == header_block.owner() { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; } log::debug!( @@ -733,7 +738,7 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, the qc of block {:?} has received before", self, block.block_id() ); - return self.process_block_qc(qc, block, remote).await; + return self.process_block_qc(qc, block).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( @@ -762,7 +767,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block, proposals).await { + if let Some(vote) = self.make_vote(block, proposals, &remote).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -791,22 +796,12 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - let mut pre_state_id = match new_header.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); + + let mut pre_state_id = old_header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); for proposal in new_header.proposals() { let proposal_obj = self @@ -900,6 +895,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_round(&mut self, quorum_round: u64) { + if quorum_round > self.max_quorum_round { + self.max_quorum_round = quorum_round; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -922,7 +923,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -930,6 +931,13 @@ impl HotstuffRunner { return None; } + if self.max_quorum_round >= self.round { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } + // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -1002,6 +1010,10 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + self, + block.block_id(), + ); return None; } @@ -1016,44 +1028,15 @@ impl HotstuffRunner { return None; } - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - match block.prev_block_id() { - Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await.map(|is_finished| (is_finished, &proposal_result.proposal)), - None => Ok((false, &proposal_result.proposal)) - } - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok((is_finished, proposal_id)) => { - if is_finished { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", - self, - block.block_id(), - proposal_id - ); - return None; - } - }, - Err(err) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", - self, - block.block_id(), - err - ); - return None; - }, - } + if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err + ); + return None; } - if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await.is_err() { - return None; - } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1075,7 +1058,12 @@ impl HotstuffRunner { } }; - if self.store.set_last_vote_round(block.round()).await.is_err() { + if let Err(err) = self.store.set_last_vote_round(block.round()).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for update last-vote-round failed {:?}", + self, + block.block_id(), + err + ); return None; } @@ -1086,23 +1074,39 @@ impl HotstuffRunner { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + block.block_id(), + block_timestamp, + now + ); + false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); + let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + block.block_id(), + block_timestamp, + prev_block_time + ); return false } } } for proposal in block.proposals() { - let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_id = proposal.proposal; + let proposal = proposals.get(&proposal_id).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + block.block_id(), + block_timestamp, + proposal_id, + proposal_timestamp + ); return false } } @@ -1174,7 +1178,7 @@ impl HotstuffRunner { if is_prev_none {"None"} else {"Some"} ); - self.process_block_qc(qc, &block, remote).await?; + self.process_block_qc(qc, &block).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1185,7 +1189,6 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, - remote: ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1334,7 +1337,10 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - + + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1453,6 +1459,9 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1501,8 +1510,7 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ) - .await.map_err(|err| { + ).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", self, err @@ -1541,7 +1549,13 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let prev_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), + Some(qc) => { + let prev_block = self.store.find_block_in_cache(&qc.block_id)?; + if let Some(result_state_id) = prev_block.result_state_id() { + self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + } + Some(prev_block) + }, None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1940,6 +1954,58 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } + async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 + let obj_map_processor = self.store.get_object_map_processor(); + + #[async_recursion::async_recursion] + async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if non_driver.get_object(&root_id, None).await.is_ok() { + // TODO: 可能有下级分支子树因为异常不齐全 + return Ok(()); + } + let obj = non_driver.get_object(root_id, Some(remote)).await?; + match obj.object.as_ref() { + Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { + let single_op_env = obj_map_processor.create_single_op_env().await?; + single_op_env.load(root_id).await?; + loop { + let branchs = single_op_env.next(16).await?; + for branch in branchs.list.iter() { + let branch_id = match branch { + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Map(map) => &map.1, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Set(set) => set, + }; + make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + } + + if branchs.list.len() < 16 { + return Ok(()) + } + } + }, + _ => return Ok(()) + } + } + + let mut result = Ok(()); + for remote in remotes { + result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + if result.is_ok() { + return result; + } + } + result + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 82f4017a0..f44260a04 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 1170176b2..77a652a7e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,7 +17,7 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; -pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(5000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 0a3544c09..790429c6c 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -154,6 +154,11 @@ impl DecStateRequestorRunner { .await .map(|r| r.cloned()); + log::debug!( + "handle_verifiable_state sub_path: {}, result: {:?}", + sub_path, + result + ); self.query_state_notifier.reply(&sub_path, result).await } Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cc0b4aff2..b1506a192 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -13,7 +13,7 @@ use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), - BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), // LastStateRequest(ObjectId), DelayBroadcast, } diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index 858c37fff..bfc9bc5d2 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -69,8 +69,25 @@ impl<'de> RawDecode<'de> for GroupRPathStatus { assert_eq!(remain.len(), 0); let mut status_map = HashMap::new(); for obj_buf in proto.status_list.iter() { - let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; - assert_eq!(remain.len(), 0); + log::debug!("will decode len: {}", obj_buf.len()); + // size + object_id + let status = if obj_buf.len() > OBJECT_ID_LEN + 1 { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status + } else if obj_buf.len() == OBJECT_ID_LEN + 1 { + NONObjectInfo::new( + ObjectId::clone_from_slice(&obj_buf.as_slice()[1..])?, + obj_buf.clone(), + None, + ) + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidData, + "expect NONObjectInfo", + )); + }; + status_map.insert(status.object_id, status); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 6c9f89e96..932e5cd46 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use itertools::Itertools; use sha2::Digest; use crate::GroupRPathStatus; @@ -185,12 +186,13 @@ impl std::fmt::Debug for HotstuffMessage { result.as_ref().map(|status| { let desc = status.block_desc.content(); format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ) }) ) @@ -315,12 +317,13 @@ impl std::fmt::Debug for HotstuffPackage { |status| { let desc = status.block_desc.content(); let ok = format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ); Ok(ok) } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index de5a0fd4a..60a45724f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -69,6 +69,10 @@ impl DecStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { Some(state) => state, None => return Ok(None), @@ -98,6 +102,8 @@ impl DecStorage { assert_eq!(remain.len(), 0); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 122ae72ab..966fa518a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, - ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, @@ -223,7 +223,13 @@ impl GroupStorage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - ) -> BuckyResult)>> { + ) -> BuckyResult< + Option<( + &GroupConsensusBlock, + Option, + Vec, + )>, + > { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); @@ -399,9 +405,10 @@ impl GroupStorage { } } - self.cache.header_block = Some(new_header); + let old_header_block = self.cache.header_block.replace(new_header); return Ok(Some(( self.cache.header_block.as_ref().unwrap(), + old_header_block, removed_blocks, ))); } @@ -736,6 +743,7 @@ impl GroupStorage { } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + // TODO: 需要一套通用的同步ObjectMap树的实现 let (header_block, qc) = match self.cache.header_block.as_ref() { Some(block) => { let (_, qc_block) = self @@ -778,6 +786,9 @@ impl GroupStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { @@ -806,6 +817,8 @@ impl GroupStorage { status_map.insert(parent_state_id, parent_state); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder @@ -821,7 +834,11 @@ impl GroupStorage { } } - let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + let leaf_state = if parent_state_id.is_data() { + NONObjectInfo::new(parent_state_id, parent_state_id.to_vec()?, None) + } else { + self.non_driver.get_object(&parent_state_id, None).await? + }; status_map.insert(parent_state_id, leaf_state); return Ok(GroupRPathStatus { diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 0053ccd5f..01094f12a 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -27,4 +27,5 @@ cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } -cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 394b15acb..618336df4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -14,7 +14,7 @@ use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; mod Common { use std::{fmt::format, io::ErrorKind, sync::Arc}; @@ -505,8 +505,15 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + use cyfs_group::{ + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, + }; + use cyfs_lib::{ + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, + }; use cyfs_stack::CyfsStack; + use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -522,10 +529,42 @@ mod GroupDecService { Box::new(GroupRPathDelegateFactory { local_name }), ) .await - .unwrap() + .unwrap(); + + // let source = RequestSourceInfo { + // protocol: todo!(), + // zone: todo!(), + // dec: todo!(), + // verified: todo!(), + // }; + + // cyfs_stack + // .router_handlers() + // .handlers(&RouterHandlerChain::PostRouter) + // .post_object() + // .add_handler(RouterHandler::new()); } } + // pub struct PostProposalRoutine { + // controller: RPathControl, + // } + + // #[async_trait::async_trait] + // impl EventListenerAsyncRoutine + // for PostProposalRoutine + // { + // async fn call( + // &self, + // param: &NONPostObjectInputRequest, + // ) -> BuckyResult { + // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // self.controller.push_proposal(proposal).await?; + // Ok(NONPostObjectInputResponse { object: None }) + // } + // } + pub struct GroupRPathDelegateFactory { local_name: String, } @@ -778,6 +817,16 @@ mod GroupDecService { .execute(proposal, pre_state_id, object_map_processor) .await?; + log::info!( + "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + execute_result.result_state_id, + execute_result.context.is_none(), + execute_result.receipt.is_none(), + result.result_state_id, + result.context.is_none(), + result.receipt.is_none() + ); + let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() && execute_result.receipt.is_none(); @@ -1007,7 +1056,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 1000usize; + let PROPOSAL_COUNT = 5usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1085,6 +1134,28 @@ async fn main_run() { log::info!("will push new proposals, i: {}", i); } } + + let client = admin_stacks + .get(0) + .unwrap() + .group_mgr() + .rpath_client( + &group.desc().object_id(), + dec_app_id.object_id(), + &EXAMPLE_RPATH, + ) + .await + .unwrap(); + + let value_obj = client + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .unwrap(); + let buf = value_obj.as_ref().unwrap().object_id.data(); + let mut value = [0u8; 8]; + value.copy_from_slice(&buf[..8]); + + log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From 762b34f3e8601c875f3ab9fb878bc7a38999693e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 15:46:00 +0800 Subject: [PATCH 089/553] Fix: result-state verify failed --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++++++++++++++---- src/tests/group-example/src/main.rs | 3 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 10c5d9635..e142d4069 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -464,7 +464,7 @@ impl HotstuffRunner { let mut prev_state_id = match prev_block .as_ref() { Some(prev_block) => { - let result_state_id = block.result_state_id(); + let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; } @@ -520,14 +520,24 @@ impl HotstuffRunner { err })? { + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); + prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", self, proposal_exe_info.proposal, - prev_state_id, - proposal_exe_info.result_state + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); @@ -966,7 +976,7 @@ impl HotstuffRunner { let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block.clone()), + Ok(block) => Some(block), Err(_) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", self, @@ -1960,11 +1970,18 @@ impl HotstuffRunner { #[async_recursion::async_recursion] async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if root_id.is_data() { + return Ok(()); + } + if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await?; + let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { + log::warn!("get branch {} failed {:?}", root_id, err); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { let single_op_env = obj_map_processor.create_single_op_env().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 618336df4..4daa0d4f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -818,7 +818,8 @@ mod GroupDecService { .await?; log::info!( - "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + pre_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), From e222cdd29b730eb4b665af3a50c412ad05bc6ce5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 28 Feb 2023 20:27:49 +0800 Subject: [PATCH 090/553] Redefine the Group object for Permission --- .../protos/standard_objects-permission.proto | 203 ++++++++++++++++++ src/tests/group-example/src/main.rs | 8 +- 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto new file mode 100644 index 000000000..b2ec61f60 --- /dev/null +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -0,0 +1,203 @@ +syntax="proto3"; + +// contract +message ContractBodyContent { + bytes data = 1; +} + +// device +message DeviceBodyContent { + repeated bytes endpoints = 1; + repeated bytes sn_list = 2; + repeated bytes passive_pn_list = 3; + optional string name = 4; + optional uint32 bdt_version = 5; +} + +// dir +message DirBodyContent { + enum Type { + Chunk = 0; + ObjList = 1; + } + Type type = 1; + optional bytes chunk_id = 2; + + // 使用list编码hash_map + message ObjItem { + bytes obj_id = 1; + bytes value = 2; + } + repeated ObjItem obj_list = 3; +} + +// file +message ChunkList { + enum Type { + ChunkInList = 0; + ChunkInFile = 1; + ChunkInBundle = 2; + } + enum HashMethod { + Serial = 0; + } + + Type type = 1; + repeated bytes chunk_id_list = 2; + bytes file_id = 3; + optional HashMethod hash_method = 4; +} + +message FileBodyContent { + ChunkList chunk_list = 1; +} + +// people +message PeopleBodyContent { + repeated bytes ood_list = 1; + optional string name = 2; + optional bytes icon = 3; + optional string ood_work_mode = 4; +} + +message GroupRPathPermissionWeight { + string rpath = 1; + GroupFunctionPermissionWeight weight = 2; +} + +message GroupDecPermissionWeight { + bytes dec_id = 1; + optional GroupRPathPermissionWeight default_dec_weight = 2; + repeated GroupRPathPermissionWeight rpath_weight = 3; +} + +message GroupMember { + bytes id = 1; + string title = 2; + // uint64 shares = 3; delay + optional GroupGlobalPermissionWeight global_weight = 4; + optional GroupDecPermissionWeight weight = 5; +} + +/** +admin 修改管理员列表 +member 修改成员列表 +display-${scope} 修改展示信息 + ${scope}=g: 修改group信息 + ${scope}=s: 修改自身信息 + ${scope}=m: 修改任意member信息 + ${scope}=a: 修改任意admin信息 +property 修改资产信息 +conclusion 修改决议类别列表 +conclusion-${category} 修改决议类别配置 +it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) +c-${any} 其他自定义(custom)权限 +*/ + +message GroupGlobalPermissionWeight { + optional uint32 admin = 1; + optional uint32 member = 2; + optional uint32 display_group = 3; + optional uint32 display_self = 4; + optional uint32 display_member = 5; + optional uint32 display_admin = 6; + optional uint32 property = 7; +} + +message GroupCommonPermissionWeight { + string category = 1; + uint32 weight = 2; +} + +message GroupFunctionPermissionWeight { + optional uint32 it = 1; + optional uint32 conclusion = 2; + repeated GroupCommonPermissionWeight conclusion_category = 3; + repeated GroupCommonPermissionWeight custom = 4; +} + +message GroupITConfig { + repeated bytes ood_list = 8; + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms +} + +message GroupConclusionConfig { + string category = 1; + uint64 lifespan = 2; // ms +} + +message GroupConfigItem { + optional GroupITConfig it = 1; + repeated GroupConclusionConfig conclusions = 2; + optional GroupFunctionPermissionWeight weight_threshold = 3; +} + +message GroupRPathConfig { + string rpath = 1; + GroupConfigItem config = 2; +} + +message GroupDecConfig { + bytes dec_id = 1; + optional GroupConfigItem default_dec_config = 2; + repeated GroupRPathConfig rpath_configs = 3; +} + +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; + + repeated GroupMember members = 4; + + // uint64 total_equity = 5; // delay + + repeated bytes revoked_conclusions = 6; + + GroupConfigItem default_config = 7; + repeated GroupDecConfig dec_configs = 8; + + GroupGlobalPermissionWeight global_weight_threshold = 9; + GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + + uint64 version = 11; +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} + +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} + +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; +} + +// tx +message TxBodyContent { + bytes data = 1; +} + +// proof_of_service +message ProofData { + bytes data = 1; +} + +message ProofOfServiceBodyContent { + ProofData data = 1; +} \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 4daa0d4f1..ef2366de0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1051,13 +1051,13 @@ async fn main_run() { .unwrap(); } - async_std::task::sleep(Duration::from_millis(30000)).await; + async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 5usize; + let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1130,12 +1130,14 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } + async_std::task::sleep(Duration::from_millis(10000)).await; + let client = admin_stacks .get(0) .unwrap() From c4bd83853ce953a6781acf490b71cc99d2148719 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 14:41:55 +0800 Subject: [PATCH 091/553] Simplify group definition --- .../protos/standard_objects-permission.proto | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto index b2ec61f60..09f9e3684 100644 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -60,89 +60,9 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } -message GroupRPathPermissionWeight { - string rpath = 1; - GroupFunctionPermissionWeight weight = 2; -} - -message GroupDecPermissionWeight { - bytes dec_id = 1; - optional GroupRPathPermissionWeight default_dec_weight = 2; - repeated GroupRPathPermissionWeight rpath_weight = 3; -} - message GroupMember { bytes id = 1; string title = 2; - // uint64 shares = 3; delay - optional GroupGlobalPermissionWeight global_weight = 4; - optional GroupDecPermissionWeight weight = 5; -} - -/** -admin 修改管理员列表 -member 修改成员列表 -display-${scope} 修改展示信息 - ${scope}=g: 修改group信息 - ${scope}=s: 修改自身信息 - ${scope}=m: 修改任意member信息 - ${scope}=a: 修改任意admin信息 -property 修改资产信息 -conclusion 修改决议类别列表 -conclusion-${category} 修改决议类别配置 -it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) -c-${any} 其他自定义(custom)权限 -*/ - -message GroupGlobalPermissionWeight { - optional uint32 admin = 1; - optional uint32 member = 2; - optional uint32 display_group = 3; - optional uint32 display_self = 4; - optional uint32 display_member = 5; - optional uint32 display_admin = 6; - optional uint32 property = 7; -} - -message GroupCommonPermissionWeight { - string category = 1; - uint32 weight = 2; -} - -message GroupFunctionPermissionWeight { - optional uint32 it = 1; - optional uint32 conclusion = 2; - repeated GroupCommonPermissionWeight conclusion_category = 3; - repeated GroupCommonPermissionWeight custom = 4; -} - -message GroupITConfig { - repeated bytes ood_list = 8; - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms -} - -message GroupConclusionConfig { - string category = 1; - uint64 lifespan = 2; // ms -} - -message GroupConfigItem { - optional GroupITConfig it = 1; - repeated GroupConclusionConfig conclusions = 2; - optional GroupFunctionPermissionWeight weight_threshold = 3; -} - -message GroupRPathConfig { - string rpath = 1; - GroupConfigItem config = 2; -} - -message GroupDecConfig { - bytes dec_id = 1; - optional GroupConfigItem default_dec_config = 2; - repeated GroupRPathConfig rpath_configs = 3; } message CommonGroupBodyContent { @@ -152,17 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - // uint64 total_equity = 5; // delay - - repeated bytes revoked_conclusions = 6; - - GroupConfigItem default_config = 7; - repeated GroupDecConfig dec_configs = 8; - - GroupGlobalPermissionWeight global_weight_threshold = 9; - GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + repeated bytes ood_list = 5; - uint64 version = 11; + optional bytes prev_version = 6; + uint64 version_num = 7; } // simple_group @@ -184,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx From f96efc78b3d5ea833e0ecaf24bfa04751ba4db05 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 20:16:27 +0800 Subject: [PATCH 092/553] Move the interface to cyfs-lib --- .../src/consensus/hotstuff/hotstuff.rs | 8 +++--- .../cyfs-group/src/dec/group_manager.rs | 6 ++--- src/component/cyfs-group/src/dec/mod.rs | 6 ++--- .../cyfs-group/src/dec/rpath_control.rs | 3 ++- .../engine/storage_engine_group_state.rs | 6 ++--- .../cyfs-group/src/storage/group_storage.rs | 6 ++--- .../src/group}/delegate_factory.rs | 2 +- .../cyfs-lib/src/group/group_manager.rs | 20 ++++++++++++++ src/component/cyfs-lib/src/group/mod.rs | 7 +++++ .../cyfs-lib/src/group/rpath_client.rs | 27 +++++++++++++++++++ src/component/cyfs-lib/src/lib.rs | 6 +++-- src/tests/group-example/src/main.rs | 8 +++--- 12 files changed, 79 insertions(+), 26 deletions(-) rename src/component/{cyfs-group/src/dec => cyfs-lib/src/group}/delegate_factory.rs (98%) create mode 100644 src/component/cyfs-lib/src/group/group_manager.rs create mode 100644 src/component/cyfs-lib/src/group/mod.rs create mode 100644 src/component/cyfs-lib/src/group/rpath_client.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e142d4069..52dcdd650 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,15 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, + GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7b7fbbbe..60ddba1fb 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,11 +6,11 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; use crate::{ - storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, + NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index b4e753a27..8a43844b2 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,11 +1,9 @@ // dec framework -mod delegate_factory; +mod group_manager; mod rpath_client; mod rpath_control; -mod group_manager; -pub use delegate_factory::*; +pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 7abff1ec1..c3a25b060 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,10 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathDelegate, + PendingProposalHandler, PendingProposalMgr, }; struct RPathControlRaw { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 8b8799207..adf11c7e4 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,11 +6,11 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_lib::GroupObjectMapProcessor; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, - GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, - GROUP_STATE_PATH_RESULT_STATE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 966fa518a..fa6f4930f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,11 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-lib/src/group/delegate_factory.rs similarity index 98% rename from src/component/cyfs-group/src/dec/delegate_factory.rs rename to src/component/cyfs-lib/src/group/delegate_factory.rs index f5092dbfc..9e55ff8f4 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-lib/src/group/delegate_factory.rs @@ -1,8 +1,8 @@ +use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-lib/src/group/group_manager.rs new file mode 100644 index 000000000..7d836ae49 --- /dev/null +++ b/src/component/cyfs-lib/src/group/group_manager.rs @@ -0,0 +1,20 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +use crate::{DelegateFactory, RPathClient}; + +#[derive(Clone)] +pub struct GroupManager; + +impl GroupManager { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self) { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-lib/src/group/mod.rs new file mode 100644 index 000000000..482d9ea0d --- /dev/null +++ b/src/component/cyfs-lib/src/group/mod.rs @@ -0,0 +1,7 @@ +mod delegate_factory; +mod group_manager; +mod rpath_client; + +pub use delegate_factory::*; +pub use group_manager::*; +pub use rpath_client::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-lib/src/group/rpath_client.rs new file mode 100644 index 000000000..4162abe68 --- /dev/null +++ b/src/component/cyfs-lib/src/group/rpath_client.rs @@ -0,0 +1,27 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{GroupProposal, GroupRPath}; + +use crate::NONObjectInfo; + +struct RPathClientRaw {} + +#[derive(Clone)] +pub struct RPathClient(Arc); + +impl RPathClient { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index b1a7bd497..e91d4d612 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,9 +4,11 @@ mod base; mod crypto; mod default_app; mod events; +mod group; mod ndn; mod non; mod prelude; +mod requestor; mod rmeta; mod root_state; mod router_handler; @@ -17,7 +19,6 @@ mod trans; mod util; mod ws; mod zone; -mod requestor; pub use crate::util::*; pub use acl::*; @@ -26,9 +27,11 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; +pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; +pub use requestor::*; pub use rmeta::*; pub use root_state::*; pub use router_handler::*; @@ -38,7 +41,6 @@ pub use sync::*; pub use trans::*; pub use ws::*; pub use zone::*; -pub use requestor::*; // 重新导出cache相关接口,由于bdt层的依赖关系,只能放在util工程 pub use cyfs_util::cache::*; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ef2366de0..42544e51c 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,12 +505,10 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, - }; + use cyfs_group::RPathControl; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, + NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, }; use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; From 4af09a0ca2ebd8614339e60a3f4ea39f7d9ecec1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 12:20:30 +0800 Subject: [PATCH 093/553] Remove the `decide` from proposal, It seems unuseful --- .../cyfs-core/protos/core_objects.proto | 9 +- .../cyfs-core/src/group/group_proposal.rs | 415 +++++++++--------- src/component/cyfs-core/src/group/mod.rs | 10 +- 3 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 487ece4bd..abd299e9d 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -352,7 +352,7 @@ message GroupProposalDescContent { message GroupProposalBodyContent { optional bytes payload = 1; - +/* message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; @@ -360,8 +360,10 @@ message GroupProposalBodyContent { } repeated Signature decide_signatures = 2; +*/ } +/* message GroupUpdateGroupPropsalParam { repeated bytes target_dec_id = 1; // the proccesor decs optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) @@ -373,6 +375,7 @@ message GroupPropsalDecideParam { bytes proposal_id = 2; bytes decide = 3; } +*/ message HotstuffBlockQc { bytes block_id = 1; @@ -431,6 +434,7 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } +/* message GroupActionDescContent { // target GroupRPath r_path = 1; @@ -441,4 +445,5 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 10aeed798..bf28aafb2 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,4 +1,4 @@ -use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; +use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use sha2::Digest; @@ -34,45 +34,44 @@ impl DescContent for GroupProposalDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone)] -pub struct GroupProposalSignature { - signature: Signature, - proponent_id: ObjectId, - decide: Vec, -} - -impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> - for GroupProposalSignature -{ - fn transform( - value: &crate::codec::protos::group_proposal_body_content::Signature, - ) -> BuckyResult { - Ok(Self { - signature: Signature::raw_decode(value.signature.as_slice())?.0, - proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, - decide: value.decide.clone(), - }) - } -} - -impl ProtobufTransform<&GroupProposalSignature> - for crate::codec::protos::group_proposal_body_content::Signature -{ - fn transform(value: &GroupProposalSignature) -> BuckyResult { - Ok(Self { - signature: value.signature.to_vec()?, - proponent_id: value.proponent_id.to_vec()?, - decide: value.decide.clone(), - }) - } -} +// #[derive(Clone)] +// pub struct GroupProposalSignature { +// signature: Signature, +// proponent_id: ObjectId, +// decide: Vec, +// } + +// impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> +// for GroupProposalSignature +// { +// fn transform( +// value: &crate::codec::protos::group_proposal_body_content::Signature, +// ) -> BuckyResult { +// Ok(Self { +// signature: Signature::raw_decode(value.signature.as_slice())?.0, +// proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, +// decide: value.decide.clone(), +// }) +// } +// } + +// impl ProtobufTransform<&GroupProposalSignature> +// for crate::codec::protos::group_proposal_body_content::Signature +// { +// fn transform(value: &GroupProposalSignature) -> BuckyResult { +// Ok(Self { +// signature: value.signature.to_vec()?, +// proponent_id: value.proponent_id.to_vec()?, +// decide: value.decide.clone(), +// }) +// } +// } #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] pub struct GroupProposalBodyContent { payload: Option>, - - decide_signatures: Vec, + // decide_signatures: Vec, } impl BodyContent for GroupProposalBodyContent { @@ -85,14 +84,14 @@ impl ProtobufTransform for GroupProposalBodyContent { fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push(GroupProposalSignature::transform(sign)?); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push(GroupProposalSignature::transform(sign)?); + // } Ok(Self { payload: value.payload, - decide_signatures, + // decide_signatures, }) } } @@ -101,16 +100,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> for crate::codec::protos::GroupProposalBodyContent { fn transform(value: &GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push( - crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, - ); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push( + // crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + // ); + // } Ok(Self { payload: value.payload.clone(), - decide_signatures, + // decide_signatures, }) } } @@ -143,17 +142,17 @@ impl GroupProposalDescContent { } impl GroupProposalBodyContent { - fn hash_decide_signature( - proposal_id: &ObjectId, - proponent_id: &ObjectId, - decide: &[u8], - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(proposal_id.as_slice()); - sha256.input(proponent_id.as_slice()); - sha256.input(decide); - sha256.result().into() - } + // fn hash_decide_signature( + // proposal_id: &ObjectId, + // proponent_id: &ObjectId, + // decide: &[u8], + // ) -> HashValue { + // let mut sha256 = sha2::Sha256::new(); + // sha256.input(proposal_id.as_slice()); + // sha256.input(proponent_id.as_slice()); + // sha256.input(decide); + // sha256.result().into() + // } } #[async_trait] @@ -182,27 +181,27 @@ pub trait GroupProposalObject { fn payload(&self) -> &Option>; fn set_payload(&mut self, payload: Option>); - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult>; - - fn decided_members_no_verify(&self) -> &Vec; - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult; - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()>; + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult>; + + // fn decided_members_no_verify(&self) -> &Vec; + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult; + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()>; } #[async_trait] @@ -231,7 +230,7 @@ impl GroupProposalObject for GroupProposal { desc, GroupProposalBodyContent { payload, - decide_signatures: vec![], + // decide_signatures: vec![], }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) @@ -252,9 +251,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { - Some(params) => { - HashValue::try_from(params.as_slice()).map(|h| Some(h)) - } + Some(params) => HashValue::try_from(params.as_slice()).map(|h| Some(h)), None => Ok(None), } } @@ -298,134 +295,130 @@ impl GroupProposalObject for GroupProposal { self.body_mut().as_mut().unwrap().content_mut().payload = payload; } - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult> { - let signs = self - .body() - .as_ref() - .unwrap() - .content() - .decide_signatures - .as_slice(); - - let proposal_id = self.desc().object_id(); - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - - let mut decides = vec![]; - - for sign in signs { - if &sign.proponent_id == member_id { - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &sign.proponent_id, - sign.decide.as_slice(), - ); - - if verifier.verify(hash.as_slice(), &sign.signature).await { - decides.push(sign.decide.as_slice()); - } else { - return Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )); - } - } - } - - Ok(decides) - } - - fn decided_members_no_verify(&self) -> &Vec { - &self.body().as_ref().unwrap().content().decide_signatures - } - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult { - let signs = &self.body().as_ref().unwrap().content().decide_signatures; - - if signs.iter().find(|s| s.proponent_id == member_id).is_some() { - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicated decide", - )); - } - - let proposal_id = self.desc().object_id(); - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.as_slice(), - ); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - let sign = signer - .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) - .await?; - - Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) - } - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()> { - let proposal_id = self.desc().object_id(); - - if decide.proposal_id() != &proposal_id { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - format!( - "proposal id not match for decide signature: {}/{}", - proposal_id, - decide.proposal_id() - ), - )); - } - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.decide(), - ); - - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - if verifier.verify(hash.as_slice(), decide.signature()).await { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - for exist in signs.iter() { - if &exist.proponent_id == &member_id && exist.decide == decide.decide() { - return Ok(()); - } - } - - signs.push(GroupProposalSignature { - signature: decide.signature().clone(), - proponent_id: member_id, - decide: Vec::from(decide.decide()), - }); - - Ok(()) - } else { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )) - } - } + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult> { + // let signs = self + // .body() + // .as_ref() + // .unwrap() + // .content() + // .decide_signatures + // .as_slice(); + + // let proposal_id = self.desc().object_id(); + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + // let mut decides = vec![]; + + // for sign in signs { + // if &sign.proponent_id == member_id { + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &sign.proponent_id, + // sign.decide.as_slice(), + // ); + + // if verifier.verify(hash.as_slice(), &sign.signature).await { + // decides.push(sign.decide.as_slice()); + // } else { + // return Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )); + // } + // } + // } + + // Ok(decides) + // } + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult { + // let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + // if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + // return Err(BuckyError::new( + // BuckyErrorCode::AlreadyExists, + // "duplicated decide", + // )); + // } + + // let proposal_id = self.desc().object_id(); + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.as_slice(), + // ); + + // let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + // let sign = signer + // .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + // .await?; + + // Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) + // } + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()> { + // let proposal_id = self.desc().object_id(); + + // if decide.proposal_id() != &proposal_id { + // return Err(BuckyError::new( + // BuckyErrorCode::NotMatch, + // format!( + // "proposal id not match for decide signature: {}/{}", + // proposal_id, + // decide.proposal_id() + // ), + // )); + // } + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.decide(), + // ); + + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + // if verifier.verify(hash.as_slice(), decide.signature()).await { + // let signs = &mut self + // .body_mut() + // .as_mut() + // .unwrap() + // .content_mut() + // .decide_signatures; + // for exist in signs.iter() { + // if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + // return Ok(()); + // } + // } + + // signs.push(GroupProposalSignature { + // signature: decide.signature().clone(), + // proponent_id: member_id, + // decide: Vec::from(decide.decide()), + // }); + + // Ok(()) + // } else { + // Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )) + // } + // } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b2885d637..4310f48a5 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,13 +1,15 @@ mod group_consensus_block; mod group_proposal; -mod group_proposal_decide_param; +// mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_update_group_proposal_param; +// mod group_update_group_proposal_param; +mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; -pub use group_proposal_decide_param::*; +// pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_update_group_proposal_param::*; +// pub use group_update_group_proposal_param::*; +pub use group_protocol::*; From 6ba64c598f97d05494acb4dd4e6b73af80d361e1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 20:52:45 +0800 Subject: [PATCH 094/553] Prepare for export interface to SDK --- .../cyfs-core/protos/core_objects.proto | 2 +- src/component/cyfs-core/src/coreobj.rs | 1 + src/component/cyfs-core/src/group/mod.rs | 2 - src/component/cyfs-group-lib/Cargo.toml | 34 ++ .../{cyfs-group => cyfs-group-lib}/build.rs | 27 +- .../protos/group_bft_protocol.proto | 63 +++ src/component/cyfs-group-lib/readme.md | 14 + .../src/delegate.rs} | 18 +- .../src}/group_manager.rs | 6 +- .../mod.rs => cyfs-group-lib/src/lib.rs} | 6 +- .../cyfs-group-lib/src/objects/certificate.rs | 190 ++++++++ .../cyfs-group-lib/src/objects/codec/mod.rs | 3 + .../src/objects/group_command.rs | 428 ++++++++++++++++++ .../src/objects/group_decide_proposal.rs | 0 .../src/objects/group_rpath_status.rs | 6 +- .../src/objects/group_update_proposal.rs | 0 .../cyfs-group-lib/src/objects/mod.rs | 12 + .../src}/rpath_client.rs | 3 +- src/component/cyfs-group/Cargo.toml | 3 +- .../protos/group_bft_protocol.proto | 23 - .../src/consensus/hotstuff/hotstuff.rs | 60 +-- .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 7 +- .../cyfs-group/src/dec/group_events.rs | 42 ++ .../cyfs-group/src/dec/group_manager.rs | 94 ++-- src/component/cyfs-group/src/dec/mod.rs | 2 + .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec/rpath_control.rs | 8 +- .../src/dec_state/dec_state_requestor.rs | 6 +- .../src/dec_state/dec_state_synchronizer.rs | 64 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/helper/mod.rs | 2 - src/component/cyfs-group/src/helper/verify.rs | 16 - src/component/cyfs-group/src/lib.rs | 4 - src/component/cyfs-group/src/network/mod.rs | 2 + .../src/{objects => network}/protocol.rs | 306 +++---------- src/component/cyfs-group/src/objects/mod.rs | 9 - .../cyfs-group/src/storage/dec_storage.rs | 9 +- .../engine/storage_engine_group_state.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 7 +- src/component/cyfs-group/src/utils.rs | 8 - src/component/cyfs-lib/src/lib.rs | 2 - 42 files changed, 977 insertions(+), 529 deletions(-) create mode 100644 src/component/cyfs-group-lib/Cargo.toml rename src/component/{cyfs-group => cyfs-group-lib}/build.rs (66%) create mode 100644 src/component/cyfs-group-lib/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group-lib/readme.md rename src/component/{cyfs-lib/src/group/delegate_factory.rs => cyfs-group-lib/src/delegate.rs} (81%) rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/group_manager.rs (100%) rename src/component/{cyfs-lib/src/group/mod.rs => cyfs-group-lib/src/lib.rs} (56%) create mode 100644 src/component/cyfs-group-lib/src/objects/certificate.rs create mode 100644 src/component/cyfs-group-lib/src/objects/codec/mod.rs create mode 100644 src/component/cyfs-group-lib/src/objects/group_command.rs rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_decide_proposal.rs (100%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_rpath_status.rs (93%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_update_proposal.rs (100%) create mode 100644 src/component/cyfs-group-lib/src/objects/mod.rs rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/rpath_client.rs (94%) delete mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group/src/dec/group_events.rs delete mode 100644 src/component/cyfs-group/src/helper/verify.rs rename src/component/cyfs-group/src/{objects => network}/protocol.rs (70%) delete mode 100644 src/component/cyfs-group/src/objects/mod.rs delete mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index abd299e9d..742c14904 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -446,4 +446,4 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; } -*/ \ No newline at end of file +*/ diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3d53a082f..8eb96a930 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupAction = 704, GroupQuorumCertificate = 705, + GroupCommand = 706, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4310f48a5..d7134a3c0 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,7 +4,6 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; @@ -12,4 +11,3 @@ pub use group_proposal::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; -pub use group_protocol::*; diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml new file mode 100644 index 000000000..e7cfda851 --- /dev/null +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -0,0 +1,34 @@ + +[package] +name = 'cyfs-group-lib' +version = '0.1.1' +authors = ['zhangzhen '] +edition = '2021' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +prost-build = { version = '0.9.0' } +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +itertools = "0.10.3" +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group-lib/build.rs similarity index 66% rename from src/component/cyfs-group/build.rs rename to src/component/cyfs-group-lib/build.rs index 8d4efe9c9..206d6bc6f 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group-lib/build.rs @@ -37,28 +37,13 @@ fn gen_protos() { } fn main() { - println!("cargo:rerun-if-env-changed=VERSION"); - println!("cargo:rerun-if-env-changed=CHANNEL"); - println!("cargo:rerun-if-env-changed=TARGET"); - println!( - "cargo:rustc-env=VERSION={}", - std::env::var("VERSION").unwrap_or("0".to_owned()) - ); - println!( - "cargo:rustc-env=CHANNEL={}", - std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) - ); - println!( - "cargo:rustc-env=TARGET={}", - std::env::var("TARGET").unwrap() - ); - + println!("cargo:rerun-if-changed=protos"); println!( - "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + "cargo:warning={}", + format!( + "cyfs-core run build script, OUT_DIR={}", + std::env::var("OUT_DIR").unwrap() + ) ); - - println!("cargo:rerun-if-changed=protos"); - gen_protos(); } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto new file mode 100644 index 000000000..2bfdd8d21 --- /dev/null +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -0,0 +1,63 @@ + +syntax = "proto3"; + +message HotstuffBlockQCVote { + bytes block_id = 1; + optional bytes prev_block_id = 2; + uint64 round = 3; + bytes voter = 4; + bytes signature = 5; +} + +message HotstuffTimeoutVote { + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; +} + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} + +// GroupCommand + +message GroupCommandDescContent { + +} + +message GroupCommandNewRPath { + bytes group_id = 1; + string rpath = 2; + optional bytes with_block = 3; // Block.to_vec() +} + +message GroupCommandExecute { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId +} + +message GroupCommandExecuteResult { + optional bytes result_state_id = 1; // ObjectId + optional bytes receipt = 2; // NONObjectInfo.to_vec() + optional bytes context = 3; // Vec +} + +message GroupCommandVerify { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec +} + +message GroupCommandCommited { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec + bytes block = 6; // Block.to_vec() +} diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group-lib/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-lib/src/group/delegate_factory.rs b/src/component/cyfs-group-lib/src/delegate.rs similarity index 81% rename from src/component/cyfs-lib/src/group/delegate_factory.rs rename to src/component/cyfs-group-lib/src/delegate.rs index 9e55ff8f4..21b1e6346 100644 --- a/src/component/cyfs-lib/src/group/delegate_factory.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,25 +1,17 @@ -use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult>; - - async fn on_state_changed( &self, group_id: &ObjectId, rpath: &str, - state_id: Option, - pre_state_id: Option, - ); + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()>; } pub struct ExecuteResult { @@ -30,8 +22,6 @@ pub struct ExecuteResult { #[async_trait::async_trait] pub trait RPathDelegate: Sync + Send { - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; - async fn on_execute( &self, proposal: &GroupProposal, @@ -45,7 +35,7 @@ pub trait RPathDelegate: Sync + Send { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult; + ) -> BuckyResult<()>; async fn on_commited( &self, diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs similarity index 100% rename from src/component/cyfs-lib/src/group/group_manager.rs rename to src/component/cyfs-group-lib/src/group_manager.rs index 7d836ae49..8c82bc9e1 100644 --- a/src/component/cyfs-lib/src/group/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -6,15 +6,15 @@ use crate::{DelegateFactory, RPathClient}; pub struct GroupManager; impl GroupManager { - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { unimplemented!() } - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn unregister(&self) { unimplemented!() } } diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-group-lib/src/lib.rs similarity index 56% rename from src/component/cyfs-lib/src/group/mod.rs rename to src/component/cyfs-group-lib/src/lib.rs index 482d9ea0d..199307bcc 100644 --- a/src/component/cyfs-lib/src/group/mod.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,7 +1,9 @@ -mod delegate_factory; +mod delegate; mod group_manager; +mod objects; mod rpath_client; -pub use delegate_factory::*; +pub use delegate::*; pub use group_manager::*; +pub use objects::*; pub use rpath_client::*; diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs new file mode 100644 index 000000000..32b1b53c8 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -0,0 +1,190 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, HashValue, ObjectId, ObjectLink, ProtobufDecode, + ProtobufEncode, ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, + RawEncodePurpose, RsaCPUObjectSigner, Signature, SignatureSource, Signer, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffBlockQcVote)] +pub struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub prev_block_id: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.block_id().object_id(); + let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let signature = signer + .sign( + hash.as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + block_id: block_id.clone(), + round, + voter: local_device_id, + signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) + } + + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: super::codec::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for super::codec::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffTimeoutVote)] +pub struct HotstuffTimeoutVote { + pub high_qc: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: Option, + round: u64, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_device_id, + signature, + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + } + + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: super::codec::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffTimeoutVote { + high_qc: match value.high_qc.as_ref() { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} diff --git a/src/component/cyfs-group-lib/src/objects/codec/mod.rs b/src/component/cyfs-group-lib/src/objects/codec/mod.rs new file mode 100644 index 000000000..66df9053f --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/codec/mod.rs @@ -0,0 +1,3 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs new file mode 100644 index 000000000..912ced438 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -0,0 +1,428 @@ +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, NamedObjType, NamedObject, + NamedObjectBase, NamedObjectBuilder, NamedObjectId, ObjectId, ProtobufDecode, ProtobufEncode, + ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, RawEncode, RawEncodePurpose, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, +}; + +use cyfs_core::{CoreObjectType, GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandDescContent)] +pub struct GroupCommandDescContent {} + +impl DescContent for GroupCommandDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupCommand as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupCommandDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Debug)] +pub enum GroupCommandType { + NewRPath, + Execute, + ExecuteResult, + Verify, + Commited, +} + +#[derive(Clone, RawEncode, RawDecode)] +pub enum GroupCommandBodyContent { + NewRPath(GroupCommandNewRPath), + Execute(GroupCommandExecute), + ExecuteResult(GroupCommandExecuteResult), + Verify(GroupCommandVerify), + Commited(GroupCommandCommited), +} + +pub type GroupCommandObjectType = NamedObjType; +pub type GroupCommandBuilder = NamedObjectBuilder; + +pub type GroupCommandId = NamedObjectId; +pub type GroupCommand = NamedObjectBase; + +impl GroupCommandBodyContent { + pub fn cmd_type(&self) -> GroupCommandType { + match self { + GroupCommandBodyContent::NewRPath(_) => GroupCommandType::NewRPath, + GroupCommandBodyContent::Execute(_) => GroupCommandType::Execute, + GroupCommandBodyContent::ExecuteResult(_) => GroupCommandType::ExecuteResult, + GroupCommandBodyContent::Verify(_) => GroupCommandType::Verify, + GroupCommandBodyContent::Commited(_) => GroupCommandType::Commited, + } + } +} + +pub trait GroupCommandObject { + fn cmd_type(&self) -> GroupCommandType; + fn into_cmd(self) -> GroupCommandBodyContent; +} + +impl GroupCommandObject for GroupCommand { + fn cmd_type(&self) -> GroupCommandType { + self.body().as_ref().unwrap().content().cmd_type() + } + + fn into_cmd(self) -> GroupCommandBodyContent { + self.into_body().unwrap().into_content() + } +} + +impl BodyContent for GroupCommandBodyContent { + fn version(&self) -> u8 { + 0 + } + + fn format(&self) -> u8 { + cyfs_base::OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupCommandBodyContent") + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandNewRPath)] +pub struct GroupCommandNewRPath { + pub group_id: ObjectId, + pub rpath: String, + pub with_block: Option, +} + +impl ProtobufTransform for GroupCommandNewRPath { + fn transform(value: super::codec::protos::GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: ObjectId::raw_decode(value.group_id.as_slice())?.0, + with_block: match value.with_block.as_ref() { + Some(buf) => Some(GroupConsensusBlock::raw_decode(buf.as_slice())?.0), + None => None, + }, + rpath: value.rpath, + }) + } +} + +impl ProtobufTransform<&GroupCommandNewRPath> for super::codec::protos::GroupCommandNewRPath { + fn transform(value: &GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: value.group_id.to_vec()?, + rpath: value.rpath.clone(), + with_block: match value.with_block.as_ref() { + Some(block) => Some(block.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecute)] +pub struct GroupCommandExecute { + pub proposal: GroupProposal, + pub prev_state_id: Option, +} + +impl ProtobufTransform for GroupCommandExecute { + fn transform(value: super::codec::protos::GroupCommandExecute) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecute> for super::codec::protos::GroupCommandExecute { + fn transform(value: &GroupCommandExecute) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecuteResult)] +pub struct GroupCommandExecuteResult { + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform + for GroupCommandExecuteResult +{ + fn transform(value: super::codec::protos::GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecuteResult> + for super::codec::protos::GroupCommandExecuteResult +{ + fn transform(value: &GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandVerify)] +pub struct GroupCommandVerify { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform for GroupCommandVerify { + fn transform(value: super::codec::protos::GroupCommandVerify) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + receipt: match value.receipt { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupCommandVerify { + fn transform(value: &GroupCommandVerify) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] +pub struct GroupCommandCommited { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, + pub block: GroupConsensusBlock, +} + +impl ProtobufTransform for GroupCommandCommited { + fn transform(value: super::codec::protos::GroupCommandCommited) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, + }, + block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { + fn transform(value: &GroupCommandCommited) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + block: value.block.to_vec()?, + }) + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandNewRPath) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::NewRPath(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecute) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Execute(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecuteResult) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::ExecuteResult(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandVerify) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Verify(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandCommited) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Commited(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::NewRPath(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect NewRPath", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Execute(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Execute", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::ExecuteResult(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect ExecuteResult", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Verify(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Verify", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Commited(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Commited", cmd_type), + )), + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_decide_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs similarity index 93% rename from src/component/cyfs-group/src/objects/group_rpath_status.rs rename to src/component/cyfs-group-lib/src/objects/group_rpath_status.rs index bfc9bc5d2..ae656b5ad 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs @@ -21,7 +21,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -42,7 +42,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -56,7 +56,7 @@ impl RawEncode for GroupRPathStatus { impl<'de> RawDecode<'de> for GroupRPathStatus { fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let proto = super::codec::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::Failed, msg) diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_update_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_update_proposal.rs diff --git a/src/component/cyfs-group-lib/src/objects/mod.rs b/src/component/cyfs-group-lib/src/objects/mod.rs new file mode 100644 index 000000000..668afe8cf --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/mod.rs @@ -0,0 +1,12 @@ +mod group_command; +// mod group_decide_proposal; +mod group_rpath_status; +// mod group_update_proposal; +mod certificate; +mod codec; + +pub use group_command::*; +// pub use group_decide_proposal::*; +pub use group_rpath_status::*; +// pub use group_update_proposal::*; +pub use certificate::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs similarity index 94% rename from src/component/cyfs-lib/src/group/rpath_client.rs rename to src/component/cyfs-group-lib/src/rpath_client.rs index 4162abe68..2fea6dcf7 100644 --- a/src/component/cyfs-lib/src/group/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -5,8 +5,7 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupProposal, GroupRPath}; - -use crate::NONObjectInfo; +use cyfs_lib::NONObjectInfo; struct RPathClientRaw {} diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 4a7aae6c2..1caf5b9a4 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,5 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto deleted file mode 100644 index 621186522..000000000 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ /dev/null @@ -1,23 +0,0 @@ - -syntax = "proto3"; - -message HotstuffBlockQCVote { - bytes block_id = 1; - optional bytes prev_block_id = 2; - uint64 round = 3; - bytes voter = 4; - bytes signature = 5; -} - -message HotstuffTimeoutVote { - optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) - uint64 round = 2; - bytes voter = 3; - bytes signature = 4; -} - -message GroupRPathStatus { - bytes block_desc = 1; // GroupConsensusBlockDescContent - bytes certificate = 2; // HotstuffBlockQC for block - repeated bytes status_list = 4; // Array> -} \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52dcdd650..cc555298b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,16 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; +use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, }; /** @@ -51,7 +52,7 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -81,7 +82,7 @@ impl Hotstuff { rx_message, proposal_consumer, state_pusher_runner, - delegate, + event_notifier, rpath2, ) .run() @@ -224,7 +225,7 @@ struct HotstuffRunner { tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, synchronizer: Synchronizer, rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, @@ -251,7 +252,7 @@ impl HotstuffRunner { rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, state_pusher: StatePusher, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); @@ -307,7 +308,7 @@ impl HotstuffRunner { network_sender, tx_message, rx_message, - delegate, + event_notifier, synchronizer, non_driver, rpath, @@ -511,37 +512,25 @@ impl HotstuffRunner { context: proposal_exe_info.context.clone(), }; - if self - .delegate - .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) + self + .event_notifier + .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); err - })? - { - log::debug!( - "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + })?; - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); - return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); - } + prev_state_id = proposal_exe_info.result_state; } assert_eq!( @@ -840,11 +829,10 @@ impl HotstuffRunner { None => None, }; - self.delegate + self.event_notifier .on_commited( &proposal_obj, pre_state_id, - self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1625,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { + match self.event_notifier.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ad3a21e35..398274723 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -14,9 +14,10 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::network::NONDriverHelper; #[derive(Clone)] pub(crate) struct Committee { diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index f44260a04..6a9735a7f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,13 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, -}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, HotstuffTimeout, HotstuffTimeoutSign, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::Committee; pub(crate) struct VoteMgr { committee: Committee, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs new file mode 100644 index 000000000..67f79cfdd --- /dev/null +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -0,0 +1,42 @@ +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_group_lib::ExecuteResult; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone)] +pub(crate) struct RPathEventNotifier {} + +impl RPathEventNotifier { + pub fn new() -> Self { + unimplemented!() + } + + pub async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 60ddba1fb..95bdbcd17 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,15 +2,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, - NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, + RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -22,7 +22,6 @@ type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - delegate_by_dec: HashMap>, control_by_group: ControlByGroup, client_by_group: ClientByGroup, } @@ -33,6 +32,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,12 +54,12 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { control_by_group: ControlByGroup::default(), client_by_group: ClientByGroup::default(), - delegate_by_dec: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -69,29 +69,12 @@ impl GroupManager { Ok(mgr) } - pub async fn register( - &self, - dec_id: DecAppId, - delegate_factory: Box, - ) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec - .insert(dec_id.object_id().clone(), delegate_factory); - Ok(()) - } - - pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec.remove(dec_id.object_id()); - Ok(()) - } - pub async fn find_rpath_control( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -204,7 +187,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, Some(&block), Some(&remote), ) @@ -220,7 +203,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -236,7 +219,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -252,7 +235,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -268,7 +251,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -284,7 +267,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -331,7 +314,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::No, + false, None, Some(&remote), ) @@ -378,7 +361,7 @@ impl GroupManager { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -398,7 +381,6 @@ impl GroupManager { { // write - let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); @@ -411,6 +393,7 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -424,40 +407,25 @@ impl GroupManager { let store = match store { Ok(store) => Some(store), Err(e) => { - if let IsCreateRPath::No = is_auto_create { - return Err(e); - } if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - None + + self.on_new_rpath_request(group_id, dec_id, rpath, block) + .await?; + + if !is_auto_create { + return Err(e); + } else { + None + } } else { return Err(e); } } }; - // TODO: query group - let group = non_driver - .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) - .await?; - let mut raw = self.write().await; - let delegate = { - let delegate_factory = raw.delegate_by_dec.get(dec_id); - if delegate_factory.is_none() { - return Err(BuckyError::new( - BuckyErrorCode::DecNotRunning, - "dec not running for the rpath-control", - )); - } - let delegate_factory = delegate_factory.unwrap(); - - delegate_factory - .create_rpath_delegate(&group, rpath, block) - .await? - }; - let store = match store { Some(store) => store, None => { @@ -489,7 +457,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - Arc::new(delegate), + event_notifier, network_sender, non_driver, store, @@ -501,4 +469,14 @@ impl GroupManager { } } } + + async fn on_new_rpath_request( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 8a43844b2..2ad717514 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,9 +1,11 @@ // dec framework +mod group_events; mod group_manager; mod rpath_client; mod rpath_control; +pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 8a1dd34a7..08be0f5a0 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -224,10 +224,10 @@ impl RPathClient { HotstuffMessage::Timeout(tc) => unreachable!(), HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), HotstuffMessage::LastStateRequest => unreachable!(), - HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffMessage::StateChangeNotify(header_block, qc) => { self.0 .state_sync - .on_state_change(header_block, qc_block, remote) + .on_state_change(header_block, qc, remote) .await } HotstuffMessage::ProposalResult(proposal_id, result) => { diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c3a25b060..593d82db4 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::RPathDelegate; +use cyfs_group_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, + PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; struct RPathControlRaw { @@ -26,7 +26,7 @@ impl RPathControl { local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, - delegate: Arc>, + event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, store: GroupStorage, @@ -46,7 +46,7 @@ impl RPathControl { network_sender.clone(), non_driver, pending_proposal_consumer, - delegate, + event_notifier, rpath.clone(), ); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 790429c6c..8fd67496b 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,13 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, - CHANNEL_CAPACITY, -}; +use crate::{storage::DecStorage, Committee, HotstuffMessage, CHANNEL_CAPACITY}; use super::{CallReplyNotifier, CallReplyWaiter}; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 7272b3882..e019db892 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -2,15 +2,12 @@ use std::{collections::HashSet, sync::Arc}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, -}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, Committee, CHANNEL_CAPACITY, @@ -21,13 +18,9 @@ use super::{CallReplyNotifier, CallReplyWaiter}; enum DecStateSynchronizerMessage { ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, ), - StateChange(GroupConsensusBlock, GroupConsensusBlock), + StateChange(GroupConsensusBlock, HotstuffBlockQC), DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } @@ -81,11 +74,7 @@ impl DecStateSynchronizer { pub async fn on_proposal_complete( &self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { self.0 @@ -100,13 +89,13 @@ impl DecStateSynchronizer { pub async fn on_state_change( &self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { self.0 .tx_dec_state_sync_message .send(( - DecStateSynchronizerMessage::StateChange(header_block, qc_block), + DecStateSynchronizerMessage::StateChange(header_block, qc), remote, )) .await; @@ -121,7 +110,7 @@ struct DecStateSynchronizerCache { struct UpdateNotifyInfo { header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remotes: HashSet, group_chunk_id: ObjectId, group: Group, @@ -178,15 +167,11 @@ impl DecStateSynchronizerRunner { async fn handle_proposal_complete( &mut self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { match result { - Ok((result, header_block, qc_block)) => { + Ok((result, header_block, qc)) => { if header_block .proposals() .iter() @@ -200,7 +185,7 @@ impl DecStateSynchronizerRunner { } if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_err() { @@ -226,11 +211,11 @@ impl DecStateSynchronizerRunner { async fn handle_state_change( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_ok() { @@ -251,11 +236,7 @@ impl DecStateSynchronizerRunner { for remote in notify_info.remotes.iter() { match self .store - .sync( - ¬ify_info.header_block, - ¬ify_info.qc_block, - remote.clone(), - ) + .sync(¬ify_info.header_block, ¬ify_info.qc, remote.clone()) .await { Ok(_) => { @@ -264,7 +245,7 @@ impl DecStateSynchronizerRunner { state_cache: DecStorageCache { state: notify_info.header_block.result_state_id().clone(), header_block: notify_info.header_block.clone(), - qc_block: notify_info.qc_block.clone(), + qc: notify_info.qc.clone(), }, group_chunk_id: notify_info.group_chunk_id, group: notify_info.group.clone(), @@ -316,14 +297,9 @@ impl DecStateSynchronizerRunner { async fn push_update_notify( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { - if qc_block.qc().is_none() { - log::warn!("the qc is none for qc-block({})", qc_block.block_id()); - return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); - } - if let Some(notify) = self.update_notifies.as_mut() { match notify.header_block.height().cmp(&header_block.height()) { std::cmp::Ordering::Less => {} @@ -338,11 +314,7 @@ impl DecStateSynchronizerRunner { if header_block.check() && self .committee - .verify_block_desc_with_qc( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - remote, - ) + .verify_block_desc_with_qc(header_block.named_object().desc(), &qc, remote) .await .is_ok() { @@ -354,7 +326,7 @@ impl DecStateSynchronizerRunner { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, - qc_block: qc_block, + qc: qc, remotes: HashSet::from([remote]), group_chunk_id, group, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b1506a192..571c1ca13 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -194,7 +194,11 @@ impl StateChanggeRunner { .post_message( HotstuffMessage::ProposalResult( exe_info.proposal, - Ok((receipt, block.clone(), qc_block.clone())), + Ok(( + receipt, + block.clone(), + qc_block.qc().as_ref().unwrap().clone(), + )), ), rpath.clone(), &proposer, @@ -320,7 +324,7 @@ impl StateChanggeRunner { let msg = HotstuffMessage::StateChangeNotify( progress.header_block.clone(), - progress.qc_block.clone(), + progress.qc_block.qc().as_ref().unwrap().clone(), ); if notify_targets.len() > 0 { diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index ce36043a3..4d3f1b1c6 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,5 +1,3 @@ mod timer; -mod verify; pub use timer::*; -pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs deleted file mode 100644 index ef3e34495..000000000 --- a/src/component/cyfs-group/src/helper/verify.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, -}; - -use crate::GroupRPathStatus; - -pub async fn verify_rpath_value( - value: &GroupRPathStatus, - sub_path: &str, - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - unimplemented!() -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index ba8e83569..c493f13c5 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -4,10 +4,8 @@ mod dec; mod dec_state; mod helper; mod network; -mod objects; mod statepath; mod storage; -mod utils; pub use consensus::*; pub use constant::*; @@ -15,7 +13,5 @@ pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; pub use network::*; -pub use objects::*; pub use statepath::*; pub(crate) use storage::*; -pub use utils::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index f79e67dd4..096bd0950 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,7 +1,9 @@ mod listener; mod non_driver; +mod protocol; mod sender; pub(crate) use listener::*; pub use non_driver::*; +pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs similarity index 70% rename from src/component/cyfs-group/src/objects/protocol.rs rename to src/component/cyfs-group/src/network/protocol.rs index 932e5cd46..7e32fdc4d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -1,16 +1,8 @@ -pub mod protos { - include!(concat!(env!("OUT_DIR"), "/mod.rs")); -} - use cyfs_base::*; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_group_lib::{GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; use itertools::Itertools; -use sha2::Digest; - -use crate::GroupRPathStatus; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { @@ -96,15 +88,11 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, - ), // (proposal-id, (ExecuteResult, block, qc-block)) + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, + ), // (proposal-id, (ExecuteResult, block, qc)) QueryState(String), VerifiableState(String, BuckyResult), } @@ -151,8 +139,8 @@ impl std::fmt::Debug for HotstuffMessage { "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest => { @@ -169,8 +157,8 @@ impl std::fmt::Debug for HotstuffMessage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) }) ) @@ -214,16 +202,12 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) LastStateRequest(ProtocolAddress), ProposalResult( ObjectId, Result< - ( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - ), + (Option, GroupConsensusBlock, HotstuffBlockQC), (BuckyError, ProtocolAddress), >, ), // (proposal-id, ExecuteResult) @@ -276,8 +260,8 @@ impl std::fmt::Debug for HotstuffPackage { "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest(_) => { @@ -296,8 +280,8 @@ impl std::fmt::Debug for HotstuffPackage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ); Ok(ok) } @@ -394,23 +378,25 @@ fn decode_with_length<'de, O: RawDecode<'de>>( impl RawEncode for HotstuffPackage { fn raw_measure(&self, purpose: &Option) -> BuckyResult { let len = match self { - HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::Block(b) => 3 + b.raw_measure(purpose)?, HotstuffPackage::BlockVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::TimeoutVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::Timeout(addr, tc) => { - 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + tc.raw_measure(purpose)? } HotstuffPackage::SyncRequest(addr, min, max) => { - addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + + min.raw_measure(purpose)? + + max.raw_measure(purpose)? } HotstuffPackage::StateChangeNotify(block, qc) => { - 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + 3 + qc.raw_measure(purpose)? } - HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::LastStateRequest(addr) => 2 + addr.raw_measure(purpose)?, HotstuffPackage::ProposalResult(id, result) => { id.raw_measure(purpose)? + match result { @@ -418,22 +404,23 @@ impl RawEncode for HotstuffPackage { non.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + + 3 + block_qc.raw_measure(purpose)? } Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } HotstuffPackage::QueryState(addr, sub_path) => { - addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } HotstuffPackage::VerifiableState(sub_path, result) => { sub_path.raw_measure(purpose)? + match result { - Ok(status) => status.raw_measure(purpose)?, + Ok(status) => 3 + status.raw_measure(purpose)?, Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } @@ -451,43 +438,43 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::Block(b) => { buf[0] = 0; let buf = &mut buf[1..]; - b.raw_encode(buf, purpose) + encode_with_length(buf, b, purpose, 3) } HotstuffPackage::BlockVote(addr, vote) => { buf[0] = 1; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::TimeoutVote(addr, vote) => { buf[0] = 2; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::Timeout(addr, tc) => { buf[0] = 3; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - tc.raw_encode(buf, purpose) + encode_with_length(buf, tc, purpose, 3) } HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; + encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; - let buf = max.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + max.raw_encode(buf, purpose) } HotstuffPackage::StateChangeNotify(block, qc) => { buf[0] = 5; let buf = &mut buf[1..]; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } HotstuffPackage::LastStateRequest(addr) => { buf[0] = 6; let buf = &mut buf[1..]; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; @@ -501,19 +488,19 @@ impl RawEncode for HotstuffPackage { Ok((non, block, qc)) => { let buf = non.raw_encode(buf, purpose)?; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } HotstuffPackage::QueryState(addr, sub_path) => { buf[0] = 8; let buf = &mut buf[1..]; - let buf = sub_path.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2)?; + sub_path.raw_encode(buf, purpose) } HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; @@ -523,10 +510,10 @@ impl RawEncode for HotstuffPackage { let buf = &mut buf[1..]; let buf = sub_path.raw_encode(buf, purpose)?; match result { - Ok(status) => status.raw_encode(buf, purpose), + Ok(status) => encode_with_length(buf, status, purpose, 3), Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } @@ -542,49 +529,49 @@ impl<'de> RawDecode<'de> for HotstuffPackage { match pkg_type { 0 => { let buf = &buf[1..]; - let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (b, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } @@ -596,7 +583,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { true => { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), @@ -605,7 +592,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } @@ -613,8 +600,8 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } 8 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } @@ -624,13 +611,13 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (sub_path, buf) = String::raw_decode(buf)?; match is_ok { true => { - let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + let (status, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), @@ -698,188 +685,5 @@ impl ProtocolAddress { } } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] -pub(crate) struct HotstuffBlockQCVote { - pub block_id: ObjectId, - pub prev_block_id: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let block_id = block.block_id().object_id(); - let round = block.round(); - - log::debug!( - "[block vote] local: {:?}, vote hash {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let hash = Self::hash_content(block_id, block.prev_block_id(), round); - - log::debug!( - "[block vote] local: {:?}, vote sign {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let signature = signer - .sign( - hash.as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - block_id: block_id.clone(), - round, - voter: local_device_id, - signature, - prev_block_id: block.prev_block_id().map(|id| id.clone()), - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) - } - - fn hash_content( - block_id: &ObjectId, - prev_block_id: Option<&ObjectId>, - round: u64, - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(block_id.as_slice()); - sha256.input(round.to_le_bytes()); - if let Some(prev_block_id) = prev_block_id { - sha256.input(prev_block_id.as_slice()); - } - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffBlockQCVote { - fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, - round: value.round, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), - None => None, - }, - }) - } -} - -impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { - fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { - let ret = crate::protos::HotstuffBlockQcVote { - block_id: value.block_id.to_vec()?, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(id.to_vec()?), - None => None, - }, - }; - - Ok(ret) - } -} - -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] -pub(crate) struct HotstuffTimeoutVote { - pub high_qc: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffTimeoutVote { - pub async fn new( - high_qc: Option, - round: u64, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let signature = signer - .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - high_qc, - round, - voter: local_device_id, - signature, - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) - } - - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(high_qc_round.to_le_bytes()); - sha256.input(round.to_le_bytes()); - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffTimeoutVote { - fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { - let high_qc = if value.high_qc().len() == 0 { - None - } else { - Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) - }; - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - round: value.round, - high_qc, - }) - } -} - -impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { - fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { - let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc.as_ref() { - Some(qc) => Some(qc.to_vec()?), - None => None, - }, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - }; - - Ok(ret) - } -} - #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs deleted file mode 100644 index 5d1a8b13f..000000000 --- a/src/component/cyfs-group/src/objects/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod group_decide_proposal; -mod group_rpath_status; -mod group_update_proposal; -mod protocol; - -pub use group_decide_proposal::*; -pub use group_rpath_status::*; -pub use group_update_proposal::*; -pub use protocol::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 60a45724f..0d937487c 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -5,16 +5,17 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; +use crate::STATE_PATH_SEPARATOR; #[derive(Clone)] pub struct DecStorageCache { pub state: Option, pub header_block: GroupConsensusBlock, - pub qc_block: GroupConsensusBlock, + pub qc: HotstuffBlockQC, } #[derive(Clone)] @@ -42,7 +43,7 @@ impl DecStorage { pub async fn sync( &self, header_block: &GroupConsensusBlock, - qc_block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index adf11c7e4..63158a865 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_lib::GroupObjectMapProcessor; +use cyfs_group_lib::GroupObjectMapProcessor; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index fa6f4930f..a1a681259 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; +use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, + STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs deleted file mode 100644 index 5d005a726..000000000 --- a/src/component/cyfs-group/src/utils.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cyfs_base::ObjectId; - -pub type Round = u64; - -pub enum IsCreateRPath { - No, - Yes, -} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index e91d4d612..80b572e2c 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,7 +4,6 @@ mod base; mod crypto; mod default_app; mod events; -mod group; mod ndn; mod non; mod prelude; @@ -27,7 +26,6 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; -pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; From b0ee75349ea31b7f9de76b7432541c1e3de2fa77 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 12:15:59 +0800 Subject: [PATCH 095/553] Implement the events with post_object --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- .../cyfs-group/src/dec/group_events.rs | 120 +++++++++++++++--- .../cyfs-group/src/dec/group_manager.rs | 50 ++++++-- .../cyfs-group/src/dec/rpath_client.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 19 ++- .../cyfs-stack/src/stack/group_non_driver.rs | 8 +- 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index cc555298b..eaaaed06e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -514,7 +514,7 @@ impl HotstuffRunner { self .event_notifier - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal.clone(), prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -831,14 +831,14 @@ impl HotstuffRunner { self.event_notifier .on_commited( - &proposal_obj, + proposal_obj, pre_state_id, &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, - &new_header, + new_header.clone(), ) .await; @@ -1613,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.event_notifier.on_execute(&proposal, result_state_id).await { + match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 67f79cfdd..fc3d12c63 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,42 +1,132 @@ use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_group_lib::ExecuteResult; +use cyfs_group_lib::{ + ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandVerify, +}; use cyfs_lib::NONObjectInfo; +use crate::NONDriverHelper; + #[derive(Clone)] -pub(crate) struct RPathEventNotifier {} +pub(crate) struct RPathEventNotifier { + non_driver: NONDriverHelper, +} impl RPathEventNotifier { - pub fn new() -> Self { - unimplemented!() + pub fn new(driver: NONDriverHelper) -> Self { + Self { non_driver: driver } } pub async fn on_execute( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, ) -> BuckyResult { - unimplemented!() + let cmd = GroupCommandExecute { + proposal, + prev_state_id, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_some()); + match result.as_ref() { + Some(result) => { + let (cmd, _remain) = GroupCommand::raw_decode(result.object_raw.as_slice())?; + assert_eq!(_remain.len(), 0); + let mut cmd = TryInto::::try_into(cmd)?; + Ok(ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }) + } + None => Err(BuckyError::new( + BuckyErrorCode::Unknown, + "expect some result from dec-app", + )), + } } pub async fn on_verify( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandVerify { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } pub async fn on_commited( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, - block: &GroupConsensusBlock, + block: GroupConsensusBlock, ) { - unimplemented!() + let cmd = GroupCommandCommited { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec().expect( + format!("on_commited {} failed for encode", self.non_driver.dec_id()) + .as_str(), + ), + object: None, + }, + None, + ) + .await + .map_err(|err| log::warn!("on_commited {} failed {:?}", self.non_driver.dec_id(), err)); + + assert!(result.is_err() || result.unwrap().is_none()); } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95bdbcd17..346e75d02 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,11 +2,13 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -32,7 +34,6 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, - event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,7 +55,6 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, - event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { @@ -393,7 +393,6 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -410,8 +409,13 @@ impl GroupManager { if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - self.on_new_rpath_request(group_id, dec_id, rpath, block) - .await?; + self.on_new_rpath_request( + group_id.clone(), + dec_id, + rpath.to_string(), + block.cloned(), + ) + .await?; if !is_auto_create { return Err(e); @@ -457,7 +461,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - event_notifier, + RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, store, @@ -472,11 +476,33 @@ impl GroupManager { async fn on_new_rpath_request( &self, - group_id: &ObjectId, + group_id: ObjectId, dec_id: &ObjectId, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, + rpath: String, + with_block: Option, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandNewRPath { + group_id, + rpath, + with_block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .local_info() + .non_driver + .post_object( + dec_id, + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 08be0f5a0..41db0c25c 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -100,7 +100,7 @@ impl RPathClient { match self .0 .non_driver - .post_object(non_proposal.clone(), ood) + .post_object(non_proposal.clone(), Some(ood)) .await { Ok(r) => post_result = Some(Ok(())), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 979451b79..c7f9e7d93 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, }; @@ -29,8 +29,8 @@ pub trait NONDriver: Send + Sync { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()>; + to: Option<&ObjectId>, + ) -> BuckyResult>; } #[derive(Clone)] @@ -49,6 +49,10 @@ impl NONDriverHelper { } } + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id + } + pub async fn get_object( &self, object_id: &ObjectId, @@ -74,12 +78,17 @@ impl NONDriverHelper { self.driver.put_object(&self.dec_id, obj).await } - pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object( + &self, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { self.driver.post_object(&self.dec_id, obj, to).await } pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { - futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), Some(to)))) + .await; } pub async fn get_block( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fcb0dd6da..f7f305a83 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -88,8 +88,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()> { + to: Option<&ObjectId>, + ) -> BuckyResult> { self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { @@ -107,12 +107,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { level: NONAPILevel::Router, - target: Some(to.clone()), + target: to.cloned(), flags: 0, }, object: obj, }) .await - .map(|_| ()) + .map(|resp| resp.object) } } From 850e1bdf6e19968ab7a9ee16c207c9f36d85d519 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 14:56:29 +0800 Subject: [PATCH 096/553] Rename `control` into `Service` --- .../cyfs-group/src/dec/group_manager.rs | 80 +++++++++---------- src/component/cyfs-group/src/dec/mod.rs | 4 +- .../{rpath_control.rs => rpath_service.rs} | 8 +- src/tests/group-example/src/main.rs | 20 ++--- 4 files changed, 56 insertions(+), 56 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_control.rs => rpath_service.rs} (96%) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 346e75d02..23202fddf 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,19 +12,19 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, + RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, }; -type ControlByRPath = HashMap; -type ControlByDec = HashMap; -type ControlByGroup = HashMap; +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; type ClientByRPath = HashMap; type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - control_by_group: ControlByGroup, + service_by_group: ServiceByGroup, client_by_group: ClientByGroup, } @@ -58,7 +58,7 @@ impl GroupManager { }; let raw = GroupRPathMgrRaw { - control_by_group: ControlByGroup::default(), + service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), }; @@ -69,14 +69,14 @@ impl GroupManager { Ok(mgr) } - pub async fn find_rpath_control( + pub async fn find_rpath_service( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, is_auto_create: bool, - ) -> BuckyResult { - self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + ) -> BuckyResult { + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -155,7 +155,7 @@ impl GroupManager { } // return - pub async fn enum_rpath_control( + pub async fn enum_rpath_service( &self, group_id: &ObjectId, ) -> BuckyResult> { @@ -182,8 +182,8 @@ impl GroupManager { match msg { HotstuffPackage::Block(block) => { let rpath = block.r_path(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -192,14 +192,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Block(block), remote) .await; } HotstuffPackage::BlockVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -208,14 +208,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; } HotstuffPackage::TimeoutVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -224,14 +224,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; } HotstuffPackage::Timeout(target, tc) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -240,14 +240,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Timeout(tc), remote) .await; } HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -256,14 +256,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; } HotstuffPackage::LastStateRequest(target) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -272,7 +272,7 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::LastStateRequest, remote) .await; } @@ -309,8 +309,8 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -320,9 +320,9 @@ impl GroupManager { ) .await; - match control { - Ok(control) => { - control + match service { + Ok(service) => { + service .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } @@ -356,7 +356,7 @@ impl GroupManager { Ok(()) } - async fn find_rpath_control_inner( + async fn find_rpath_service_inner( &self, group_id: &ObjectId, dec_id: &ObjectId, @@ -364,12 +364,12 @@ impl GroupManager { is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, - ) -> BuckyResult { + ) -> BuckyResult { { // read let raw = self.read().await; let found = raw - .control_by_group + .service_by_group .get(group_id) .map_or(None, |by_dec| by_dec.get(dec_id)) .map_or(None, |by_rpath| by_rpath.get(rpath)); @@ -446,7 +446,7 @@ impl GroupManager { }; let found = raw - .control_by_group + .service_by_group .entry(group_id.clone()) .or_insert_with(HashMap::new) .entry(dec_id.clone()) @@ -456,7 +456,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let control = RPathControl::load( + let service = RPathService::load( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -467,8 +467,8 @@ impl GroupManager { store, ) .await?; - entry.insert(control.clone()); - Ok(control) + entry.insert(service.clone()); + Ok(service) } } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 2ad717514..f881db19c 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod group_events; mod group_manager; mod rpath_client; -mod rpath_control; +mod rpath_service; pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; -pub use rpath_control::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_service.rs similarity index 96% rename from src/component/cyfs-group/src/dec/rpath_control.rs rename to src/component/cyfs-group/src/dec/rpath_service.rs index 593d82db4..b4b90972f 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -9,7 +9,7 @@ use crate::{ PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; -struct RPathControlRaw { +struct RPathServiceRaw { local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, @@ -18,9 +18,9 @@ struct RPathControlRaw { } #[derive(Clone)] -pub struct RPathControl(Arc); +pub struct RPathService(Arc); -impl RPathControl { +impl RPathService { pub(crate) async fn load( local_id: ObjectId, local_device_id: ObjectId, @@ -50,7 +50,7 @@ impl RPathControl { rpath.clone(), ); - let raw = RPathControlRaw { + let raw = RPathServiceRaw { network_sender, pending_proposal_handle, local_id, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 42544e51c..88450ac1b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,7 +505,7 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathControl; + use cyfs_group::RPathService; use cyfs_lib::{ DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, @@ -545,7 +545,7 @@ mod GroupDecService { } // pub struct PostProposalRoutine { - // controller: RPathControl, + // service: RPathService, // } // #[async_trait::async_trait] @@ -558,7 +558,7 @@ mod GroupDecService { // ) -> BuckyResult { // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // self.controller.push_proposal(proposal).await?; + // self.service.push_proposal(proposal).await?; // Ok(NONPostObjectInputResponse { object: None }) // } // } @@ -1037,9 +1037,9 @@ async fn main_run() { ) .await; - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1066,9 +1066,9 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1113,9 +1113,9 @@ async fn main_run() { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1125,7 +1125,7 @@ async fn main_run() { .unwrap(); async_std::task::spawn(async move { - control.push_proposal(proposal).await.unwrap(); + service.push_proposal(proposal).await.unwrap(); }); if i % 10 == 0 { From b471df85a34eb79b52d07e40bfdc0105421009d0 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 15:34:34 +0800 Subject: [PATCH 097/553] Interface in client for DecAPP --- src/component/cyfs-group-lib/src/delegate.rs | 6 +-- .../cyfs-group-lib/src/group_manager.rs | 37 ++++++++++++++++--- src/component/cyfs-group-lib/src/lib.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 23 ++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/rpath_service.rs diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 21b1e6346..645cd0656 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,4 @@ -use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, -}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -11,7 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()>; + ) -> BuckyResult>; } pub struct ExecuteResult { diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 8c82bc9e1..103807446 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,20 +1,47 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::DecAppId; +use cyfs_lib::SharedCyfsStack; -use crate::{DelegateFactory, RPathClient}; +use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; #[derive(Clone)] pub struct GroupManager; impl GroupManager { - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn open( + stack: SharedCyfsStack, + delegate_factory: Box, + ) -> BuckyResult { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn start_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + delegate: Box, + ) -> BuckyResult { + Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + } + + pub async fn find_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client( + &self, + group_id: ObjectId, + dec_id: DecAppId, + rpath: String, + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 199307bcc..34473bf07 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -2,8 +2,10 @@ mod delegate; mod group_manager; mod objects; mod rpath_client; +mod rpath_service; pub use delegate::*; pub use group_manager::*; pub use objects::*; pub use rpath_client::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs new file mode 100644 index 000000000..81225ed72 --- /dev/null +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupProposal, GroupRPath}; + +struct RPathServiceRaw {} + +#[derive(Clone)] +pub struct RPathService(Arc); + +impl RPathService { + pub(crate) async fn load() -> BuckyResult { + unimplemented!() + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + unimplemented!() + } +} From b802959580473e07fb1c3e0d7ff655cb35423a81 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 21:21:44 +0800 Subject: [PATCH 098/553] Interface in client for DecAPP events --- .../cyfs-base/protos/standard_objects.proto | 4 +- src/component/cyfs-base/src/objects/group.rs | 20 +- .../cyfs-core/protos/core_objects.proto | 8 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 18 +- .../cyfs-core/src/group/group_rpath.rs | 14 +- src/component/cyfs-group-lib/Cargo.toml | 3 +- src/component/cyfs-group-lib/src/delegate.rs | 24 +- .../cyfs-group-lib/src/group_manager.rs | 442 +++++++++++++++++- .../cyfs-group-lib/src/rpath_client.rs | 45 +- .../cyfs-group-lib/src/rpath_service.rs | 122 ++++- .../src/consensus/hotstuff/hotstuff.rs | 4 +- .../cyfs-group/src/dec/group_events.rs | 10 +- .../cyfs-group/src/dec/group_manager.rs | 28 +- .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec_state/state_pusher.rs | 4 +- .../cyfs-group/src/network/protocol.rs | 6 +- .../engine/storage_engine_group_state.rs | 8 +- .../cyfs-group/src/storage/group_storage.rs | 6 +- src/component/cyfs-lib/src/stack/stack.rs | 31 +- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- 21 files changed, 701 insertions(+), 122 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index cfb722c62..4a9714958 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -72,7 +72,7 @@ message GroupMethodACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; double min_support_percent = 4; string permissions = 5; // ACL-String @@ -83,7 +83,7 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; string method = 4; double right_percent = 5; diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ed7686157..5c8cda714 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -436,7 +436,7 @@ impl TryFrom<&GroupMember> for protos::GroupMember { pub struct GroupMethodACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub min_support_percent: f64, pub permissions: String, // ACL-String } @@ -452,8 +452,8 @@ impl TryFrom for GroupMethodACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -475,8 +475,8 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.min_support_percent = value.min_support_percent; ret.permissions = value.permissions.clone(); @@ -489,7 +489,7 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { pub struct GroupRoleACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub method: String, pub right_percent: f64, @@ -508,8 +508,8 @@ impl TryFrom for GroupRoleACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -533,8 +533,8 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.method = value.method.clone(); ret.right_percent = value.right_percent; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 742c14904..8048b3951 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -333,12 +333,12 @@ message SyncResponseObjectMetaInfo { message GroupRPath { bytes group_id = 1; bytes dec_id = 2; - string r_path = 3; + string rpath = 3; } message GroupProposalDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; @@ -404,7 +404,7 @@ message HotstuffTimeout { message GroupConsensusBlockDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // input bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) @@ -437,7 +437,7 @@ message GroupConsensusBlockBodyContent { /* message GroupActionDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 35c418552..7d447ad15 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -10,7 +10,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path: GroupRPath, + rpath: GroupRPath, body_hash: HashValue, result_state_id: Option, height: u64, @@ -40,7 +40,7 @@ impl DescContent for GroupConsensusBlockDescContent { impl GroupConsensusBlockDescContent { pub fn rpath(&self) -> &GroupRPath { - &self.r_path + &self.rpath } pub fn result_state_id(&self) -> &Option { @@ -236,7 +236,7 @@ impl GroupConsensusBlockBodyContent { pub trait GroupConsensusBlockObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -248,7 +248,7 @@ pub trait GroupConsensusBlockObject { owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; @@ -266,7 +266,7 @@ pub trait GroupConsensusBlockObject { impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -280,7 +280,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { - r_path, + rpath, result_state_id, height, @@ -319,9 +319,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path(&self) -> &GroupRPath { + fn rpath(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path + &desc.rpath } fn proposals(&self) -> &Vec { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index bf28aafb2..508418f7b 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -6,7 +6,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, @@ -123,7 +123,7 @@ pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, meta_block_id: Option, @@ -131,7 +131,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path, + rpath, method, params, meta_block_id, @@ -158,7 +158,7 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -169,7 +169,7 @@ pub trait GroupProposalObject { effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -207,7 +207,7 @@ pub trait GroupProposalObject { #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -218,7 +218,7 @@ impl GroupProposalObject for GroupProposal { effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path, + rpath, method, params, meta_block_id, @@ -237,8 +237,8 @@ impl GroupProposalObject for GroupProposal { .owner(owner) } - fn r_path(&self) -> &GroupRPath { - &self.desc().content().r_path + fn rpath(&self) -> &GroupRPath { + &self.desc().content().rpath } fn method(&self) -> &str { diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 3b86fbc57..f177015bf 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,25 +1,25 @@ use cyfs_base::*; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq, Hash)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, - r_path: String, + rpath: String, } impl std::fmt::Debug for GroupRPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.rpath) } } impl GroupRPath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { Self { group_id, dec_id, - r_path, + rpath, } } @@ -31,7 +31,7 @@ impl GroupRPath { &self.dec_id } - pub fn r_path(&self) -> &str { - self.r_path.as_str() + pub fn rpath(&self) -> &str { + self.rpath.as_str() } } diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index e7cfda851..bad3d3112 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -31,4 +31,5 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 645cd0656..3cc99902b 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,6 @@ -use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SingleOpEnvStub}; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { @@ -23,30 +23,36 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult<()>; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ); } #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { - async fn create_single_op_env(&self) -> BuckyResult; - async fn create_sub_tree_op_env(&self) -> BuckyResult; + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult; + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 103807446..f93be45f0 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,37 +1,132 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::DecAppId; -use cyfs_lib::SharedCyfsStack; +use std::{collections::HashMap, sync::Arc}; -use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RawDecode, +}; +use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, + SharedCyfsStack, +}; +use cyfs_util::EventListenerAsyncRoutine; + +use crate::{ + DelegateFactory, ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandNewRPath, GroupCommandObject, GroupCommandType, + GroupCommandVerify, RPathClient, RPathDelegate, RPathService, +}; + +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupManagerRaw { + stack: SharedCyfsStack, + requestor: HttpRequestorRef, + delegate_factory: Option>, + clients: RwLock, + services: RwLock, + local_zone: Option, +} #[derive(Clone)] -pub struct GroupManager; +pub struct GroupManager(Arc); impl GroupManager { pub async fn open( stack: SharedCyfsStack, delegate_factory: Box, + requestor_type: &CyfsStackRequestorType, ) -> BuckyResult { - unimplemented!() + if stack.dec_id().is_none() { + let msg = "the stack should be opened with dec-id"; + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let dec_id = stack.dec_id().unwrap().clone(); + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + let router_handler_manager = stack.router_handlers().clone(); + + let mgr = Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: Some(delegate_factory), + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + })); + + // TODO: other filters? only local zone + let filter = format!( + "obj_type == {} && dec_id == {}", + CoreObjectType::GroupCommand as u16, + dec_id, + ); + + router_handler_manager + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-cmd-{}", dec_id).as_str(), + 0, + Some(filter), + None, + RouterHandlerAction::Pass, + Some(Box::new(mgr.clone())), + ) + .await?; + + Ok(mgr) } - pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { + pub async fn open_as_client( + stack: SharedCyfsStack, + requestor_type: &CyfsStackRequestorType, + ) -> BuckyResult { + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + + Ok(Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: None, + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + }))) + } + + pub async fn stop(&self) { unimplemented!() } + pub fn stack(&self) -> &SharedCyfsStack { + &self.0.stack + } + pub async fn start_rpath_service( &self, group_id: ObjectId, rpath: String, delegate: Box, ) -> BuckyResult { - Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + unimplemented!() } pub async fn find_rpath_service( &self, - group_id: ObjectId, - rpath: String, + group_id: &ObjectId, + rpath: &str, ) -> BuckyResult { unimplemented!() } @@ -40,8 +135,329 @@ impl GroupManager { &self, group_id: ObjectId, dec_id: DecAppId, - rpath: String, - ) -> BuckyResult { - unimplemented!() + rpath: &str, + ) -> RPathClient { + { + let clients = self.0.clients.read().await; + let found = clients + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id.object_id())) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return found.clone(); + } + } + + { + let client = RPathClient::new( + GroupRPath::new(group_id, dec_id.object_id().clone(), rpath.to_string()), + self.0.stack.dec_id().cloned(), + self.0.stack.non_service().clone(), + ); + + let mut clients = self.0.clients.write().await; + let client = clients + .entry(group_id) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert(client); + client.clone() + } + } + + async fn on_command( + &self, + cmd: GroupCommand, + ) -> BuckyResult> { + match cmd.into_cmd() { + crate::GroupCommandBodyContent::NewRPath(cmd) => { + self.on_new_rpath(cmd).await.map(|_| None) + } + crate::GroupCommandBodyContent::Execute(cmd) => { + self.on_execute(cmd).await.map(|r| Some(r)) + } + crate::GroupCommandBodyContent::ExecuteResult(_) => { + let msg = format!( + "should not get the cmd({:?}) in sdk", + GroupCommandType::ExecuteResult + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)) + } + crate::GroupCommandBodyContent::Verify(cmd) => self.on_verify(cmd).await.map(|_| None), + crate::GroupCommandBodyContent::Commited(cmd) => { + self.on_commited(cmd).await.map(|_| None) + } + } + } + + async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let group_id = &cmd.group_id; + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.rpath.as_str(); + + { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if found.is_some() { + return Ok(()); + } + } + + let delegate = factory + .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) + .await?; + + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(()); + } + }; + + new_service.start().await; + Ok(()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } + } + + async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try execute proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try execute proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let mut result = service + .on_execute(&cmd.proposal, &cmd.prev_state_id) + .await?; + + Ok(GroupCommandExecuteResult { + result_state_id: result.result_state_id.take(), + receipt: result.receipt.take(), + context: result.context.take(), + }) + } + + async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try verify proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try verify proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) + .await + } + + async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try commited proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try commited proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } +} + +#[async_trait::async_trait] +impl EventListenerAsyncRoutine + for GroupManager +{ + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + let req_common = ¶m.request.common; + if req_common.level != NONAPILevel::NOC + || req_common.source.zone.zone != self.0.local_zone + || self.0.local_zone.is_none() + || self.0.stack.dec_id().is_none() + { + log::warn!( + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id() + ); + + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let obj = ¶m.request.object; + match obj.object.as_ref() { + None => { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }) + } + Some(any_obj) => { + assert_eq!(any_obj.obj_type(), CoreObjectType::GroupCommand as u16); + if any_obj.obj_type() != CoreObjectType::GroupCommand as u16 { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let (cmd, remain) = GroupCommand::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + let resp_obj = self.on_command(cmd).await; + + let resp_cmd = resp_obj.map_or_else( + |err| Err(err), + |resp_obj| { + resp_obj.map_or(Ok(None), |resp_cmd| { + let resp_cmd = GroupCommand::from(resp_cmd); + resp_cmd.to_vec().map(|buf| { + Some(NONObjectInfo::new(resp_cmd.desc().object_id(), buf, None)) + }) + }) + }, + ); + + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: Some(resp_cmd.map(|cmd| NONPostObjectInputResponse { object: cmd })), + }) + } + } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 2fea6dcf7..ea032715b 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -1,26 +1,55 @@ use std::sync::Arc; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, - RawConvertTo, +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, }; -use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::NONObjectInfo; -struct RPathClientRaw {} +struct RPathClientRaw { + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, +} #[derive(Clone)] pub struct RPathClient(Arc); impl RPathClient { + pub(crate) fn new( + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, + ) -> Self { + Self(Arc::new(RPathClientRaw { + requestor, + rpath, + local_dec_id, + })) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + self.0 + .requestor + .post_object(NONPostObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: self.0.local_dec_id.clone(), + level: NONAPILevel::Router, + target: Some(proposal.rpath().group_id().clone()), + flags: 0, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), proposal.to_vec()?, None), + }) + .await + .map(|resp| resp.object) } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 81225ed72..cebe445dd 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,23 +1,133 @@ use std::sync::Arc; -use cyfs_base::BuckyResult; -use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, +}; -struct RPathServiceRaw {} +use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + +struct RPathServiceRaw { + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, +} #[derive(Clone)] pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load() -> BuckyResult { + pub fn rpath(&self) -> &GroupRPath { unimplemented!() } - pub fn rpath(&self) -> &GroupRPath { + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + // post http unimplemented!() } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub(crate) fn new( + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, + ) -> Self { + Self(Arc::new(RPathServiceRaw { + rpath, + requestor, + delegate, + stack, + })) + } + + pub(crate) async fn start(&self) -> BuckyResult { + // post create command unimplemented!() } + + pub(crate) async fn on_execute( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + ) -> BuckyResult { + self.0 + .delegate + .on_execute( + proposal, + prev_state_id, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_verify( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + self.0 + .delegate + .on_verify( + proposal, + prev_state_id, + execute_result, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_commited( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + self.0 + .delegate + .on_commited( + proposal, + prev_state_id, + execute_result, + block, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } +} + +struct GroupObjectMapProcessorImpl { + stack: SharedCyfsStack, +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorImpl { + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_single_op_env_with_access(access) + .await + } + + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_isolate_path_op_env_with_access(access) + .await + } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index eaaaed06e..d2dbcc517 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,7 +11,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; @@ -20,7 +20,7 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, }; /** diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index fc3d12c63..9bda7e340 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,6 @@ use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -130,3 +130,9 @@ impl RPathEventNotifier { assert!(result.is_err() || result.unwrap().is_none()); } } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 23202fddf..7a9708ccc 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -181,12 +181,12 @@ impl GroupManager { ) -> BuckyResult<()> { match msg { HotstuffPackage::Block(block) => { - let rpath = block.r_path(); + let rpath = block.rpath(); let service = self .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, Some(&block), Some(&remote), @@ -202,7 +202,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -218,7 +218,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -234,7 +234,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -250,7 +250,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -266,7 +266,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -278,9 +278,9 @@ impl GroupManager { } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { // TODO: unimplemented - // let rpath = header_block.r_path(); + // let rpath = header_block.rpath(); // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) // .await?; // client // .on_message( @@ -292,10 +292,10 @@ impl GroupManager { HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( @@ -313,7 +313,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -328,7 +328,7 @@ impl GroupManager { } _ => { let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) @@ -342,7 +342,7 @@ impl GroupManager { |status| status.block_desc.content().rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 41db0c25c..43fb8e559 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -78,13 +78,13 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.0.rpath); + assert_eq!(proposal.rpath(), &self.0.rpath); // TODO: signature let group = self .0 .non_driver - .get_group(proposal.r_path().group_id(), None, None) + .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 571c1ca13..99c3fed62 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -222,7 +222,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) @@ -248,7 +248,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 7e32fdc4d..1f2a46a73 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -321,16 +321,16 @@ impl std::fmt::Debug for HotstuffPackage { impl HotstuffPackage { pub(crate) fn rpath(&self) -> &GroupRPath { match self { - HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::Block(block) => block.rpath(), HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), - HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::StateChangeNotify(block, _) => block.rpath(), HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( |(_, addr)| addr.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 63158a865..029b09e78 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,12 +5,12 @@ use cyfs_base::{ ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_group_lib::GroupObjectMapProcessor; +use cyfs_core::GroupConsensusBlockObject; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a1a681259..3a762c1b6 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,12 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, - STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 5b21e5d2d..5de037faa 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -3,6 +3,7 @@ use crate::crypto::*; use crate::events::*; use crate::ndn::*; use crate::non::*; +use crate::requestor::*; use crate::rmeta::*; use crate::root_state::*; use crate::router_handler::*; @@ -10,7 +11,6 @@ use crate::storage::StateStorage; use crate::sync::*; use crate::trans::*; use crate::util::*; -use crate::requestor::*; use cyfs_base::*; use http_types::Url; @@ -94,7 +94,7 @@ pub struct SharedCyfsStack { // uni_stack uni_stack: Arc>, - requestor_holder: RequestorHolder, + requestor_holder: Arc>, } #[derive(Debug, Clone)] @@ -110,8 +110,7 @@ pub enum CyfsStackRequestorType { #[derive(Debug, Clone)] pub struct CyfsStackRequestorConfig { - - // default is None, use the traditional http-tcp requestor without connection pool; + // default is None, use the traditional http-tcp requestor without connection pool; // use Some(0) will use the default connection pool size 50 pub http_max_connections_per_host: Option, @@ -291,8 +290,13 @@ impl RequestorHolder { param.service_url.port().unwrap() ); - if let Some(http_max_connections_per_host) = self.requestor_config.http_max_connections_per_host { - Arc::new(Box::new(SurfHttpRequestor::new(&addr, http_max_connections_per_host))) + if let Some(http_max_connections_per_host) = + self.requestor_config.http_max_connections_per_host + { + Arc::new(Box::new(SurfHttpRequestor::new( + &addr, + http_max_connections_per_host, + ))) } else { Arc::new(Box::new(TcpHttpRequestor::new(&addr))) } @@ -378,7 +382,8 @@ impl SharedCyfsStack { // ndn let requestor = requestor_holder.select_requestor(¶m, ¶m.requestor_config.ndn_service); - let data_requestor = requestor_holder.select_requestor(¶m, &CyfsStackRequestorType::Http); + let data_requestor = + requestor_holder.select_requestor(¶m, &CyfsStackRequestorType::Http); let ndn_service = NDNRequestor::new(Some(dec_id.clone()), requestor, Some(data_requestor)); // sync @@ -471,20 +476,21 @@ impl SharedCyfsStack { device_info: Arc::new(RwLock::new(None)), uni_stack: Arc::new(OnceCell::new()), - requestor_holder, + requestor_holder: Arc::new(RwLock::new(requestor_holder)), }; Ok(ret) } pub async fn stop(&self) { - self.requestor_holder.stop().await; + let requestor_holder = self.requestor_holder.read().unwrap(); + requestor_holder.stop().await; self.router_handlers.stop().await; self.router_events.stop().await; } - + pub fn param(&self) -> &SharedCyfsStackParam { &self.param } @@ -722,6 +728,11 @@ impl SharedCyfsStack { pub fn uni_stack(&self) -> &UniCyfsStackRef { self.uni_stack.get_or_init(|| self.create_uni_stack()) } + + pub fn select_requestor(&self, requestor_type: &CyfsStackRequestorType) -> HttpRequestorRef { + let mut requestor_holder = self.requestor_holder.write().unwrap(); + requestor_holder.select_requestor(&self.param, requestor_type) + } } impl UniCyfsStack for SharedCyfsStack { diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index f7f305a83..431915a96 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: None, flags: 0, @@ -105,7 +105,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, From ccf343dce2b5dacd1b2eec515e9f1c6a321995c3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 16:49:16 +0800 Subject: [PATCH 099/553] Interface for client --- src/component/cyfs-group-lib/Cargo.toml | 1 + src/component/cyfs-group-lib/src/delegate.rs | 1 + .../cyfs-group-lib/src/group_manager.rs | 255 ++++++++---------- .../cyfs-group-lib/src/input_request.rs | 0 src/component/cyfs-group-lib/src/lib.rs | 12 + .../cyfs-group-lib/src/output_request.rs | 7 + src/component/cyfs-group-lib/src/processor.rs | 6 + src/component/cyfs-group-lib/src/request.rs | 0 .../cyfs-group-lib/src/request_codec.rs | 21 ++ src/component/cyfs-group-lib/src/requestor.rs | 210 +++++++++++++++ .../cyfs-group-lib/src/rpath_client.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 14 +- .../cyfs-lib/src/non/output_request.rs | 20 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- 14 files changed, 391 insertions(+), 162 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/input_request.rs create mode 100644 src/component/cyfs-group-lib/src/output_request.rs create mode 100644 src/component/cyfs-group-lib/src/processor.rs create mode 100644 src/component/cyfs-group-lib/src/request.rs create mode 100644 src/component/cyfs-group-lib/src/request_codec.rs create mode 100644 src/component/cyfs-group-lib/src/requestor.rs diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index bad3d3112..740b303cd 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' itertools = "0.10.3" +http-types = '2.12' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 3cc99902b..d678438c3 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -9,6 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult>; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f93be45f0..f442d5c55 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,7 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, @@ -195,98 +195,28 @@ impl GroupManager { } async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { - match self.0.delegate_factory.as_ref() { - Some(factory) => { - let group_id = &cmd.group_id; - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.rpath.as_str(); - - { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - if found.is_some() { - return Ok(()); - } - } - - let delegate = factory - .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) - .await?; - - let new_service = { - let mut is_new = false; - - let mut services = self.0.services.write().await; - let service = services - .entry(group_id.clone()) - .or_insert_with(HashMap::new) - .entry(dec_id.clone()) - .or_insert_with(HashMap::new) - .entry(rpath.to_string()) - .or_insert_with(|| { - is_new = true; - - RPathService::new( - GroupRPath::new( - group_id.clone(), - dec_id.clone(), - rpath.to_string(), - ), - self.0.requestor.clone(), - delegate, - self.0.stack.clone(), - ) - }); - - if is_new { - service.clone() - } else { - return Ok(()); - } - }; - - new_service.start().await; - Ok(()) - } - None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), - } + self.find_or_restart_service( + &cmd.group_id, + self.0.stack.dec_id().unwrap(), + cmd.rpath.as_str(), + &cmd.with_block, + true, + ) + .await + .map(|_| ()) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try execute proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try execute proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) @@ -300,36 +230,16 @@ impl GroupManager { } async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try verify proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try verify proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -343,47 +253,102 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; - if cmd.proposal.rpath().dec_id() != dec_id { + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } + + async fn find_or_restart_service( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: &Option, + is_new: bool, + ) -> BuckyResult { + if dec_id != self.0.stack.dec_id().unwrap() { let msg = format!( - "try commited proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id + "try find proposal in different dec {:?}, expected: {:?}", + dec_id, + self.0.stack.dec_id().unwrap() ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - let service = { + { let services = self.0.services.read().await; let found = services .get(group_id) .and_then(|by_dec| by_dec.get(dec_id)) .and_then(|by_rpath| by_rpath.get(rpath)); - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try commited proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } + if let Some(found) = found { + return Ok(found.clone()); } - }; + } - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let delegate = factory + .create_rpath_delegate(group_id, rpath, with_block.as_ref(), is_new) + .await?; - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; - Ok(()) + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(service.clone()); + } + }; + + new_service.start().await; + Ok(new_service.clone()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } } } diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 34473bf07..519a64040 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,11 +1,23 @@ mod delegate; mod group_manager; +mod input_request; mod objects; +mod output_request; +mod processor; +mod request; +mod request_codec; +mod requestor; mod rpath_client; mod rpath_service; pub use delegate::*; pub use group_manager::*; +pub use input_request::*; pub use objects::*; +pub use output_request::*; +pub use processor::*; +pub(crate) use request::*; +pub use request_codec::*; +pub use requestor::*; pub use rpath_client::*; pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs new file mode 100644 index 000000000..c847668df --- /dev/null +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -0,0 +1,7 @@ +use cyfs_base::ObjectId; + +#[derive(Debug)] +pub struct GroupStartServiceOutputRequest { + pub group_id: ObjectId, + pub rpath: String, +} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs new file mode 100644 index 000000000..925061f3e --- /dev/null +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +#[async_trait::async_trait] +pub trait GroupOutputProcessor: Send + Sync {} + +pub type GroupOutputProcessorRef = Arc; diff --git a/src/component/cyfs-group-lib/src/request.rs b/src/component/cyfs-group-lib/src/request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs new file mode 100644 index 000000000..c4f330efc --- /dev/null +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -0,0 +1,21 @@ +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use serde_json::{Map, Value}; + +use crate::output_request::GroupStartServiceOutputRequest; + +impl JsonCodec for GroupStartServiceOutputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs new file mode 100644 index 000000000..437a01184 --- /dev/null +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + CYFS_API_LEVEL, +}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, +}; +use http_types::{Method, Request, Url}; + +use crate::{ + output_request::GroupStartServiceOutputRequest, + processor::{GroupOutputProcessor, GroupOutputProcessorRef}, +}; + +#[derive(Clone)] +pub struct GroupRequestor { + dec_id: ObjectId, + requestor: HttpRequestorRef, + service_url: Url, +} + +impl GroupRequestor { + pub fn new(dec_id: ObjectId, requestor: HttpRequestorRef) -> Self { + let addr = requestor.remote_addr(); + + let url = format!("http://{}/group/", addr); + let url = Url::parse(&url).unwrap(); + + Self { + dec_id, + requestor, + service_url: url, + } + } + + pub fn clone_processor(&self) -> GroupOutputProcessorRef { + Arc::new(self.clone()) + } + + fn encode_common_headers( + &self, + // action: NONAction, + com_req: &NONOutputRequestCommon, + http_req: &mut Request, + ) { + let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); + http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); + + RequestorHelper::encode_opt_header_with_encoding( + http_req, + cyfs_base::CYFS_REQ_PATH, + com_req.req_path.as_deref(), + ); + + // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + + http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); + + if let Some(target) = &com_req.target { + http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); + } + + if let Some(source) = &com_req.source { + http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); + } + + http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); + } + + fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(dec_id), + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, + } + } + + pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + log::info!("will start group service: {:?}", rpath); + + let url = self.service_url.join("start-service").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + let req = GroupStartServiceOutputRequest { + group_id: rpath.group_id().clone(), + rpath: rpath.rpath().to_string(), + }; + + self.encode_common_headers( + &Self::make_default_common(rpath.dec_id().clone()), + &mut http_req, + ); + let body = req.encode_string(); + http_req.set_body(body); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group start service failed, read body string error! req={:?} {}", + req, e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!("group start service success"); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group start service failed: rpath={:?}, status={}, {}", + rpath, + code, + e + ); + Err(e) + } + } + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + let proposal_id = proposal.desc().object_id(); + log::info!( + "will push proposal: {:?}, {}", + proposal.rpath(), + proposal_id + ); + + let url = self.service_url.join("push-proposal").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + self.encode_common_headers( + &Self::make_default_common(proposal.rpath().dec_id().clone()), + &mut http_req, + ); + + NONRequestorHelper::encode_object_info( + &mut http_req, + NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + ); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group push proposal failed, read body string error! req={:?}/{} {}", + proposal.rpath(), + proposal_id, + e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!( + "group push proposal success, req={:?}/{}", + proposal.rpath(), + proposal_id + ); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group push proposal failed: rpath={:?}/{}, status={}, {}", + proposal.rpath(), + proposal_id, + code, + e + ); + Err(e) + } + } + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupRequestor {} diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index ea032715b..7d7c9a613 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -32,6 +32,8 @@ impl RPathClient { &self.0.rpath } + // post proposal to the admins, it's same as calling to non.post_object with default parameters; + // and you can call the non.post_object with more parameters. pub async fn post_proposal( &self, proposal: &GroupProposal, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index cebe445dd..95811e339 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -6,11 +6,11 @@ use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; +use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; struct RPathServiceRaw { rpath: GroupRPath, - requestor: HttpRequestorRef, + requestor: GroupRequestor, delegate: Box, stack: SharedCyfsStack, } @@ -20,12 +20,12 @@ pub struct RPathService(Arc); impl RPathService { pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - unimplemented!() + self.0.requestor.push_proposal(proposal).await } pub(crate) fn new( @@ -35,16 +35,16 @@ impl RPathService { stack: SharedCyfsStack, ) -> Self { Self(Arc::new(RPathServiceRaw { + requestor: GroupRequestor::new(rpath.dec_id().clone(), requestor), rpath, - requestor, delegate, stack, })) } - pub(crate) async fn start(&self) -> BuckyResult { + pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - unimplemented!() + self.0.requestor.start_group_service(self.rpath()).await } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-lib/src/non/output_request.rs b/src/component/cyfs-lib/src/non/output_request.rs index d4950ce33..b6e96dcb3 100644 --- a/src/component/cyfs-lib/src/non/output_request.rs +++ b/src/component/cyfs-lib/src/non/output_request.rs @@ -4,7 +4,7 @@ use cyfs_base::*; use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NONOutputRequestCommon { // 请求路径,可为空 pub req_path: Option, @@ -130,14 +130,22 @@ impl NONUpdateObjectMetaOutputRequest { Self::new(NONAPILevel::NOC, object_id, access) } - pub fn new_non(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_non( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::NON, object_id, access); ret.common.target = target.map(|v| v.into()); ret } - pub fn new_router(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_router( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::Router, object_id, access); ret.common.target = target; @@ -243,7 +251,6 @@ impl NONGetObjectOutputRequest { } } - impl fmt::Display for NONGetObjectOutputRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "common: {}", self.common)?; @@ -338,7 +345,6 @@ impl fmt::Display for NONPostObjectOutputResponse { } } - // select #[derive(Clone)] pub struct NONSelectObjectOutputRequest { @@ -392,7 +398,6 @@ impl fmt::Display for NONSelectObjectOutputRequest { } } - #[derive(Clone)] pub struct NONSelectObjectOutputResponse { pub objects: Vec, @@ -470,7 +475,6 @@ impl fmt::Display for NONDeleteObjectOutputRequest { } } - #[derive(Clone)] pub struct NONDeleteObjectOutputResponse { pub object: Option, @@ -479,7 +483,7 @@ pub struct NONDeleteObjectOutputResponse { impl fmt::Display for NONDeleteObjectOutputResponse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "object: {:?}", self.object)?; - + Ok(()) } } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 431915a96..9333e7981 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::NOC, target: None, flags: 0, From b99859c7ba3cfbb481c47f49b1996dd9ecc8dff4 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 21:35:56 +0800 Subject: [PATCH 100/553] Export to SDK --- .../cyfs-group-lib/src/input_request.rs | 10 + .../cyfs-group-lib/src/output_request.rs | 4 + src/component/cyfs-group-lib/src/processor.rs | 24 ++- .../cyfs-group-lib/src/request_codec.rs | 19 +- src/component/cyfs-group-lib/src/requestor.rs | 54 +++-- .../cyfs-group-lib/src/rpath_service.rs | 21 +- src/component/cyfs-stack/Cargo.toml | 1 + src/component/cyfs-stack/src/group/mod.rs | 5 + .../cyfs-stack/src/group/processor.rs | 25 +++ .../cyfs-stack/src/group/transform.rs | 190 ++++++++++++++++++ .../cyfs-stack/src/group_api/acl/group_acl.rs | 61 ++++++ .../cyfs-stack/src/group_api/acl/mod.rs | 3 + src/component/cyfs-stack/src/group_api/mod.rs | 7 + .../group_api/router/group_service_router.rs | 133 ++++++++++++ .../src/group_api/router/local_service.rs | 113 +++++++++++ .../cyfs-stack/src/group_api/router/mod.rs | 5 + .../src/group_api/service/group_handler.rs | 125 ++++++++++++ .../src/group_api/service/group_listener.rs | 77 +++++++ .../src/group_api/service/group_service.rs | 35 ++++ .../cyfs-stack/src/group_api/service/mod.rs | 7 + .../cyfs-stack/src/interface/http_listener.rs | 11 + .../src/interface/listener_manager.rs | 14 +- src/component/cyfs-stack/src/lib.rs | 2 + .../cyfs-stack/src/stack/cyfs_stack.rs | 12 +- 24 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/component/cyfs-stack/src/group/mod.rs create mode 100644 src/component/cyfs-stack/src/group/processor.rs create mode 100644 src/component/cyfs-stack/src/group/transform.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/group_acl.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/group_service_router.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/local_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_handler.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_listener.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/mod.rs diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index e69de29bb..0f861ea3c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -0,0 +1,10 @@ +use cyfs_base::ObjectId; + +pub struct GroupStartServiceInputRequest { + pub group_id: ObjectId, + pub rpath: String, +} + +pub struct GroupStartServiceInputResponse {} + +pub struct GroupPushProposalInputResponse {} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index c847668df..f65e02e3e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -5,3 +5,7 @@ pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, pub rpath: String, } + +pub struct GroupStartServiceOutputResponse {} + +pub struct GroupPushProposalOutputResponse {} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 925061f3e..9aec5a354 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -1,6 +1,26 @@ use std::sync::Arc; +use cyfs_base::BuckyResult; +use cyfs_core::GroupProposal; +use cyfs_lib::NONOutputRequestCommon; + +use crate::{ + GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, +}; + #[async_trait::async_trait] -pub trait GroupOutputProcessor: Send + Sync {} +pub trait GroupOutputProcessor: Send + Sync { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult; + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} -pub type GroupOutputProcessorRef = Arc; +pub type GroupOutputProcessorRef = Arc>; diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index c4f330efc..58404d6b0 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::output_request::GroupStartServiceOutputRequest; +use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { @@ -19,3 +19,20 @@ impl JsonCodec for GroupStartServiceOutputReques }) } } + +impl JsonCodec for GroupStartServiceInputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 437a01184..462b1df85 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -13,6 +13,7 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, + GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -37,7 +38,7 @@ impl GroupRequestor { } pub fn clone_processor(&self) -> GroupOutputProcessorRef { - Arc::new(self.clone()) + Arc::new(Box::new(self.clone())) } fn encode_common_headers( @@ -70,7 +71,7 @@ impl GroupRequestor { http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { NONOutputRequestCommon { req_path: None, source: None, @@ -81,21 +82,23 @@ impl GroupRequestor { } } - pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + pub async fn start_service( + &self, + req_common: NONOutputRequestCommon, + group_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); let url = self.service_url.join("start-service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { - group_id: rpath.group_id().clone(), - rpath: rpath.rpath().to_string(), + group_id: group_id.clone(), + rpath: rpath.to_string(), }; - self.encode_common_headers( - &Self::make_default_common(rpath.dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -123,7 +126,7 @@ impl GroupRequestor { log::debug!("group start service success"); - Ok(()) + Ok(GroupStartServiceOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -138,7 +141,11 @@ impl GroupRequestor { } } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + proposal: &GroupProposal, + ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", @@ -149,10 +156,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers( - &Self::make_default_common(proposal.rpath().dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, @@ -189,7 +193,7 @@ impl GroupRequestor { proposal_id ); - Ok(()) + Ok(GroupPushProposalOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -207,4 +211,20 @@ impl GroupRequestor { } #[async_trait::async_trait] -impl GroupOutputProcessor for GroupRequestor {} +impl GroupOutputProcessor for GroupRequestor { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupRequestor::push_proposal(self, req_common, &req).await + } +} diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 95811e339..66d0d83f4 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; @@ -25,7 +25,14 @@ impl RPathService { pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - self.0.requestor.push_proposal(proposal).await + self.0 + .requestor + .push_proposal( + GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal, + ) + .await + .map(|_| {}) } pub(crate) fn new( @@ -44,7 +51,15 @@ impl RPathService { pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - self.0.requestor.start_group_service(self.rpath()).await + self.0 + .requestor + .start_service( + GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + self.rpath().group_id(), + self.rpath().rpath(), + ) + .await + .map(|_| {}) } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index d1815a2be..faaaf23ec 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -16,6 +16,7 @@ cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-group = { path = "../../component/cyfs-group" } +cyfs-group-lib = { path = "../../component/cyfs-group-lib" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } diff --git a/src/component/cyfs-stack/src/group/mod.rs b/src/component/cyfs-stack/src/group/mod.rs new file mode 100644 index 000000000..da7603e40 --- /dev/null +++ b/src/component/cyfs-stack/src/group/mod.rs @@ -0,0 +1,5 @@ +mod processor; +mod transform; + +pub(crate) use processor::*; +pub(crate) use transform::*; \ No newline at end of file diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs new file mode 100644 index 000000000..b6fe1544b --- /dev/null +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -0,0 +1,25 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +#[async_trait::async_trait] +pub(crate) trait GroupInputProcessor: Sync + Send { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult; + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} + +pub(crate) type GroupInputProcessorRef = Arc; diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs new file mode 100644 index 000000000..50abe1afb --- /dev/null +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -0,0 +1,190 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, + GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +use super::{GroupInputProcessor, GroupInputProcessorRef}; + +// 实现从input到output的转换 +pub(crate) struct GroupInputTransformer { + processor: GroupOutputProcessorRef, +} + +impl GroupInputTransformer { + pub fn new(processor: GroupOutputProcessorRef) -> GroupInputProcessorRef { + let ret = Self { processor }; + Arc::new(ret) + } + + fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { + NONOutputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 来源DEC + dec_id: common.source.get_opt_dec().cloned(), + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source: common.source.zone.device, + } + } + + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let out_req = GroupStartServiceOutputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let out_resp = self + .processor + .start_service(Self::convert_common(req_common), out_req) + .await?; + + let resp = GroupStartServiceInputResponse {}; + + Ok(resp) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let out_resp = self + .processor + .push_proposal(Self::convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalInputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupInputTransformer { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + GroupInputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupInputTransformer::push_proposal(self, req_common, req).await + } +} + +// 实现从output到input的转换 +pub(crate) struct GroupOutputTransformer { + processor: GroupInputProcessorRef, + source: RequestSourceInfo, +} + +impl GroupOutputTransformer { + fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + let mut source = self.source.clone(); + if let Some(dec_id) = common.dec_id { + source.set_dec(dec_id); + } + + NONInputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source, + } + } + + pub fn new( + processor: GroupInputProcessorRef, + source: RequestSourceInfo, + ) -> GroupOutputProcessorRef { + let ret = Self { processor, source }; + Arc::new(Box::new(ret)) + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let in_resp = self + .processor + .push_proposal(self.convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalOutputResponse {}; + + Ok(resp) + } + + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + let in_req = GroupStartServiceInputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let in_resp = self + .processor + .start_service(self.convert_common(req_common), in_req) + .await?; + + let resp = GroupStartServiceOutputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupOutputTransformer { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupOutputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupOutputTransformer::push_proposal(self, req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs new file mode 100644 index 000000000..0e789c023 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -0,0 +1,61 @@ +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +pub struct GroupAclInnerInputProcessor { + next: GroupInputProcessorRef, +} + +impl GroupAclInnerInputProcessor { + pub(crate) fn new(next: GroupInputProcessorRef) -> GroupInputProcessorRef { + Arc::new(Self { next }) + } + + fn check_local_zone_permit( + &self, + service: &str, + source: &RequestSourceInfo, + ) -> BuckyResult<()> { + // TODO + // if !source.is_current_zone() { + // let msg = format!( + // "{} service valid only in current zone! source={:?}, category={}", + // service, + // source.zone.device, + // source.zone.zone_category.as_str() + // ); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, msg)); + // } + + Ok(()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupAclInnerInputProcessor { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.next.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.next.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/mod.rs b/src/component/cyfs-stack/src/group_api/acl/mod.rs new file mode 100644 index 000000000..53dad00b3 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/mod.rs @@ -0,0 +1,3 @@ +mod group_acl; + +pub use group_acl::*; diff --git a/src/component/cyfs-stack/src/group_api/mod.rs b/src/component/cyfs-stack/src/group_api/mod.rs new file mode 100644 index 000000000..29e257330 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/mod.rs @@ -0,0 +1,7 @@ +mod acl; +mod router; +mod service; + +pub(crate) use acl::*; +pub(crate) use router::*; +pub(crate) use service::*; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs new file mode 100644 index 000000000..2c1a2841f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyResult, DeviceId, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::{ + forward::ForwardProcessorManager, + group::{GroupInputProcessor, GroupInputProcessorRef, GroupInputTransformer}, + group_api::GroupAclInnerInputProcessor, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupServiceRouter { + processor: GroupInputProcessorRef, + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, +} + +impl GroupServiceRouter { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + processor: GroupInputProcessorRef, + ) -> GroupInputProcessorRef { + let processor = GroupAclInnerInputProcessor::new(processor); + let ret = Self { + processor, + zone_manager, + forward, + }; + Arc::new(ret) + } + + async fn get_forward( + &self, + dec_id: ObjectId, + target: DeviceId, + ) -> BuckyResult { + let requestor = self.forward.get(&target).await?; + let group_requestor = GroupRequestor::new(dec_id, requestor); + Ok(GroupInputTransformer::new( + group_requestor.clone_processor(), + )) + } + + // 不同于non/ndn的router,如果target为空,那么表示本地device + async fn get_target(&self, target: Option<&ObjectId>) -> BuckyResult> { + let ret = match target { + Some(object_id) => { + let info = self + .zone_manager + .target_zone_manager() + .resolve_target(Some(object_id)) + .await?; + if info.target_device == *self.zone_manager.get_current_device_id() { + None + } else { + Some(info.target_device) + } + } + None => None, + }; + + Ok(ret) + } + + async fn get_processor( + &self, + dec_id: ObjectId, + target: Option<&ObjectId>, + ) -> BuckyResult { + if let Some(device_id) = self.get_target(target).await? { + debug!("group target resolved: {:?} -> {}", target, device_id); + let processor = self.get_forward(dec_id, device_id).await?; + Ok(processor) + } else { + Ok(self.processor.clone()) + } + } + + pub async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + pub async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupServiceRouter { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs new file mode 100644 index 000000000..e14691b5e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc}; +use cyfs_core::{GroupProposal, GroupProposalObject}; +use cyfs_group::GroupManager; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; + +#[derive(Clone)] +pub(crate) struct LocalGroupService { + group_manager: GroupManager, +} + +impl LocalGroupService { + pub(crate) fn new(group_manager: GroupManager) -> Self { + Self { group_manager } + } + + pub fn clone_processor(&self) -> GroupInputProcessorRef { + Arc::new(self.clone()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for LocalGroupService { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.group_manager + .find_rpath_service( + &req.group_id, + &req_common.source.dec, + req.rpath.as_str(), + true, + ) + .await + .map(|_| GroupStartServiceInputResponse {}) + .map_err(|err| { + log::error!( + "group start service {}-{}-{} failed {:?}", + req.group_id, + req_common.source.dec, + req.rpath, + err + ); + err + }) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let proposal_id = req.desc().object_id(); + let rpath = req.rpath().clone(); + if &req_common.source.dec != rpath.dec_id() { + let msg = format!( + "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + req_common.source.dec + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let service = self + .group_manager + .find_rpath_service( + req.rpath().group_id(), + &req_common.source.dec, + rpath.rpath(), + true, + ) + .await + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed when find the service {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + })?; + + service + .push_proposal(req) + .await + .map(|_| GroupPushProposalInputResponse {}) + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + }) + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/mod.rs b/src/component/cyfs-stack/src/group_api/router/mod.rs new file mode 100644 index 000000000..877b4eff6 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/mod.rs @@ -0,0 +1,5 @@ +mod group_service_router; +mod local_service; + +pub use group_service_router::*; +pub(crate) use local_service::*; diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs new file mode 100644 index 000000000..f01f2eaa5 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -0,0 +1,125 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; + +use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; + +#[derive(Clone)] +pub(crate) struct GroupRequestHandler { + processor: GroupInputProcessorRef, +} + +impl GroupRequestHandler { + pub fn new(processor: GroupInputProcessorRef) -> Self { + Self { processor } + } + + // 解析通用header字段 + fn decode_common_headers( + req: &NONInputHttpRequest, + ) -> BuckyResult { + // req_path + let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( + &req.request, + cyfs_base::CYFS_REQ_PATH, + )?; + + // 尝试提取flags + let flags: Option = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; + + // 尝试提取default_action字段 + let level = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; + + // 尝试提取target字段 + let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; + + let ret = NONInputRequestCommon { + req_path, + source: req.source.clone(), + level: level.unwrap_or_default(), + target, + flags: flags.unwrap_or(0), + }; + + Ok(ret) + } + + // group/start-service + pub async fn process_start_service( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_start_service(req).await { + Ok(_resp) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_start_service( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + let common = Self::decode_common_headers(&req)?; + + // 提取body里面的object对象,如果有的话 + let body = req.request.body_json().await.map_err(|e| { + let msg = format!("group start service failed, read body bytes error! {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidParam, msg) + })?; + + let req = GroupStartServiceInputRequest::decode_json(&body)?; + + self.processor.start_service(common, req).await + } + + pub async fn process_push_proposal( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_push_proposal(req).await { + Ok(_) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_push_proposal( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + // 检查action + // let action = Self::decode_action(&req, NONAction::PutObject)?; + // if action != NONAction::PutObject { + // let msg = format!("invalid non put_object action! {:?}", action); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + // } + + let common = Self::decode_common_headers(&req)?; + let object = NONRequestorHelper::decode_object_info(&mut req.request).await?; + let (proposal, remain) = GroupProposal::raw_decode(object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + // let access: Option = + // RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_ACCESS)?; + // let access = access.map(|v| AccessString::new(v)); + + info!("recv push proposal: {}", object.object_id); + + self.processor.push_proposal(common, proposal).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs new file mode 100644 index 000000000..163228d1f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -0,0 +1,77 @@ +use cyfs_lib::RequestProtocol; +use tide::Response; + +use crate::{non::NONInputHttpRequest, ZoneManagerRef}; + +use super::GroupRequestHandler; + +enum GroupRequestType { + StartService, + PushProposal, +} + +pub(crate) struct GroupRequestHandlerEndpoint { + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, +} + +impl GroupRequestHandlerEndpoint { + fn new( + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, + ) -> Self { + Self { + zone_manager, + protocol, + req_type, + handler, + } + } + + async fn process_request(&self, req: tide::Request) -> Response { + let req = match NONInputHttpRequest::new(&self.zone_manager, &self.protocol, req).await { + Ok(v) => v, + Err(resp) => return resp, + }; + match self.req_type { + GroupRequestType::StartService => self.handler.process_start_service(req).await, + GroupRequestType::PushProposal => self.handler.process_push_proposal(req).await, + } + } + + pub fn register_server( + zone_manager: &ZoneManagerRef, + protocol: &RequestProtocol, + handler: &GroupRequestHandler, + server: &mut tide::Server<()>, + ) { + server.at("/group/start-service").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::StartService, + handler.clone(), + )); + + server.at("group/push-proposal").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::PushProposal, + handler.clone(), + )); + } +} + +#[async_trait::async_trait] +impl tide::Endpoint for GroupRequestHandlerEndpoint +where + State: Clone + Send + Sync + 'static, +{ + async fn call(&self, req: tide::Request) -> tide::Result { + let resp = self.process_request(req).await; + Ok(resp) + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_service.rs b/src/component/cyfs-stack/src/group_api/service/group_service.rs new file mode 100644 index 000000000..3a25e282e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_service.rs @@ -0,0 +1,35 @@ +use cyfs_group::GroupManager; + +use crate::{ + forward::ForwardProcessorManager, + group::GroupInputProcessorRef, + group_api::{GroupServiceRouter, LocalGroupService}, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupService { + router: GroupInputProcessorRef, + local_service: LocalGroupService, +} + +impl GroupService { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + group_manager: GroupManager, + ) -> Self { + let local_service = LocalGroupService::new(group_manager); + let router = + GroupServiceRouter::new(forward, zone_manager, local_service.clone_processor()); + + Self { + router, + local_service, + } + } + + pub(crate) fn clone_processor(&self) -> GroupInputProcessorRef { + self.router.clone() + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/mod.rs b/src/component/cyfs-stack/src/group_api/service/mod.rs new file mode 100644 index 000000000..1140a741d --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/mod.rs @@ -0,0 +1,7 @@ +mod group_service; +mod group_listener; +mod group_handler; + +pub(crate) use group_service::*; +pub(crate) use group_listener::*; +pub(crate) use group_handler::*; diff --git a/src/component/cyfs-stack/src/interface/http_listener.rs b/src/component/cyfs-stack/src/interface/http_listener.rs index 21b6e86e3..e9ef12523 100644 --- a/src/component/cyfs-stack/src/interface/http_listener.rs +++ b/src/component/cyfs-stack/src/interface/http_listener.rs @@ -1,6 +1,7 @@ use crate::acl::AclManagerRef; use crate::crypto_api::*; use crate::front::{FrontProtocolHandler, FrontRequestHandlerEndpoint}; +use crate::group_api::{GroupRequestHandler, GroupRequestHandlerEndpoint, GroupService}; use crate::name::NameResolver; use crate::ndn_api::*; use crate::non_api::*; @@ -75,6 +76,7 @@ impl ObjectHttpListener { global_state_meta: &GlobalStateMetaService, name_resolver: &NameResolver, zone_manager: &ZoneManagerRef, + group_service: &GroupService, ) -> Self { let mut server = new_server(); @@ -225,6 +227,15 @@ impl ObjectHttpListener { &mut server, ); + // group manager + let handler = GroupRequestHandler::new(group_service.clone_processor()); + GroupRequestHandlerEndpoint::register_server( + zone_manager, + &protocol, + &handler, + &mut server, + ); + Self { server } } diff --git a/src/component/cyfs-stack/src/interface/listener_manager.rs b/src/component/cyfs-stack/src/interface/listener_manager.rs index c6b5510be..76d3c4e9d 100644 --- a/src/component/cyfs-stack/src/interface/listener_manager.rs +++ b/src/component/cyfs-stack/src/interface/listener_manager.rs @@ -9,6 +9,7 @@ use crate::acl::AclManagerRef; use crate::app::AuthenticatedAppList; use crate::config::StackGlobalConfig; use crate::events::RouterEventsManager; +use crate::group_api::GroupService; use crate::interface::http_ws_listener::ObjectHttpWSService; use crate::name::NameResolver; use crate::rmeta_api::GlobalStateMetaService; @@ -18,7 +19,7 @@ use crate::stack::ObjectServices; use crate::zone::ZoneRoleManager; use cyfs_base::*; use cyfs_bdt::StackGuard; -use cyfs_lib::{RequestProtocol, BrowserSanboxMode}; +use cyfs_lib::{BrowserSanboxMode, RequestProtocol}; use cyfs_debug::Mutex; use std::net::SocketAddr; @@ -131,6 +132,7 @@ impl ObjectListenerManager { root_state: &GlobalStateService, local_cache: &GlobalStateLocalService, global_state_meta: &GlobalStateMetaService, + group_service: &GroupService, ) { assert!(self.listeners.is_empty()); @@ -151,6 +153,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); @@ -172,18 +175,14 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); let http_server = DefaultHttpServer::new(raw_handler.into(), default_handler.clone()); let http_server = match config.get_stack_params().front.browser_mode { BrowserSanboxMode::None => http_server.into(), - mode @ _ => { - BrowserSanboxHttpServer::new( - http_server.into(), - mode, - ).into() - } + mode @ _ => BrowserSanboxHttpServer::new(http_server.into(), mode).into(), }; self.http_tcp_server = Some(http_server); } @@ -202,6 +201,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); diff --git a/src/component/cyfs-stack/src/lib.rs b/src/component/cyfs-stack/src/lib.rs index c180fe861..832029d33 100644 --- a/src/component/cyfs-stack/src/lib.rs +++ b/src/component/cyfs-stack/src/lib.rs @@ -29,6 +29,8 @@ mod config; mod front; mod rmeta_api; mod rmeta; +mod group; +mod group_api; pub use stack::*; pub use storage::*; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 23b3c6c4b..7f6f75ef7 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -10,6 +10,7 @@ use crate::crypto_api::{CryptoService, ObjectCrypto, ObjectVerifier}; use crate::events::RouterEventsManager; use crate::forward::ForwardProcessorManager; use crate::front::FrontService; +use crate::group_api::GroupService; use crate::interface::{ ObjectListenerManager, ObjectListenerManagerParams, ObjectListenerManagerRef, }; @@ -105,7 +106,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupManager, + group_service: GroupService, } impl CyfsStackImpl { @@ -434,6 +435,8 @@ impl CyfsStackImpl { bdt_stack.clone(), global_state_manager.clone_processor(), )?; + let group_service = + GroupService::new(forward_manager.clone(), zone_manager.clone(), group_manager); let mut stack = Self { config, @@ -471,7 +474,7 @@ impl CyfsStackImpl { acl_manager, - group_manager, + group_service, }; // init an system-dec router-handler processor for later use @@ -561,6 +564,7 @@ impl CyfsStackImpl { &stack.root_state, &stack.local_cache, &stack.global_state_meta, + &stack.group_service, ); let interface = Arc::new(interface); @@ -1118,8 +1122,8 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupManager { - &self.stack.group_manager + pub fn group_service(&self) -> &GroupService { + &self.stack.group_service } // use system dec as default dec From 6a83a3ad60c266b8c725307472915a1e10d3dcf6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Mar 2023 17:39:29 +0800 Subject: [PATCH 101/553] Remove several unused import --- src/component/cyfs-group-lib/src/request_codec.rs | 2 +- src/component/cyfs-group-lib/src/requestor.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 58404d6b0..4c7ddfe88 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 462b1df85..341bff3e3 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -4,7 +4,7 @@ use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, CYFS_API_LEVEL, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, }; @@ -116,7 +116,7 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupStartServiceOutputResponse::decode_string(&body).map_err(|e| { // error!( // "decode group start service resp from body string error: body={} {}", // body, e, @@ -179,9 +179,9 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { // error!( - // "decode group start service resp from body string error: body={} {}", + // "decode group push proposal resp from body string error: body={} {}", // body, e, // ); // e From 7bdf8959a34988a96e8e0c4a7d1fd548d9497ef4 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 19:19:00 +0800 Subject: [PATCH 102/553] Debug --- src/component/cyfs-group-lib/Cargo.toml | 1 - .../cyfs-group-lib/src/group_manager.rs | 138 +++++- src/component/cyfs-group-lib/src/requestor.rs | 11 +- .../cyfs-group/src/dec/group_events.rs | 43 +- .../cyfs-group/src/dec/group_manager.rs | 10 +- .../cyfs-group/src/dec/rpath_service.rs | 7 +- .../src/group_api/service/group_listener.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 21 +- .../cyfs-stack/src/zone/zone_manager.rs | 20 +- src/tests/group-example/Cargo.toml | 4 +- src/tests/group-example/src/main.rs | 436 ++++++++---------- 11 files changed, 407 insertions(+), 288 deletions(-) diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index 740b303cd..68931728c 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -32,5 +32,4 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f442d5c55..61a11698d 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -7,7 +7,7 @@ use cyfs_base::{ }; use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -68,11 +68,14 @@ impl GroupManager { // TODO: other filters? only local zone let filter = format!( - "obj_type == {} && dec_id == {}", + "obj_type == {} && source.dec_id == {} && source.zone_category == {}", CoreObjectType::GroupCommand as u16, dec_id, + DeviceZoneCategory::CurrentZone.to_string(), ); + // let filter = "*".to_string(); + router_handler_manager .post_object() .add_handler( @@ -80,7 +83,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - None, + Some("group-inner".to_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) @@ -120,7 +123,38 @@ impl GroupManager { rpath: String, delegate: Box, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap().clone(); + + { + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(&dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath.as_str())); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + RPathService::new( + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + Ok(service.clone()) + } } pub async fn find_rpath_service( @@ -128,7 +162,20 @@ impl GroupManager { group_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap(); + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + found.map_or( + Err(BuckyError::new( + BuckyErrorCode::NotFound, + "please start the service first", + )), + |service| Ok(service.clone()), + ) } pub async fn rpath_client( @@ -204,6 +251,16 @@ impl GroupManager { ) .await .map(|_| ()) + .map_err(|err| { + log::warn!( + "group on_new_rpath {}-{:?}-{} failed, err: {:?}", + cmd.group_id, + self.0.stack.dec_id(), + cmd.rpath, + err + ); + err + }) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { @@ -216,11 +273,27 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; Ok(GroupCommandExecuteResult { result_state_id: result.result_state_id.take(), @@ -239,7 +312,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_verify find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -250,6 +331,14 @@ impl GroupManager { service .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) .await + .map_err(|err| { + log::warn!( + "group on_verify {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + }) } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { @@ -262,7 +351,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_commited find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -361,27 +458,38 @@ impl EventListenerAsyncRoutine BuckyResult { let req_common = ¶m.request.common; - if req_common.level != NONAPILevel::NOC - || req_common.source.zone.zone != self.0.local_zone + let obj = ¶m.request.object; + + log::debug!( + "group-command handle, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) + ); + + if !req_common.source.zone.is_current_zone() || self.0.local_zone.is_none() + // || req_common.source.zone.zone != self.0.local_zone || self.0.stack.dec_id().is_none() { log::warn!( - "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", req_common.level, req_common.source.zone, self.0.local_zone, - self.0.stack.dec_id() + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) ); return Ok(RouterHandlerPostObjectResult { - action: RouterHandlerAction::Reject, + action: RouterHandlerAction::Pass, request: None, response: None, }); } - let obj = ¶m.request.object; match obj.object.as_ref() { None => { return Ok(RouterHandlerPostObjectResult { diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 341bff3e3..b77f93dad 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -6,7 +6,8 @@ use cyfs_base::{ }; use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ - HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, + HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, + RequestorHelper, }; use http_types::{Method, Request, Url}; @@ -43,7 +44,7 @@ impl GroupRequestor { fn encode_common_headers( &self, - // action: NONAction, + action: NONAction, com_req: &NONOutputRequestCommon, http_req: &mut Request, ) { @@ -56,7 +57,7 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); @@ -98,7 +99,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -156,7 +157,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 9bda7e340..a25accb19 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,9 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -32,13 +35,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -78,13 +86,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -111,16 +124,26 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd + .to_vec() + .expect(format!("on_commited {} failed for encode", self.non_driver.dec_id()).as_str()); + let any_obj = cyfs_base::AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(object_raw_buf.as_slice()).expect( + format!( + "on_commited {} failed for convert to any", + self.non_driver.dec_id() + ) + .as_str(), + ), + ); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec().expect( - format!("on_commited {} failed for encode", self.non_driver.dec_id()) - .as_str(), - ), - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7a9708ccc..579f63831 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawConvertTo, RsaCPUObjectSigner, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; @@ -488,6 +488,10 @@ impl GroupManager { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); let result = self .local_info() .non_driver @@ -495,8 +499,8 @@ impl GroupManager { dec_id, NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index b4b90972f..1f2e836a1 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -66,6 +66,11 @@ impl RPathService { } pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + log::info!( + "group({:?}) push proposal {}", + self.rpath(), + proposal.desc().object_id() + ); self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 163228d1f..47be52927 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").post(Self::new( + server.at("/group/start-service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").post(Self::new( + server.at("group/push-proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9333e7981..fa136b3fa 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::NOC, + level: NONAPILevel::Router, target: None, flags: 0, @@ -90,10 +90,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { obj: NONObjectInfo, to: Option<&ObjectId>, ) -> BuckyResult> { + let obj_type_code = obj.object_id.obj_type_code(); + let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some("group-inner".to_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -105,7 +108,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, @@ -114,5 +117,15 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) .await .map(|resp| resp.object) + .map_err(|err| { + log::warn!( + "group post object(type={:?}/{:?}) to {:?} failed {:?}", + obj_type_code, + obj_type, + to, + err + ); + err + }) } } diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 6819b991d..61f284bc4 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -652,7 +652,25 @@ impl ZoneManager { owner_id, work_mode, list ); - return Ok((work_mode, list.to_owned())); + if obj_type == ObjectTypeCode::People { + return Ok((work_mode, list.to_owned())); + } else if obj_type == ObjectTypeCode::Group { + let group = owner_object.into_group(); + // TODO: 先简单处理,找最近的OOD,后面可能要依据具体操作向不同身份发起请求; + // 比如:读操作向任意member请求即可 + let list = group + .ood_list_with_distance( + self.get_current_device_id().object_id(), + ) + .into_iter() + .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) + .map(|id| DeviceId::try_from(id).unwrap()) + .collect(); + return Ok((work_mode, list)); + } else { + unreachable!() + } + /* let ood_device_id = list[0].clone(); let obj_type = ood_device_id.object_id().obj_type_code(); diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 01094f12a..2cf31aba9 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -23,9 +23,9 @@ cyfs-core = { path = '../../component/cyfs-core' } cyfs-bdt = { path = '../../component/cyfs-bdt' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } -cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 88450ac1b..e74f3c5d6 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,36 +1,43 @@ -use std::{clone, sync::Arc, time::Duration}; +use std::{clone, collections::HashSet, sync::Arc, time::Duration}; +use async_std::sync::Mutex; use cyfs_base::{ AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_group::IsCreateRPath; +use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, - NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, + NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, + RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; +use crate::{ + Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}, + GroupDecService::MyRPathDelegate, +}; mod Common { - use std::{fmt::format, io::ErrorKind, sync::Arc}; + use std::{ + fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, + }; - use async_std::{fs, stream::StreamExt}; + use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId, DecAppObj}; - use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_core::{DecApp, DecAppId}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, @@ -348,6 +355,8 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, + rpc_port: u16, + ws_port: u16, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -369,13 +378,19 @@ mod Common { config: CyfsStackConfigParams { isolate: Some(device.desc().object_id().to_string()), sync_service: false, - shared_stack: false, + shared_stack: true, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], - tcp_listeners: vec![], - ws_listener: None, + tcp_listeners: vec![SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + rpc_port, + ))], + ws_listener: Some(SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + ws_port, + ))), }, meta: CyfsStackMetaParams { target: MetaMinerTarget::Dev, @@ -454,9 +469,20 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, - ) -> CyfsStack { - let params = - init_stack_params(people, private_key, device, admins, members, group, dec_app); + rpc_port: u16, + ws_port: u16, + ) -> (CyfsStack, SharedCyfsStack) { + let params = init_stack_params( + people, + private_key, + device, + admins, + members, + group, + dec_app, + rpc_port, + ws_port, + ); log::info!("cyfs-stack.open"); @@ -468,14 +494,23 @@ mod Common { }) .unwrap(); - stack + async_std::task::sleep(Duration::from_millis(1000)).await; + + let shared_stack = + SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) + .await + .unwrap(); + + shared_stack.wait_online(None).await.unwrap(); + + (stack, shared_stack) } } mod Client { // use cyfs_base::ObjectId; // use cyfs_core::GroupProposal; - // use cyfs_group::RPathClient; + // use cyfs_group_lib::RPathClient; // pub struct DecClient {} @@ -505,12 +540,14 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathService; + use cyfs_group_lib::{ + DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, + RPathService, + }; use cyfs_lib::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, - NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, SharedCyfsStack, }; - use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -518,16 +555,18 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { - let group_mgr = cyfs_stack.group_mgr(); - - group_mgr - .register( - dec_app_id.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), - ) - .await - .unwrap(); + pub async fn run( + cyfs_stack: &SharedCyfsStack, + local_name: String, + dec_app_id: DecAppId, + ) -> GroupManager { + let group_mgr = GroupManager::open( + cyfs_stack.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + &cyfs_lib::CyfsStackRequestorType::Http, + ) + .await + .unwrap(); // let source = RequestSourceInfo { // protocol: todo!(), @@ -541,6 +580,8 @@ mod GroupDecService { // .handlers(&RouterHandlerChain::PostRouter) // .post_object() // .add_handler(RouterHandler::new()); + + group_mgr } } @@ -570,7 +611,7 @@ mod GroupDecService { impl GroupRPathDelegateFactory { pub fn is_accept( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, ) -> bool { @@ -583,27 +624,18 @@ mod GroupDecService { impl DelegateFactory for GroupRPathDelegateFactory { async fn create_rpath_delegate( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { + if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } } pub struct MyRPathDelegate { @@ -621,73 +653,19 @@ mod GroupDecService { } impl MyRPathDelegate { - // pub async fn get_value_from_state_tree_with_single_op_envs( - // pre_state_id: Option, - // object_map_processor: &dyn GroupObjectMapProcessor, - // ) -> BuckyResult<( - // Option, - // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - // )> { - // let mut single_op_envs = vec![]; - // let mut parent_map_id = pre_state_id; - // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - // let single_op_env = object_map_processor.create_single_op_env().await.expect( - // format!( - // "create_single_op_env load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // parent_map_id = match parent_map_id { - // Some(parent_map_id) => { - // single_op_env.load(&parent_map_id).await.expect( - // format!( - // "load folder {} parent with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // single_op_env.get_by_key(folder).await.expect( - // format!( - // "load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ) - // } - // None => { - // single_op_env - // .create_new(ObjectMapSimpleContentType::Map) - // .await - // .expect( - // format!( - // "create folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // None - // } - // }; - // single_op_envs.push((single_op_env, folder, parent_map_id)); - // } - - // Ok((parent_map_id, single_op_envs)) - // } - pub async fn execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); - let pre_value = match pre_state_id { - Some(pre_state_id) => { - state_op_env.load(&pre_state_id).await?; + let prev_value = match prev_state_id { + Some(prev_state_id) => { + state_op_env.load(prev_state_id.to_owned()).await?; state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -708,13 +686,13 @@ mod GroupDecService { let result_value = { /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_value.map_or(0, |pre_value| { - let buf = pre_value.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + let prev_value = prev_value.map_or(0, |prev_value| { + let buf = prev_value.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let delta_buf = proposal.params().as_ref().unwrap().as_slice(); @@ -722,7 +700,7 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let value = pre_value + delta; + let value = prev_value + delta; ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() @@ -731,13 +709,13 @@ mod GroupDecService { let result_state_id = { state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) .await .expect( format!( "set_with_path {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), @@ -746,34 +724,11 @@ mod GroupDecService { format!( "commit {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), ) - // let mut sub_folder_value = result_value; - // for (parent_single_op_env, folder, sub_folder_prev_value) in - // single_op_envs.into_iter().rev() - // { - // parent_single_op_env - // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - // .await - // .expect( - // format!( - // "update folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // sub_folder_value = parent_single_op_env.commit().await.expect( - // format!( - // "commit folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // } - // sub_folder_value }; let receipt = { @@ -791,11 +746,11 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_value + proposal + context + * (result_state_id, return_object) = prev_value + proposal + context */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id), + result_state_id: Some(result_state_id.root), receipt, }) } @@ -803,21 +758,21 @@ mod GroupDecService { pub async fn verify( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult { + ) -> BuckyResult<()> { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context + * == prev_state_id + proposal + execute_result.context */ let result = self - .execute(proposal, pre_state_id, object_map_processor) + .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", - pre_state_id, + prev_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), @@ -830,7 +785,11 @@ mod GroupDecService { && execute_result.context.is_none() && execute_result.receipt.is_none(); - Ok(is_ok) + if is_ok { + Ok(()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "result unmatch")) + } } } @@ -839,31 +798,36 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id, object_map_processor) + self.execute(proposal, prev_state_id, object_map_processor) .await } async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, object_map_processor, execute_result) - .await + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<()> { + self.verify( + proposal, + prev_state_id, + object_map_processor, + execute_result, + ) + .await } async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 @@ -872,16 +836,16 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = match pre_state_id { - Some(pre_state_id) => { + let prev_value = match prev_state_id { + Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&pre_state_id) + .load(*prev_state_id) .await - .expect(format!("load {} failed", pre_state_id).as_str()); + .expect(format!("load {} failed", prev_state_id).as_str()); state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -892,21 +856,21 @@ mod GroupDecService { } None => None, } - .map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + .map_or(0, |prev_state_id| { + let buf = prev_state_id.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let result_value = match execute_result.result_state_id { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&result_state_id) + .load(result_state_id) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -932,7 +896,7 @@ mod GroupDecService { "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, - pre_value, + prev_value, result_value, proposal_id, block.block_id(), @@ -942,10 +906,6 @@ mod GroupDecService { let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); assert!(is_new_finished); } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() - } } } @@ -982,6 +942,7 @@ async fn main_run() { cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) .exit_on_panic(true) + .dingtalk_bug_report("any value to disable") .build() .start(); @@ -1004,9 +965,12 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec = vec![]; + let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; + let mut group_mgrs: Vec = vec![]; + let mut rpc_port = 32217_u16; + let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { - let cyfs_stack = create_stack( + let (cyfs_stack, shared_stack) = create_stack( admin, private_key, device, @@ -1020,33 +984,34 @@ async fn main_run() { .collect(), &group, &dec_app, + rpc_port, + ws_port, ) .await; - admin_stacks.push(cyfs_stack); + admin_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; } async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { - let stack = admin_stacks.get(i).unwrap(); + let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); - DecService::run( - &stack, - admin.name().unwrap().to_string(), - dec_app_id.clone(), - ) - .await; - - let service = stack - .group_mgr() - .find_rpath_service( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, + let local_name = admin.name().unwrap(); + let group_mgr = + DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; + + let service = group_mgr + .start_rpath_service( + group.desc().object_id(), + EXAMPLE_RPATH.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), ) .await .unwrap(); + + group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1057,7 +1022,8 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, @@ -1066,42 +1032,31 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); - let noc = stack.noc_manager().clone(); + let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); let proposal_any = Arc::new(AnyNamedObject::Core( TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), )); - let req = NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: dec_app_id.object_id().clone(), - verified: None, + let req = NONPutObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: None, + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: Some(AccessString::full().value()), + access: Some(AccessString::full()), }; - noc.put_object(&req).await; + noc.put_object(req).await; proposals.push(proposal); } @@ -1112,20 +1067,15 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); async_std::task::spawn(async move { - service.push_proposal(proposal).await.unwrap(); + service.push_proposal(&proposal).await.unwrap(); }); if i % 10 == 0 { @@ -1136,27 +1086,25 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - let client = admin_stacks - .get(0) - .unwrap() - .group_mgr() - .rpath_client( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - ) - .await - .unwrap(); - - let value_obj = client - .get_by_path(EXAMPLE_VALUE_PATH.as_str()) - .await - .unwrap(); - let buf = value_obj.as_ref().unwrap().object_id.data(); - let mut value = [0u8; 8]; - value.copy_from_slice(&buf[..8]); - - log::info!("value from client is: {}", u64::from_be_bytes(value)); + // let client = group_mgrs + // .get(0) + // .unwrap() + // .rpath_client( + // &group.desc().object_id(), + // dec_app_id.object_id(), + // &EXAMPLE_RPATH, + // ) + // .await; + + // let value_obj = client + // .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + // .await + // .unwrap(); + // let buf = value_obj.as_ref().unwrap().object_id.data(); + // let mut value = [0u8; 8]; + // value.copy_from_slice(&buf[..8]); + + // log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From b4920e8bd908c19f6bb4b61f93c2c0e1f3cd3ae2 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 15 Feb 2023 15:53:54 +0800 Subject: [PATCH 103/553] Fix: monitor create desc error --- src/misc/cyfs-monitor/src/case/meta_chain.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/misc/cyfs-monitor/src/case/meta_chain.rs b/src/misc/cyfs-monitor/src/case/meta_chain.rs index 464cc6772..904d11928 100644 --- a/src/misc/cyfs-monitor/src/case/meta_chain.rs +++ b/src/misc/cyfs-monitor/src/case/meta_chain.rs @@ -53,6 +53,7 @@ fn ensure_desc() -> BuckyResult<(PrivateKey, People)> { let sec_path = path.with_extension("sec"); if !desc_path.exists() || !sec_path.exists() { info!("not found meta writer desc, create."); + let _ = std::fs::create_dir_all(path.parent().unwrap()); let pk = PrivateKey::generate_rsa(1024)?; let people = People::new(None, vec![], pk.public(), None, None, None).build(); pk.encode_to_file(&sec_path, false)?; From 41d109a1dc2065dd23995cd4892c1c2c1718bab2 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Wed, 15 Feb 2023 16:11:05 +0800 Subject: [PATCH 104/553] Fix: stream break when loss fin ack packet --- .../cyfs-bdt/src/stream/package/read.rs | 43 ++++++++++--------- .../cyfs-bdt/src/stream/package/stream.rs | 42 +++++++----------- .../cyfs-bdt/src/stream/package/write.rs | 40 +++++++++++++---- src/component/cyfs-bdt/tests/sn.rs | 6 +-- 4 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/component/cyfs-bdt/src/stream/package/read.rs b/src/component/cyfs-bdt/src/stream/package/read.rs index aaf28bcac..127182065 100644 --- a/src/component/cyfs-bdt/src/stream/package/read.rs +++ b/src/component/cyfs-bdt/src/stream/package/read.rs @@ -238,7 +238,10 @@ impl ReadProvider { if let Some(readable) = provider.readable_waiter.as_ref() { to_wake.push_back(readable.clone()); } - *state = ReadProviderState::Closed(provider.queue.stream_end(), Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "stream broken"))); + *state = ReadProviderState::Closed( + provider.queue.stream_end(), + Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "stream broken")) + ); }, ReadProviderState::Closed(_, _) => { @@ -336,14 +339,12 @@ impl ReadProvider { ret } - pub fn close(&self, _: &PackageStream) { + pub fn close(&self) { let _ = { let state = &mut *cyfs_debug::lock!(self.0).unwrap(); match state { ReadProviderState::Open(provider) => { - *state = ReadProviderState::Closed( - provider.queue.stream_end(), - Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "stream broken"))); + *state = ReadProviderState::Closed(provider.queue.stream_end(), Ok(0)) }, _ => {} } @@ -355,17 +356,10 @@ impl OnPackage)> for Read fn on_package(&self, session_data: &SessionData, context: (&PackageStream, &mut Vec)) -> Result { let stream = context.0; let packages = context.1; - let mut closed = false; let (readable_waker, read_waker) = { let state = &mut *cyfs_debug::lock!(self.0).unwrap(); match state { ReadProviderState::Open(provider) => { - if session_data.is_flags_contain(SESSIONDATA_FLAG_RESET) { - *state = ReadProviderState::Closed( - provider.queue.stream_end(), - Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "stream reset"))); - return Ok(OnPackageResult::Handled) - } if session_data.payload.as_ref().len() > 0 || session_data.is_flags_contain(SESSIONDATA_FLAG_FIN) { match &provider.nagle { @@ -405,11 +399,22 @@ impl OnPackage)> for Read } }, - ReadProviderState::Closed(_, _) => { - debug!("closed stream get data"); - - closed = true; - + ReadProviderState::Closed(stream_end, _) => { + if session_data.stream_pos_end() > *stream_end { + debug!("{} will ack reset for read closed", stream); + let mut package = SessionData::new(); + package.flags_add(SESSIONDATA_FLAG_RESET); + package.send_time = bucky_time_now(); + packages.push(DynamicPackage::from(package)); + } else { + if packages.len() == 0 || !(&packages[packages.len() - 1] as &dyn AsRef).as_ref().is_flags_contain(SESSIONDATA_FLAG_ACK) { + trace!("{} will ack for fin or nagle income", stream); + let mut package = SessionData::new(); + package.flags_add(SESSIONDATA_FLAG_ACK); + package.send_time = bucky_time_now(); + packages.push(DynamicPackage::from(package)); + } + } // do nothing (None, None) } @@ -422,10 +427,6 @@ impl OnPackage)> for Read to_wake.wake(); } - if closed { - return Ok(OnPackageResult::Break) - } - Ok(OnPackageResult::Handled) } } diff --git a/src/component/cyfs-bdt/src/stream/package/stream.rs b/src/component/cyfs-bdt/src/stream/package/stream.rs index f69b9e2da..58e76fea8 100644 --- a/src/component/cyfs-bdt/src/stream/package/stream.rs +++ b/src/component/cyfs-bdt/src/stream/package/stream.rs @@ -169,11 +169,11 @@ impl StreamProvider for PackageStream { let _ = self.write_provider().close(self, None); }, Shutdown::Read => { - + let _ = self.read_provider().close(); }, Shutdown::Both => { let _ = self.write_provider().close(self, None); - let _ = self.read_provider().close(self); + let _ = self.read_provider().close(); } } Ok(()) @@ -217,39 +217,27 @@ impl StreamProvider for PackageStream { } impl OnPackage for PackageStream { - fn on_package(&self, session_data: &SessionData, _: Option<()>) -> Result { + fn on_package(&self, session_data: &SessionData, _: Option<()>) -> BuckyResult { let mut packages = Vec::new(); let r = if session_data.is_syn_ack() { let ack_ack = SessionData::new(); packages.push(DynamicPackage::from(ack_ack)); - Ok(OnPackageResult::Handled) + OnPackageResult::Handled } else { trace!("{} on session data {}", self, session_data); - let write_result = self.write_provider().on_package(session_data, (self, &mut packages))?; + let write_result = if session_data.is_reset() { + self.write_provider().reset(self); + OnPackageResult::Continue + } else { + self.write_provider().on_package(session_data, (self, &mut packages))? + }; + match write_result { - OnPackageResult::Continue | OnPackageResult::Break => { - let read_result = self.read_provider().on_package(session_data, (self, &mut packages)); - if read_result.is_err() { - read_result - } else { - let read_result = read_result.unwrap(); - if write_result == OnPackageResult::Break && - read_result == OnPackageResult::Break && - !session_data.is_flags_contain(SESSIONDATA_FLAG_RESET) { - let mut package = SessionData::new(); - package.flags_add(SESSIONDATA_FLAG_RESET); - package.send_time = bucky_time_now(); - packages.push(DynamicPackage::from(package)); - } - - Ok(OnPackageResult::Handled) - } - }, - OnPackageResult::Handled => { - Ok(OnPackageResult::Handled) - }, + OnPackageResult::Continue => self.read_provider().on_package(session_data, (self, &mut packages))?, + OnPackageResult::Handled => OnPackageResult::Handled, + _ => unreachable!() } - }?; + }; let _ = self.send_packages(packages); Ok(r) } diff --git a/src/component/cyfs-bdt/src/stream/package/write.rs b/src/component/cyfs-bdt/src/stream/package/write.rs index 02cd9b3ae..132acaef0 100644 --- a/src/component/cyfs-bdt/src/stream/package/write.rs +++ b/src/component/cyfs-bdt/src/stream/package/write.rs @@ -233,6 +233,35 @@ impl WriteProvider { let _ = stream.send_packages(packages); result } + + pub fn reset(&self, stream: &PackageStream) { + let waiters = { + let mut waiters = LinkedList::new(); + let state = &mut *cyfs_debug::lock!(self.0).unwrap(); + match state { + WriteProviderState::Open(provider) => { + info!("{} reset write", stream); + if let Some(waiter) = provider.write_waiter.as_ref() { + waiters.push_back(waiter.clone()); + provider.write_waiter = None; + } + waiters.append(&mut provider.flush_waiters); + if let Some(waiter) = provider.close_waiter.as_ref() { + waiters.push_back(waiter.clone()); + provider.close_waiter = None; + } + *state = WriteProviderState::Closed; + }, + _ => {} + } + + waiters + }; + + for waiter in waiters { + waiter.wake(); + } + } } impl OnPackage)> for WriteProvider { @@ -244,10 +273,7 @@ impl OnPackage)> for Writ match state { WriteProviderState::Open(provider) => { let now = bucky_time_now(); - if session_data.is_flags_contain(SESSIONDATA_FLAG_RESET) { - *state = WriteProviderState::Closed; - return Ok(OnPackageResult::Handled) - } else if session_data.is_flags_contain(SESSIONDATA_FLAG_ACK_PACKAGEID) { + if session_data.is_flags_contain(SESSIONDATA_FLAG_ACK_PACKAGEID) { let ack_est_package = session_data; let package_id = ack_est_package.id_part.as_ref().unwrap().package_id; trace!("{} recv estimate ack package {}", stream, package_id); @@ -315,11 +341,7 @@ impl OnPackage)> for Writ (Ok(OnPackageResult::Continue), Some(waiters)) } }, - WriteProviderState::Closed => { - debug!("closed stream get data"); - - (Ok(OnPackageResult::Break), None) - } + WriteProviderState::Closed => (Ok(OnPackageResult::Continue), None) } }; diff --git a/src/component/cyfs-bdt/tests/sn.rs b/src/component/cyfs-bdt/tests/sn.rs index a13be802f..816487a16 100644 --- a/src/component/cyfs-bdt/tests/sn.rs +++ b/src/component/cyfs-bdt/tests/sn.rs @@ -394,7 +394,7 @@ async fn call_with_tcp() { #[async_std::test] async fn sn_with_ipv6() { - let ipv6_ep = format!("D6udp[{:?}]:10024", &local_ip_address::list_afinet_netifas().unwrap()[0].1); + let ipv6_ep = format!("D6udp[{:?}]:10027", &local_ip_address::list_afinet_netifas().unwrap()[0].1); let (sn, sn_secret) = utils::create_device("5aSixgLuJjfrNKn9D4z66TEM6oxL3uNmWCWHk52cJDKR", &["L4udp127.0.0.1:10027", &ipv6_ep]).unwrap(); @@ -409,8 +409,8 @@ async fn sn_with_ipv6() { }); - let (ln_dev, ln_secret) = utils::create_device("5aSixgLuJjfrNKn9D4z66TEM6oxL3uNmWCWHk52cJDKR", &["L4udp127.0.0.1:10028", "D6udp[::]:10025", "D6tcp[::]:10025"]).unwrap(); - let (rn_dev, rn_secret) = utils::create_device("5aSixgLuJjfrNKn9D4z66TEM6oxL3uNmWCWHk52cJDKR", &["L4udp127.0.0.1:10029", "D6udp[::]:10026", "D6tcp[::]:10026"]).unwrap(); + let (ln_dev, ln_secret) = utils::create_device("5aSixgLuJjfrNKn9D4z66TEM6oxL3uNmWCWHk52cJDKR", &["L4udp127.0.0.1:10028", "D6udp[::]:10025", "D6tcp[::]:10028"]).unwrap(); + let (rn_dev, rn_secret) = utils::create_device("5aSixgLuJjfrNKn9D4z66TEM6oxL3uNmWCWHk52cJDKR", &["L4udp127.0.0.1:10029", "D6udp[::]:10026", "D6tcp[::]:10029"]).unwrap(); let mut ln_params = StackOpenParams::new(""); ln_params.config.interface.udp.sn_only = true; From 7bea0d17990aa0884ef3f3fa5318a1a0b6c9a716 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 15 Feb 2023 16:15:18 +0800 Subject: [PATCH 105/553] Fix: monitor create desc when desc not existed on chain --- src/misc/cyfs-monitor/src/case/meta_chain.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/misc/cyfs-monitor/src/case/meta_chain.rs b/src/misc/cyfs-monitor/src/case/meta_chain.rs index 904d11928..4e11005a9 100644 --- a/src/misc/cyfs-monitor/src/case/meta_chain.rs +++ b/src/misc/cyfs-monitor/src/case/meta_chain.rs @@ -135,10 +135,18 @@ impl MonitorRunner for MetaChainWriteMonitor { let update_time = cyfs_base::bucky_time_now(); people.body_mut_expect("").set_update_time(update_time); let data = SavedMetaObject::People(people.clone()); - let txid = self.meta_client.update_desc(&StandardObject::People(people), &data, None, None, &self.sec).await.map_err(|e|{ - error!("update desc err {}", e); - e - })?; + let exist = self.meta_client.get_desc(&people_id).await.is_ok(); + let txid = if exist { + self.meta_client.update_desc(&StandardObject::People(people), &data, None, None, &self.sec).await.map_err(|e|{ + error!("update desc err {}", e); + e + }) + } else { + self.meta_client.create_desc(&StandardObject::People(people), &data, 0, 0, 0, &self.sec).await.map_err(|e|{ + error!("create desc err {}", e); + e + }) + }?; let mut success = false; for _ in 0..3 { if let Ok(Some((ret, _))) = self.meta_client.get_tx_receipt(&txid).await { From 7c976d4e228baaffb306913e26342cd655efaeec Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 16 Feb 2023 12:30:10 +0800 Subject: [PATCH 106/553] Fix field names of ood status --- src/service/ood-daemon/src/main.rs | 2 +- src/service/ood-daemon/src/status/status.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/service/ood-daemon/src/main.rs b/src/service/ood-daemon/src/main.rs index 1ad73ebe4..2cd2a9ca8 100644 --- a/src/service/ood-daemon/src/main.rs +++ b/src/service/ood-daemon/src/main.rs @@ -1,4 +1,4 @@ -//#![windows_subsystem = "windows"] +#![windows_subsystem = "windows"] mod config; mod config_repo; diff --git a/src/service/ood-daemon/src/status/status.rs b/src/service/ood-daemon/src/status/status.rs index 06a2738bb..7eb1d2f2e 100644 --- a/src/service/ood-daemon/src/status/status.rs +++ b/src/service/ood-daemon/src/status/status.rs @@ -12,7 +12,7 @@ use once_cell::sync::OnceCell; struct ServiceStatusCache { name: String, status: serde_json::Value, - last_update_tick: u64, + last_update_time: u64, } #[derive(Clone)] @@ -91,7 +91,7 @@ impl OODStatusManager { for item in list.iter_mut() { if item.name == name { item.status = status; - item.last_update_tick = bucky_time_now(); + item.last_update_time = bucky_time_now(); return; } } @@ -99,7 +99,7 @@ impl OODStatusManager { list.push(ServiceStatusCache { name: name.to_owned(), status, - last_update_tick: bucky_time_now(), + last_update_time: bucky_time_now(), }); } } From 47340054dab1c832b049844c8cf75b765caf8a9d Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 16 Feb 2023 16:54:37 +0800 Subject: [PATCH 107/553] App-manager report app status to ood-daemon --- src/Cargo.lock | 2223 ++++++++++++++--- src/service/app-manager/Cargo.toml | 3 +- src/service/app-manager/src/app_controller.rs | 1 + src/service/app-manager/src/non_helper.rs | 62 +- 4 files changed, 1956 insertions(+), 333 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 83cc75bfe..2b06fec2a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -111,9 +111,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" [[package]] name = "android_logger" -version = "0.11.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" +checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" dependencies = [ "android_log-sys", "env_logger", @@ -141,9 +141,97 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + +[[package]] +name = "app-manager" +version = "0.5.0" +dependencies = [ + "app-manager-lib", + "async-std", + "async-trait", + "bollard", + "chrono", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "flate2", + "fs_extra", + "futures-util", + "log 0.4.17", + "once_cell", + "ood-daemon", + "regex", + "serde", + "serde_json", + "surf", + "tar", + "toml", + "version-compare", + "wait-timeout", + "walkdir", + "which", + "zip", +] + +[[package]] +name = "app-manager-lib" +version = "0.5.0" +dependencies = [ + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", + "serde", + "serde_json", + "toml", +] + +[[package]] +name = "app-tool" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + +[[package]] +name = "app-tool-ex" +version = "0.5.0" +dependencies = [ + "async-std", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] [[package]] name = "arrayref" @@ -175,9 +263,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.8.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" dependencies = [ "concurrent-queue", "event-listener", @@ -221,6 +309,7 @@ dependencies = [ "blocking", "futures-lite", "once_cell", + "tokio", ] [[package]] @@ -241,9 +330,9 @@ dependencies = [ [[package]] name = "async-io" -version = "1.12.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" dependencies = [ "autocfg 1.1.0", "concurrent-queue", @@ -256,7 +345,7 @@ dependencies = [ "slab", "socket2", "waker-fn", - "windows-sys 0.42.0", + "winapi", ] [[package]] @@ -282,20 +371,20 @@ dependencies = [ [[package]] name = "async-process" -version = "1.6.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" +checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" dependencies = [ "async-io", - "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", + "once_cell", "signal-hook", - "windows-sys 0.42.0", + "winapi", ] [[package]] @@ -404,9 +493,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.60" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", @@ -447,7 +536,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -469,9 +558,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -522,6 +611,30 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +[[package]] +name = "bdt-debuger" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "log 0.4.17", +] + +[[package]] +name = "bdt-debuger-deamon" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "log 0.4.17", + "md5", +] + [[package]] name = "bincode" version = "1.3.3" @@ -538,6 +651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f" dependencies = [ "bitcoin_hashes", + "rand 0.6.5", "rand_core 0.4.2", "serde", "unicode-normalization", @@ -620,6 +734,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding 0.2.1", "generic-array 0.14.6", ] @@ -659,16 +774,77 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" dependencies = [ "async-channel", - "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", + "once_cell", +] + +[[package]] +name = "bollard" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" +dependencies = [ + "base64 0.13.1", + "bollard-stubs", + "bytes 1.2.1", + "chrono", + "dirs-next", + "futures-core", + "futures-util", + "hex", + "http", + "hyper 0.14.20", + "hyperlocal", + "log 0.4.17", + "pin-project", + "serde", + "serde_derive", + "serde_json", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util 0.6.10", + "url 2.3.0", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2f2e73fffe9455141e170fb9c1feb0ac521ec7e7dcd47a7cab72a658490fb8" +dependencies = [ + "chrono", + "serde", + "serde_with", +] + +[[package]] +name = "browser-meta-spv" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "hex", + "log 0.4.17", + "once_cell", + "serde", + "serde_json", + "sqlx", + "tide", + "toml", ] [[package]] @@ -707,6 +883,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" + [[package]] name = "byteorder" version = "1.4.3" @@ -725,9 +907,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.3.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "bzip2" @@ -770,9 +952,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -795,22 +977,55 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "checked_int_cast" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" + [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.45", + "time 0.1.44", "wasm-bindgen", "winapi", ] +[[package]] +name = "chunk-manager" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "chrono", + "cyfs-base", + "cyfs-base-meta", + "cyfs-chunk", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "lru_time_cache", + "rand 0.8.5", + "rusqlite", + "serde", + "serde_json", + "tide", + "timer", + "url 2.3.0", +] + [[package]] name = "cipher" version = "0.2.5" @@ -838,7 +1053,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -853,6 +1068,15 @@ dependencies = [ "term", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -863,6 +1087,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colored" version = "2.0.0" @@ -880,17 +1110,23 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", "memchr", ] +[[package]] +name = "commandlines" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" + [[package]] name = "concurrent-queue" -version = "2.0.0" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ - "crossbeam-utils", + "cache-padded", ] [[package]] @@ -1067,22 +1303,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.7.1", + "memoffset", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1090,9 +1326,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if 1.0.0", ] @@ -1196,9 +1432,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.85" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" dependencies = [ "cc", "cxxbridge-flags", @@ -1208,9 +1444,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.85" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" dependencies = [ "cc", "codespan-reporting", @@ -1223,15 +1459,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.85" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" [[package]] name = "cxxbridge-macro" -version = "1.0.85" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" dependencies = [ "proc-macro2", "quote", @@ -1275,7 +1511,8 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "simple_logger", + "simple_logger 2.3.0", + "sqlx", "url 2.3.0", "zip", ] @@ -1329,7 +1566,7 @@ dependencies = [ "log 0.4.17", "lru_time_cache", "md5", - "nix 0.24.3", + "nix 0.24.2", "once_cell", "rand 0.7.3", "ringbuf", @@ -1342,34 +1579,81 @@ dependencies = [ ] [[package]] -name = "cyfs-chunk" -version = "0.5.0" +name = "cyfs-bdt-ext" +version = "0.1.0" dependencies = [ "async-std", + "async-trait", "cyfs-base", - "cyfs-base-derive", - "hex", - "http-types", + "cyfs-bdt", + "cyfs-chunk-cache", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-ndc", + "cyfs-tracker-cache", + "cyfs-util", + "futures", "log 0.4.17", - "rand 0.8.5", + "lru_time_cache", + "once_cell", "serde", - "serde_json", - "time 0.1.45", - "url 2.3.0", ] [[package]] -name = "cyfs-chunk-cache" -version = "0.5.1" +name = "cyfs-bench-mark" +version = "0.1.0" +dependencies = [ + "cyfs-debug", +] + +[[package]] +name = "cyfs-check" +version = "0.5.0" dependencies = [ + "ansi_term", "async-std", "async-trait", - "base-x", + "clap", "cyfs-base", - "cyfs-chunk-lib", - "cyfs-debug", + "cyfs-base-meta", + "cyfs-meta-lib", "cyfs-util", - "futures-lite", + "dirs 4.0.0", + "log 0.4.17", + "sysinfo 0.26.5", +] + +[[package]] +name = "cyfs-chunk" +version = "0.5.0" +dependencies = [ + "async-std", + "cyfs-base", + "cyfs-base-derive", + "hex", + "http-types", + "log 0.4.17", + "rand 0.8.5", + "serde", + "serde_json", + "time 0.1.44", + "url 2.3.0", +] + +[[package]] +name = "cyfs-chunk-cache" +version = "0.5.1" +dependencies = [ + "async-std", + "async-trait", + "base-x", + "cyfs-base", + "cyfs-chunk-lib", + "cyfs-debug", + "cyfs-util", + "futures-lite", "hex", "log 0.4.17", "memmap2", @@ -1381,6 +1665,24 @@ dependencies = [ "sysinfo 0.26.5", ] +[[package]] +name = "cyfs-chunk-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk", + "cyfs-util", + "http-types", + "log 0.4.17", + "serde", + "serde_json", + "time 0.1.44", + "url 2.3.0", +] + [[package]] name = "cyfs-chunk-lib" version = "0.6.4" @@ -1401,7 +1703,7 @@ version = "0.6.4" dependencies = [ "bip39", "cyfs-base", - "digest 0.10.6", + "digest 0.10.5", "hex", "hmac 0.12.1", "log 0.4.17", @@ -1413,6 +1715,50 @@ dependencies = [ "sha2 0.10.6", ] +[[package]] +name = "cyfs-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-recursion", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-bdt", + "cyfs-chunk", + "cyfs-chunk-client", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "hex", + "http-types", + "log 0.4.17", + "once_cell", + "rand 0.7.3", + "serde_json", + "url 2.3.0", + "walkdir", +] + +[[package]] +name = "cyfs-container" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "log 0.4.17", +] + [[package]] name = "cyfs-core" version = "0.6.5" @@ -1423,7 +1769,6 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", - "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1436,7 +1781,6 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sha2 0.8.2", ] [[package]] @@ -1455,7 +1799,7 @@ dependencies = [ "futures", "hex", "http-types", - "hyper", + "hyper 0.10.16", "lazy_static", "libc", "log 0.4.17", @@ -1490,62 +1834,101 @@ dependencies = [ name = "cyfs-lib" version = "0.8.0" dependencies = [ - "async-recursion", + "async-h1", "async-std", "async-trait", + "async-tungstenite", + "bytes 1.2.1", "chrono", "cyfs-base", "cyfs-bdt", - "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", - "cyfs-lib", + "cyfs-util", "futures", + "futures-util", + "globset", + "hex", + "http-range", + "http-types", + "int-enum", "lazy_static", "log 0.4.17", - "prost 0.11.5", - "prost-build 0.11.5", + "lru_time_cache", + "once_cell", + "percent-encoding 2.2.0", "protobuf", - "protoc-bin-vendored", - "protoc-rust", "rand 0.8.5", "serde", "serde_json", - "sha2 0.8.2", + "surf", + "tide", ] [[package]] -name = "cyfs-lib" -version = "0.7.0" +name = "cyfs-meta" +version = "0.5.0" dependencies = [ "async-h1", "async-std", "async-trait", - "async-tungstenite", - "bytes 1.3.0", + "base58", + "base64 0.13.1", + "byteorder", "chrono", "cyfs-base", - "cyfs-bdt", + "cyfs-base-meta", "cyfs-core", - "cyfs-debug", "cyfs-util", + "evm", "futures", - "futures-util", - "globset", + "generic-array 0.12.4", "hex", - "http-range", "http-types", - "int-enum", "lazy_static", + "libsqlite3-sys", "log 0.4.17", - "lru_time_cache", - "once_cell", - "percent-encoding 2.2.0", - "protobuf", + "primitive-types", "rand 0.8.5", "serde", "serde_json", + "sha2 0.8.2", + "sqlx", "tide", + "timer", +] + +[[package]] +name = "cyfs-meta-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-recursion", + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "dirs 4.0.0", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "rand 0.7.3", + "serde_json", + "simple_logger 2.3.0", +] + +[[package]] +name = "cyfs-meta-genesis" +version = "0.5.0" +dependencies = [ + "commandlines", + "cyfs-meta", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", ] [[package]] @@ -1564,6 +1947,46 @@ dependencies = [ "surf", ] +[[package]] +name = "cyfs-meta-miner" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-debug", + "cyfs-meta", + "cyfs-meta-lib", + "hex", + "lazy_static", + "log 0.4.17", + "serde", + "serde_json", + "tide", +] + +[[package]] +name = "cyfs-meta-spv" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "base58", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "ethabi", + "hex", + "libsqlite3-sys", + "log 0.4.17", + "serde", + "serde_json", + "sqlx", + "tide", +] + [[package]] name = "cyfs-mobile-stack" version = "0.5.0" @@ -1582,6 +2005,32 @@ dependencies = [ "once_cell", ] +[[package]] +name = "cyfs-monitor" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "futures", + "log 0.4.17", + "once_cell", + "rand 0.7.3", + "serde", + "serde_json", + "surf", + "toml", + "url 2.3.0", +] + [[package]] name = "cyfs-ndc" version = "0.5.0" @@ -1594,7 +2043,6 @@ dependencies = [ "cyfs-util", "log 0.4.17", "rusqlite", - "thread_local", ] [[package]] @@ -1603,6 +2051,7 @@ version = "0.5.0" dependencies = [ "async-std", "async-trait", + "base-x", "cyfs-base", "cyfs-core", "cyfs-debug", @@ -1614,12 +2063,11 @@ dependencies = [ "lru_time_cache", "once_cell", "rusqlite", - "thread_local", ] [[package]] name = "cyfs-perf-base" -version = "0.6.0" +version = "0.6.1" dependencies = [ "async-std", "cyfs-base", @@ -1669,6 +2117,40 @@ dependencies = [ "threadpool", ] +[[package]] +name = "cyfs-runtime" +version = "0.5.0" +dependencies = [ + "android_logger", + "async-h1", + "async-std", + "async-trait", + "bytes 1.2.1", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "dirs 4.0.0", + "formdata", + "futures", + "http-types", + "hyper 0.10.16", + "jni", + "log 0.4.17", + "mime-sniffer", + "once_cell", + "ood-control", + "rand 0.7.3", + "serde", + "serde_json", + "tide", + "toml", + "url 2.3.0", +] + [[package]] name = "cyfs-sha2" version = "0.8.4" @@ -1676,7 +2158,7 @@ dependencies = [ "block-buffer 0.7.3", "digest 0.8.1", "fake-simd", - "hex-literal", + "hex-literal 0.1.4", "libc", "opaque-debug 0.2.3", "sha2-asm", @@ -1698,7 +2180,6 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", - "cyfs-group", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -1716,11 +2197,11 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.5", - "prost-build 0.11.5", + "prost 0.11.3", + "prost-build 0.11.3", "protoc-bin-vendored", "rand 0.8.5", - "semver 1.0.16", + "semver 1.0.14", "serde", "serde_json", "sha2 0.8.2", @@ -1730,6 +2211,29 @@ dependencies = [ "zip", ] +[[package]] +name = "cyfs-stack-bench" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "hex", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "serde", + "toml", +] + [[package]] name = "cyfs-stack-loader" version = "0.5.0" @@ -1753,6 +2257,35 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "cyfs-stack-test" +version = "0.5.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-noc", + "cyfs-perf-client", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "log 0.4.17", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "zone-simulator", +] + [[package]] name = "cyfs-task-manager" version = "0.6.2" @@ -1806,14 +2339,15 @@ dependencies = [ "log 0.4.17", "log-panics", "named-lock", - "nix 0.24.3", + "nix 0.24.2", "once_cell", "rand 0.8.5", "rusqlite", "serde", "serde_json", - "simple_logger", - "sysinfo", + "simple_logger 2.3.0", + "sysinfo 0.27.7", + "thread_local", "toml", "url 2.3.0", "walkdir", @@ -1821,6 +2355,41 @@ dependencies = [ "zip", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "dashmap" version = "5.4.0" @@ -1831,7 +2400,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.4", ] [[package]] @@ -1859,6 +2428,33 @@ dependencies = [ "pem-rfc7468", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "desc-tool" +version = "0.5.0" +dependencies = [ + "async-std", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "hex", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + [[package]] name = "digest" version = "0.8.1" @@ -1880,9 +2476,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -1909,6 +2505,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -1920,6 +2526,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users 0.4.3", + "winapi", +] + [[package]] name = "discard" version = "1.0.4" @@ -1938,6 +2555,22 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "email-encoding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34dd14c63662e0206599796cd5e1ad0268ab2b9d19b868d6050d688eba2bbf98" +dependencies = [ + "base64 0.13.1", + "memchr", +] + +[[package]] +name = "email_address" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" + [[package]] name = "encoding" version = "0.2.33" @@ -2004,9 +2637,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "env_logger" -version = "0.10.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "log 0.4.17", "regex", @@ -2014,18 +2647,139 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.24" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" +checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" +dependencies = [ + "serde", +] + +[[package]] +name = "ethabi" +version = "14.0.0" dependencies = [ + "anyhow", + "cyfs-base", + "ethereum-types", + "evm", + "hex", + "hex-literal 0.3.4", + "itertools", + "paste 1.0.9", + "rustc-hex", "serde", + "serde_json", + "sha3 0.9.1", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9" +dependencies = [ + "ethereum-types", + "funty", + "hash-db", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "rlp-derive", + "serde", + "sha3 0.9.1", + "triehash", +] + +[[package]] +name = "ethereum-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "evm" +version = "0.26.0" +dependencies = [ + "criterion", + "cyfs-base", + "cyfs-base-meta", + "ethereum", + "evm-core", + "evm-gasometer", + "evm-runtime", + "hex", + "log 0.4.17", + "parity-scale-codec", + "primitive-types", + "rlp", + "rlp-derive", + "serde", + "sha3 0.8.2", +] + +[[package]] +name = "evm-core" +version = "0.26.0" +dependencies = [ + "cyfs-base-meta", + "funty", + "hex", + "parity-scale-codec", + "primitive-types", + "serde", +] + +[[package]] +name = "evm-gasometer" +version = "0.26.0" +dependencies = [ + "cyfs-base", + "evm-core", + "evm-runtime", + "primitive-types", ] [[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +name = "evm-runtime" +version = "0.26.0" +dependencies = [ + "cyfs-base", + "evm-core", + "primitive-types", + "sha3 0.8.2", +] [[package]] name = "fake-simd" @@ -2070,6 +2824,32 @@ dependencies = [ "web-sys", ] +[[package]] +name = "file-manager" +version = "0.5.0" +dependencies = [ + "async-std", + "cyfs-base", + "cyfs-debug", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "rusqlite", + "tide", +] + +[[package]] +name = "filetime" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.16", + "windows-sys 0.42.0", +] + [[package]] name = "fixed-hash" version = "0.7.0" @@ -2090,9 +2870,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ "crc32fast", "miniz_oxide", @@ -2165,7 +2945,7 @@ checksum = "6b2e172b694029467db935166c398f911adce5373d63bb1149740cd9182a3eee" dependencies = [ "encoding", "httparse", - "hyper", + "hyper 0.10.16", "log 0.4.17", "mime 0.2.6", "mime_multipart", @@ -2182,6 +2962,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -2310,6 +3096,39 @@ dependencies = [ "slab", ] +[[package]] +name = "gateway" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "bytes 1.2.1", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "lru_time_cache", + "once_cell", + "regex", + "serde", + "serde_json", + "tide", + "toml", + "url 2.3.0", + "wildmatch", + "winapi", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -2364,9 +3183,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" +checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" dependencies = [ "proc-macro2", "quote", @@ -2375,9 +3194,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "glob" @@ -2400,9 +3219,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c4a8d6391675c6b2ee1a6c8d06e8e2d03605c44cec1270675985a4c2a5500b" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" dependencies = [ "futures-channel", "futures-core", @@ -2411,30 +3230,22 @@ dependencies = [ ] [[package]] -name = "group-example" -version = "0.1.0" +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "cyfs-base", - "cyfs-bdt", - "cyfs-chunk-lib", - "cyfs-core", - "cyfs-debug", - "cyfs-group", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-stack", - "futures", - "lazy_static", - "log 0.4.17", - "prost 0.11.5", - "protobuf", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", + "bytes 1.2.1", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util 0.7.4", + "tracing", ] [[package]] @@ -2449,6 +3260,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -2500,15 +3326,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - [[package]] name = "hex" version = "0.4.3" @@ -2525,6 +3342,12 @@ dependencies = [ "proc-macro-hack 0.4.3", ] +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hex-literal-impl" version = "0.1.2" @@ -2590,7 +3413,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -2604,15 +3427,37 @@ dependencies = [ "hmac 0.7.1", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", "fnv", - "itoa 1.0.5", + "itoa 1.0.4", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes 1.2.1", + "http", + "pin-project-lite 0.2.9", ] [[package]] @@ -2668,6 +3513,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + [[package]] name = "hyper" version = "0.10.16" @@ -2680,13 +3531,50 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time 0.1.45", + "time 0.1.44", "traitobject", "typeable", "unicase 1.4.2", "url 1.7.2", ] +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes 1.2.1", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.4", + "pin-project-lite 0.2.9", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyperlocal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +dependencies = [ + "futures-util", + "hex", + "hyper 0.14.20", + "pin-project", + "tokio", +] + [[package]] name = "iana-time-zone" version = "0.1.51" @@ -2711,6 +3599,12 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.1.5" @@ -2733,6 +3627,20 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "impl-codec" version = "0.5.1" @@ -2742,6 +3650,24 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -2755,9 +3681,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -2770,7 +3696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" dependencies = [ "indoc-impl", - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", ] [[package]] @@ -2779,7 +3705,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", "proc-macro2", "quote", "syn", @@ -2878,9 +3804,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jni" @@ -2920,6 +3846,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2944,6 +3876,28 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lettre" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eabca5e0b4d0e98e7f2243fb5b7520b6af2b65d8f87bcc86f2c75185a6ff243" +dependencies = [ + "base64 0.13.1", + "email-encoding", + "email_address", + "fastrand", + "futures-util", + "hostname", + "httpdate", + "idna 0.2.1", + "mime 0.3.16", + "native-tls", + "nom 7.1.1", + "once_cell", + "quoted_printable", + "socket2", +] + [[package]] name = "lexical-core" version = "0.7.6" @@ -2959,9 +3913,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.139" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libm" @@ -2998,9 +3952,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" dependencies = [ "cc", ] @@ -3063,6 +4017,22 @@ version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd" +[[package]] +name = "mac_address" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" +dependencies = [ + "nix 0.23.1", + "winapi", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matches" version = "0.1.9" @@ -3105,21 +4075,29 @@ dependencies = [ "autocfg 1.1.0", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "memzero" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93c0d11ac30a033511ae414355d80f70d9f29a44a49140face477117a1ee90db" +[[package]] +name = "meta-stat" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-meta", + "log 0.4.17", + "misc-util", + "serde", + "serde_json", + "simple_logger 3.0.0", +] + [[package]] name = "mime" version = "0.2.6" @@ -3135,6 +4113,15 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime-sniffer" +version = "0.1.2" +source = "git+https://github.com/buckyos/rust-mime-sniffer?rev=99c00bba5091810514741bfe0f05d8c9ca244796#99c00bba5091810514741bfe0f05d8c9ca244796" +dependencies = [ + "mime 0.3.16", + "url 1.7.2", +] + [[package]] name = "mime_guess" version = "2.0.4" @@ -3154,7 +4141,7 @@ dependencies = [ "buf-read-ext", "encoding", "httparse", - "hyper", + "hyper 0.10.16", "log 0.4.17", "mime 0.2.6", "tempdir", @@ -3169,7 +4156,16 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ @@ -3179,6 +4175,16 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "misc-util" +version = "0.1.0" +dependencies = [ + "cyfs-base", + "lettre", + "log 0.4.17", + "serde", +] + [[package]] name = "multimap" version = "0.8.3" @@ -3229,27 +4235,27 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.2" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] name = "nix" -version = "0.24.3" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -3325,9 +4331,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" dependencies = [ "byteorder", "lazy_static", @@ -3361,6 +4367,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -3466,29 +4483,29 @@ dependencies = [ ] [[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +name = "ood-installer" +version = "0.5.0" dependencies = [ - "memchr", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "desc-tool", + "futures-util", + "hex", + "log 0.4.17", + "mac_address", + "ood-control", + "ood-daemon", + "os_type", + "qrcode", + "rust-embed", ] -[[package]] -name = "once_cell" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" - [[package]] name = "oorandom" version = "11.1.3" @@ -3509,9 +4526,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.45" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -3541,9 +4558,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.80" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg 1.1.0", "cc", @@ -3552,6 +4569,28 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_type" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24d44c0eea30167516ed8f6daca4b5e3eebcde1bde1e4e6e08b809fb02c7ba5" +dependencies = [ + "regex", +] + +[[package]] +name = "pack-tools" +version = "0.5.0" +dependencies = [ + "clap", + "cyfs-base", + "log 0.4.17", + "sha2 0.8.2", + "simple_logger 2.3.0", + "walkdir", + "zip", +] + [[package]] name = "parity-scale-codec" version = "2.3.1" @@ -3592,7 +4631,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.6", + "parking_lot_core 0.8.5", ] [[package]] @@ -3602,14 +4641,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.4", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", @@ -3621,9 +4660,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", @@ -3650,14 +4689,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", ] [[package]] name = "paste" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "paste-impl" @@ -3665,7 +4704,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", ] [[package]] @@ -3674,7 +4713,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.5", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -3816,18 +4855,37 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pn-miner" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "libc", + "log 0.4.17", + "rusqlite", + "serde", + "serde_json", + "tide", +] + [[package]] name = "polling" -version = "2.5.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "windows-sys 0.42.0", + "winapi", ] [[package]] @@ -3849,9 +4907,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "prettyplease" -version = "0.1.22" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773" +checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" dependencies = [ "proc-macro2", "syn", @@ -3911,6 +4969,8 @@ checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", "uint", ] @@ -3945,9 +5005,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.20+deprecated" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-hack-impl" @@ -3957,9 +5017,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -3970,18 +5030,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.5" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592" +checksum = "c0b18e655c21ff5ac2084a5ad0611e827b3f92badf79f4910b5a5c58f4d87ff0" dependencies = [ - "bytes 1.3.0", - "prost-derive 0.11.5", + "bytes 1.2.1", + "prost-derive 0.11.2", ] [[package]] @@ -3990,7 +5050,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", "heck 0.3.3", "itertools", "lazy_static", @@ -4006,11 +5066,11 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.5" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6" +checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", "heck 0.4.0", "itertools", "lazy_static", @@ -4018,8 +5078,8 @@ dependencies = [ "multimap", "petgraph", "prettyplease", - "prost 0.11.5", - "prost-types 0.11.5", + "prost 0.11.3", + "prost-types 0.11.2", "regex", "syn", "tempfile", @@ -4041,9 +5101,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.5" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720" +checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" dependencies = [ "anyhow", "itertools", @@ -4058,18 +5118,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.5" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091" +checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" dependencies = [ - "bytes 1.3.0", - "prost 0.11.5", + "bytes 1.2.1", + "prost 0.11.3", ] [[package]] @@ -4078,7 +5138,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.3.0", + "bytes 1.2.1", ] [[package]] @@ -4200,6 +5260,16 @@ dependencies = [ "syn", ] +[[package]] +name = "qrcode" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" +dependencies = [ + "checked_int_cast", + "image", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4208,9 +5278,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.23" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -4240,6 +5310,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -4250,7 +5339,7 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc", + "rand_hc 0.2.0", ] [[package]] @@ -4264,6 +5353,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -4317,6 +5416,15 @@ dependencies = [ "getrandom 0.2.8", ] +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -4326,21 +5434,76 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rayon" -version = "1.6.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ + "autocfg 1.1.0", + "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -4450,6 +5613,27 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes 1.2.1", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "route-recognizer" version = "0.2.0" @@ -4485,8 +5669,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", - "digest 0.10.6", - "num-bigint-dig 0.8.2", + "digest 0.10.5", + "num-bigint-dig 0.8.1", "num-integer", "num-iter", "num-traits", @@ -4518,6 +5702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a" dependencies = [ "bitflags", + "chrono", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -4538,6 +5723,40 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rust-embed" +version = "6.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" +dependencies = [ + "sha2 0.10.6", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -4587,15 +5806,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "safemem" @@ -4612,6 +5831,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +dependencies = [ + "cfg-if 1.0.0", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +dependencies = [ + "proc-macro-crate 1.2.1", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "scan_dir" version = "0.3.3" @@ -4639,9 +5882,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" [[package]] name = "sct" @@ -4687,9 +5930,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -4699,9 +5942,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] @@ -4718,9 +5961,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -4738,11 +5981,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" dependencies = [ - "itoa 1.0.5", + "itoa 1.0.4", "ryu", "serde", ] @@ -4765,20 +6008,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.5", + "itoa 1.0.4", "ryu", "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha-1" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -4798,7 +6063,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -4840,7 +6105,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -4852,6 +6117,31 @@ dependencies = [ "cc", ] +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +dependencies = [ + "block-buffer 0.7.3", + "byte-tools", + "digest 0.8.1", + "keccak", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", +] + [[package]] name = "shared_memory" version = "0.12.4" @@ -4861,7 +6151,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.17", - "nix 0.23.2", + "nix 0.23.1", "rand 0.8.5", "win-sys", ] @@ -4918,6 +6208,32 @@ dependencies = [ "winapi", ] +[[package]] +name = "simple_logger" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc20708d703a44b96b3b700578a85b6fe887fc63ab20315757026bb8a12faaad" +dependencies = [ + "atty", + "colored", + "log 0.4.17", + "time 0.3.16", + "winapi", +] + +[[package]] +name = "simple_logger" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" +dependencies = [ + "atty", + "colored", + "log 0.4.17", + "time 0.3.16", + "windows-sys 0.42.0", +] + [[package]] name = "slab" version = "0.4.7" @@ -4942,6 +6258,47 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "sn-miner-rust" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", +] + +[[package]] +name = "sn-online-test" +version = "0.1.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-util", + "log 0.4.17", + "rand 0.7.3", + "simple_logger 4.0.0", +] + +[[package]] +name = "sn-updater" +version = "0.1.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "log 0.4.17", + "simple_logger 4.0.0", +] + [[package]] name = "socket2" version = "0.4.7" @@ -5008,10 +6365,11 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.3.0", + "bytes 1.2.1", + "chrono", "crc", "crossbeam-queue", - "digest 0.10.6", + "digest 0.10.5", "either", "event-listener", "flume", @@ -5024,14 +6382,14 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.5", + "itoa 1.0.4", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "num-bigint 0.3.3", "once_cell", - "paste 1.0.11", + "paste 1.0.9", "percent-encoding 2.2.0", "rand 0.8.5", "rsa 0.6.1", @@ -5159,6 +6517,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "1.0.0" @@ -5204,9 +6568,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -5227,9 +6591,24 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.8" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade661fa5e048ada64ad7901713301c21d2dbc5b65ee7967de8826c111452960" +dependencies = [ + "cfg-if 1.0.0", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + +[[package]] +name = "sysinfo" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6" +checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -5246,6 +6625,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -5311,18 +6701,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -5372,9 +6762,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -5402,7 +6792,7 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" dependencies = [ - "itoa 1.0.5", + "itoa 1.0.4", "libc", "num_threads", "serde", @@ -5422,7 +6812,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", "time-macros-impl", ] @@ -5441,7 +6831,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", "proc-macro2", "quote", "standback", @@ -5457,6 +6847,15 @@ dependencies = [ "chrono", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5469,31 +6868,125 @@ dependencies = [ [[package]] name = "tokio" -version = "1.23.0" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg 1.1.0", + "bytes 1.2.1", + "libc", + "memchr", + "mio", + "num_cpus", "pin-project-lite 0.2.9", - "windows-sys 0.42.0", + "socket2", + "winapi", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes 1.2.1", + "futures-core", + "futures-sink", + "log 0.4.17", + "pin-project-lite 0.2.9", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes 1.2.1", + "futures-core", + "futures-sink", + "pin-project-lite 0.2.9", + "tokio", + "tracing", ] [[package]] name = "toml" -version = "0.5.10" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "indexmap", "serde", ] +[[package]] +name = "toml_datetime" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" + +[[package]] +name = "toml_edit" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646" +dependencies = [ + "combine", + "indexmap", + "itertools", + "toml_datetime", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +dependencies = [ + "cfg-if 1.0.0", + "pin-project-lite 0.2.9", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + [[package]] name = "traitobject" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" +dependencies = [ + "hash-db", + "rlp", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "tungstenite" version = "0.17.3" @@ -5502,7 +6995,7 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.3.0", + "bytes 1.2.1", "http", "httparse", "log 0.4.17", @@ -5521,15 +7014,15 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.16.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "uint" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" dependencies = [ "byteorder", "crunchy", @@ -5563,9 +7056,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" @@ -5602,9 +7095,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unindent" -version = "0.1.11" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" [[package]] name = "universal-hash" @@ -5677,6 +7170,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version-compare" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" + [[package]] name = "version_check" version = "0.1.5" @@ -5689,6 +7188,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.0" @@ -5706,6 +7214,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log 0.4.17", + "try-lock", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -5856,6 +7374,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +[[package]] +name = "wildmatch" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" + [[package]] name = "win-sys" version = "0.3.1" @@ -6045,6 +7569,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] + [[package]] name = "zeroize" version = "1.5.7" @@ -6056,9 +7589,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.3" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", @@ -6086,6 +7619,56 @@ dependencies = [ "zstd", ] +[[package]] +name = "zone-simulator" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "bip39", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "lazy_static", + "log 0.4.17", + "once_cell", + "rand 0.7.3", +] + +[[package]] +name = "zone-stack" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "bip39", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "log 0.4.17", + "rand 0.8.5", + "serde", + "serde_json", + "toml", + "zone-simulator", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" @@ -6107,9 +7690,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.4+zstd.1.5.2" +version = "2.0.1+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" +checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" dependencies = [ "cc", "libc", diff --git a/src/service/app-manager/Cargo.toml b/src/service/app-manager/Cargo.toml index 54302f69e..64779058a 100644 --- a/src/service/app-manager/Cargo.toml +++ b/src/service/app-manager/Cargo.toml @@ -46,4 +46,5 @@ app-manager-lib = { path = "../app-manager-lib" } toml = "0.5" clap = '2.34.0' wait-timeout = '0.2.0' -once_cell = "1.17.0" \ No newline at end of file +once_cell = "1.17.0" +surf = { version = '2.3.2', default-features = false, features = ['h1-client-rustls'] } \ No newline at end of file diff --git a/src/service/app-manager/src/app_controller.rs b/src/service/app-manager/src/app_controller.rs index 156b6a400..716a4b43b 100644 --- a/src/service/app-manager/src/app_controller.rs +++ b/src/service/app-manager/src/app_controller.rs @@ -177,6 +177,7 @@ impl AppController { file_id: None, dirs: None, access: None, + chunk_method: TransPublishChunkMethod::Track, }) .await .map_err(|e| { diff --git a/src/service/app-manager/src/non_helper.rs b/src/service/app-manager/src/non_helper.rs index 3fbdf4fd2..6af488071 100644 --- a/src/service/app-manager/src/non_helper.rs +++ b/src/service/app-manager/src/non_helper.rs @@ -3,6 +3,7 @@ use cyfs_base::*; use cyfs_core::*; use cyfs_lib::*; use log::*; +use serde::Serialize; const APP_MAIN_PATH: &str = "/app"; @@ -72,6 +73,52 @@ impl NonHelper { return Err(e); } + // 上报到ood-daemon + /* + { + "auto_update": true, + "id": "9tGpLNnDwJ1nReZqJgWev5eoe23ygViGDC4idnCK1Dy5", + "name": "app-manager", + "process_state": "Run", + "version": "1.0.0.713" + } + */ + #[derive(Serialize)] + struct AppStatusInfo { + pub auto_update: bool, + pub id: DecAppId, + pub name: String, + pub process_state: String, + pub version: String + } + impl From<&AppLocalStatus> for AppStatusInfo { + fn from(value: &AppLocalStatus) -> Self { + Self { + auto_update: value.auto_update(), + id: value.app_id().clone(), + name: "unknown".to_string(), + process_state: value.status().to_string(), + version: value.version().unwrap_or("unknown").to_owned(), + } + } + } + + let mut info = AppStatusInfo::from(status); + let stack = self.shared_stack.clone(); + async_std::task::spawn(async move { + let app_id = info.id.object_id(); + if let Ok(resp) = stack + .non_service() + .get_object(NONGetObjectRequest::new_noc(app_id.clone(), None)) + .await { + if let Ok(app) = DecApp::clone_from_slice(&resp.object.object_raw) { + info.name = app.name().to_owned(); + } + } + + let _ = surf::post(format!("http://127.0.0.1:{}/service_status/{}", OOD_DAEMON_LOCAL_STATUS_PORT, &app_id)).body(serde_json::to_value(info).unwrap()).send().await; + }); + Ok(()) } @@ -433,20 +480,11 @@ impl NonHelper { target: Option, flag: u32, ) -> BuckyResult { + let mut req = NONGetObjectRequest::new_router(target, obj_id.clone(), None); + req.common.flags = flag; self.shared_stack .non_service() - .get_object(NONGetObjectRequest { - common: NONOutputRequestCommon { - req_path: None, - source: None, - dec_id: None, - level: NONAPILevel::Router, - target, - flags: flag, - }, - object_id: obj_id.clone(), - inner_path: None, - }) + .get_object(req) .await } From c76a799f79caaba11cfc380ed5eafc17290df93d Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 17 Feb 2023 15:51:29 +0800 Subject: [PATCH 108/553] Fix meta-stat email format --- src/meta/meta-stat/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/meta-stat/src/main.rs b/src/meta/meta-stat/src/main.rs index 9302782b2..17f90ec25 100644 --- a/src/meta/meta-stat/src/main.rs +++ b/src/meta/meta-stat/src/main.rs @@ -65,7 +65,7 @@ async fn main() -> BuckyResult<()> { println!("reporting..."); if let Some(config) = config.email { let subject = format!("{} Meta Chain Stat {}", cyfs_base::get_channel().to_string(), chrono::Local::today().format("%F")); - let _ = send_mail(config, subject, output.replace("\n", "
")).await.map_err(|e| { + let _ = send_mail(config, subject, output).await.map_err(|e| { error!("send mail err {}", e); e }); From 4af76e42d7a18ebaf29ac48df5b5f36431bde7ce Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 17 Feb 2023 16:04:32 +0800 Subject: [PATCH 109/553] Add version output in process alive check log --- src/component/cyfs-debug/src/check/dead.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/cyfs-debug/src/check/dead.rs b/src/component/cyfs-debug/src/check/dead.rs index 494e64ecf..39dd5bf3b 100644 --- a/src/component/cyfs-debug/src/check/dead.rs +++ b/src/component/cyfs-debug/src/check/dead.rs @@ -142,7 +142,7 @@ impl ProcessDeadHelper { let this = self.clone(); std::thread::spawn(move || loop { std::thread::sleep(dur); - info!("process still alive {:?}", std::thread::current().id(),); + info!("process still alive {:?}, {}", std::thread::current().id(), cyfs_base::get_version()); this.check_task_alive(); }); } From 9dc8569a0f6f7ac3d8342475b12ee377dd320796 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 17 Feb 2023 17:18:20 +0800 Subject: [PATCH 110/553] OOD-daemon will now report an error and exit if it fails to load the repo --- src/component/cyfs-base/src/base/error.rs | 7 +++++++ src/service/ood-daemon/src/main.rs | 5 +++-- src/service/ood-daemon/src/repo/manager.rs | 17 +++++++++++------ src/service/ood-daemon/src/repo/named_data.rs | 5 ++--- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/component/cyfs-base/src/base/error.rs b/src/component/cyfs-base/src/base/error.rs index 1d6a95d70..6916ca56e 100644 --- a/src/component/cyfs-base/src/base/error.rs +++ b/src/component/cyfs-base/src/base/error.rs @@ -450,6 +450,13 @@ impl Into for BuckyErrorCode { } } +impl Into for BuckyErrorCode { + fn into(self) -> i32 { + let v: u16 = self.into(); + v as i32 + } +} + impl Into for BuckyErrorCode { fn into(self) -> u16 { match self { diff --git a/src/service/ood-daemon/src/main.rs b/src/service/ood-daemon/src/main.rs index 2cd2a9ca8..5ad479cd4 100644 --- a/src/service/ood-daemon/src/main.rs +++ b/src/service/ood-daemon/src/main.rs @@ -1,4 +1,4 @@ -#![windows_subsystem = "windows"] +// #![windows_subsystem = "windows"] mod config; mod config_repo; @@ -167,7 +167,7 @@ async fn main_run() { if !no_ood_control { if let Err(e) = start_control(mode.clone(), &matches).await { println!("start ood control failed! {}", e); - std::process::exit(-1); + std::process::exit(e.code().into()); } } else { info!("will run without ood control service"); @@ -176,6 +176,7 @@ async fn main_run() { let daemon = Daemon::new(mode, no_monitor); if let Err(e) = daemon.run().await { error!("daemon run error! err={}", e); + std::process::exit(e.code().into()); } } diff --git a/src/service/ood-daemon/src/repo/manager.rs b/src/service/ood-daemon/src/repo/manager.rs index 59947af5c..4a2eea432 100644 --- a/src/service/ood-daemon/src/repo/manager.rs +++ b/src/service/ood-daemon/src/repo/manager.rs @@ -119,6 +119,12 @@ impl RepoManager { pub async fn fetch_service(&self, fid: &str) -> BuckyResult { let repo_list = self.repo_list.lock().unwrap().clone(); + if repo_list.is_empty() { + let msg = format!("fetch service but repo list is empty! fid={}", fid); + warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotSupport, msg)); + } + let cache_dir = self.cache_dir.clone(); let fid = fid.to_owned(); @@ -222,13 +228,12 @@ impl RepoManager { for item in repo_node.iter() { info!("new repo item: {:?}", item); if let toml::Value::Table(m) = item { - let ret = Self::load_repo_item(&m).await; - if !ret.is_ok() { - continue; - } - - let repo = ret.unwrap(); + let repo = Self::load_repo_item(&m).await?; self.repo_list.lock().unwrap().push(Arc::new(repo)); + } else { + let msg = format!("unsupport repo item format!"); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::UnSupport, msg)); } } diff --git a/src/service/ood-daemon/src/repo/named_data.rs b/src/service/ood-daemon/src/repo/named_data.rs index 82732d604..149e5be60 100644 --- a/src/service/ood-daemon/src/repo/named_data.rs +++ b/src/service/ood-daemon/src/repo/named_data.rs @@ -17,7 +17,7 @@ pub struct NamedDataRepo { impl NamedDataRepo { pub async fn new() -> BuckyResult { - let mut repo = NamedDataRepo { + let repo = NamedDataRepo { client: OnceCell::new(), }; @@ -27,8 +27,7 @@ impl NamedDataRepo { } } - pub async fn init(&mut self) -> BuckyResult<()> { - + pub async fn init(&self) -> BuckyResult<()> { // service desc确保它有固定外网地址,连接不走sn。这里sn_list就可以传None let mut config = NamedCacheClientConfig::default(); From c2c164ae5091077a4e28504a9b0edc0d2f7541ce Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 17 Feb 2023 18:38:33 +0800 Subject: [PATCH 111/553] Improve the object layer strategy detection of after pass the first layer rpath access verification --- src/component/cyfs-lib/src/base/source.rs | 89 ++++++++++++++++++++++- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/component/cyfs-lib/src/base/source.rs b/src/component/cyfs-lib/src/base/source.rs index 74663703b..f5c525d2b 100644 --- a/src/component/cyfs-lib/src/base/source.rs +++ b/src/component/cyfs-lib/src/base/source.rs @@ -365,6 +365,10 @@ impl RequestSourceInfo { } } + pub fn is_fuzzy_verified(&self) -> bool { + self.verified.is_some() + } + pub fn check_target_dec_permission(&self, op_target_dec: &Option) -> bool { self.check_target_dec_permission2(op_target_dec.as_ref()) } @@ -404,17 +408,32 @@ impl RequestSourceInfo { self.dec == *dec } - pub fn mask(&self, dec_id: &ObjectId, permissions: impl Into) -> u32 { + pub fn mask(&self, own_dec_id: &ObjectId, permissions: impl Into) -> u32 { let permissions = permissions.into(); let mut access = AccessString::new(0); - if self.dec == *dec_id { + if self.dec == *own_dec_id { access.set_group_permissions(AccessGroup::OwnerDec, permissions); } else { access.set_group_permissions(AccessGroup::OthersDec, permissions); } - let group = self.zone.zone_category.into(); - access.set_group_permissions(group, permissions); + /* + A and B two dec + A creates objX, the permission is the default permission, that is, B in the same zone can access + B After obtaining the ID of objX, configure the rpath permission so that objX can be accessed outside the zone + + The key point here is that this behavior is inevitable. As long as B can access the obj, + it is theoretically impossible to prevent B from spreading the obj out of the zone? + So if other dec is allowed to access in the same zone at the object level access(Only true at the object access layer), + it can be allowed + */ + if self.is_fuzzy_verified() { + access.set_group_permissions(AccessGroup::CurrentDevice, permissions); + access.set_group_permissions(AccessGroup::CurrentZone, permissions); + } else { + let group = self.zone.zone_category.into(); + access.set_group_permissions(group, permissions); + } access.value() } @@ -569,4 +588,66 @@ mod test { let default = AccessString::default().value(); assert_ne!(default & mask, mask) } + + #[test] + fn test_verified() { + let owner = ObjectId::default(); + let dec_a = cyfs_core::DecApp::generate_id(owner.clone(), "dec-a"); + let dec_b = cyfs_core::DecApp::generate_id(owner.clone(), "dec-b"); + + let source = RequestSourceInfo { + zone: DeviceZoneInfo { + device: None, + zone: None, + zone_category: DeviceZoneCategory::OtherZone, + }, + dec: dec_a.clone(), + protocol: RequestProtocol::HttpBdt, + verified: None, + }; + + { + let mut source = source.clone(); + let object_access = AccessString::default().value(); + + let mask = source.mask(&dec_b, RequestOpType::Read); + assert_ne!(object_access & mask, mask); + + source.set_verified(dec_a); + let mask = source.mask(&dec_b, RequestOpType::Read); + assert_eq!(object_access & mask, mask); + } + + { + let mut source = source.clone(); + + // remove other dec access + let mut access = AccessString::default(); + access.clear_group_permissions(AccessGroup::OthersDec); + let object_access = access.value(); + + let mask = source.mask(&dec_b, RequestOpType::Read); + assert_ne!(object_access & mask, mask); + + source.set_verified(dec_a); + let mask = source.mask(&dec_b, RequestOpType::Read); + assert_ne!(object_access & mask, mask); + } + + { + let mut source = source.clone(); + + // remove other dec access + let mut access = AccessString::default(); + access.clear_group_permissions(AccessGroup::CurrentZone); + let object_access = access.value(); + + let mask = source.mask(&dec_b, RequestOpType::Read); + assert_ne!(object_access & mask, mask); + + source.set_verified(dec_a); + let mask = source.mask(&dec_b, RequestOpType::Read); + assert_ne!(object_access & mask, mask); + } + } } From 59d24824a31b7284b288fc619d2161c150773a7a Mon Sep 17 00:00:00 2001 From: tsukasa Date: Fri, 17 Feb 2023 19:55:34 +0800 Subject: [PATCH 112/553] Fix: tcp not update active time when recv packet --- src/component/cyfs-bdt/src/tunnel/tcp.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/component/cyfs-bdt/src/tunnel/tcp.rs b/src/component/cyfs-bdt/src/tunnel/tcp.rs index 96df5eb82..d747619f6 100644 --- a/src/component/cyfs-bdt/src/tunnel/tcp.rs +++ b/src/component/cyfs-bdt/src/tunnel/tcp.rs @@ -847,8 +847,7 @@ impl Tunnel { // tunnel显式销毁时,需要shutdown tcp stream; 这里receive_package就会出错了 match interface.receive_package(&mut recv_buf).await { Ok(recv_box) => { - // tunnel.0.last_active.store(bucky_time_now(), Ordering::SeqCst); - + tunnel.0.last_active.store(bucky_time_now(), Ordering::SeqCst); match recv_box { RecvBox::Package(package_box) => { let stack = owner.stack(); From d7e0e01a209e2934fc8b0629856d9b435988f957 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 17 Feb 2023 20:12:49 +0800 Subject: [PATCH 113/553] Set docker api timeout to 300s --- src/service/app-manager/src/docker_api.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/service/app-manager/src/docker_api.rs b/src/service/app-manager/src/docker_api.rs index faa8b3b0b..0d87177a6 100644 --- a/src/service/app-manager/src/docker_api.rs +++ b/src/service/app-manager/src/docker_api.rs @@ -1,4 +1,4 @@ -use bollard::Docker; +use bollard::{API_DEFAULT_VERSION, Docker}; use cyfs_base::*; use cyfs_util::*; use flate2::write::GzEncoder; @@ -287,8 +287,12 @@ pub struct DockerApi { impl DockerApi { pub fn new() -> DockerApi { - let docker = Docker::connect_with_socket_defaults().unwrap(); - DockerApi { docker: docker } + #[cfg(unix)] + let path = "unix:///var/run/docker.sock"; + #[cfg(windows)] + let path = "npipe:////./pipe/docker_engine"; + let docker = Docker::connect_with_socket(path, 300, API_DEFAULT_VERSION).unwrap(); + DockerApi { docker } } /// # get_network_id From c95a7841226003924763aed27ebdb663093eb6c5 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 20 Feb 2023 20:12:15 +0800 Subject: [PATCH 114/553] Email Sender support starttls --- src/misc/misc-util/src/mail.rs | 40 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/misc/misc-util/src/mail.rs b/src/misc/misc-util/src/mail.rs index fdd886cb8..5d1e10821 100644 --- a/src/misc/misc-util/src/mail.rs +++ b/src/misc/misc-util/src/mail.rs @@ -6,12 +6,45 @@ use serde::Deserialize; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult}; use log::*; +#[derive(Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum SmtpType { + TLS, + STARTTLS +} + +impl Default for SmtpType { + fn default() -> Self { + Self::STARTTLS + } +} + #[derive(Deserialize)] pub struct EmailConfig { receiver: String, sender: String, smtp_server: String, password: String, + #[serde(default)] + smtp_type: SmtpType +} + +impl EmailConfig { + fn transport(&self) -> SmtpTransport { + match self.smtp_type { + SmtpType::TLS => { + info!("send email use tls/ssl {}", &self.smtp_server); + SmtpTransport::relay(&self.smtp_server) + } + SmtpType::STARTTLS => { + info!("send email use starttls {}", &self.smtp_server); + SmtpTransport::starttls_relay(&self.smtp_server) + } + }.unwrap().credentials(Credentials::new( + self.sender.clone(), + self.password.clone(), + )).build() + } } pub async fn send_mail(config: EmailConfig, subject: String, output_html: String) -> BuckyResult<()> { @@ -24,12 +57,7 @@ pub async fn send_mail(config: EmailConfig, subject: String, output_html: String .unwrap(); // Open connection to Gmail - if let Err(e) = SmtpTransport::relay(&config.smtp_server) - .unwrap() - .credentials(Credentials::new( - config.sender, - config.password, - )).build().send(&mail) { + if let Err(e) = config.transport().send(&mail) { error!("Could not send email: {:?}", e); return Err(BuckyError::new(BuckyErrorCode::Failed, e.to_string())); } From f572d6bff81cf660b6217b154829049a5a6068aa Mon Sep 17 00:00:00 2001 From: tsukasa Date: Tue, 21 Feb 2023 14:28:03 +0800 Subject: [PATCH 115/553] Modify: add some statistic logs for ndn --- src/component/cyfs-bdt/src/ndn/channel/manager.rs | 15 +++++++++++++++ .../cyfs-bdt/src/ndn/chunk/cache/cache.rs | 15 ++++++++++++++- src/component/cyfs-bdt/src/ndn/chunk/download.rs | 10 +++++++++- src/component/cyfs-bdt/src/ndn/chunk/manager.rs | 10 +++++++++- src/component/cyfs-bdt/src/ndn/download/chunk.rs | 4 ++++ .../cyfs-bdt/src/ndn/download/chunk_list.rs | 4 ++++ src/component/cyfs-bdt/src/stack.rs | 7 +++++-- 7 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-bdt/src/ndn/channel/manager.rs b/src/component/cyfs-bdt/src/ndn/channel/manager.rs index 858b56108..f1b63c071 100644 --- a/src/component/cyfs-bdt/src/ndn/channel/manager.rs +++ b/src/component/cyfs-bdt/src/ndn/channel/manager.rs @@ -99,6 +99,21 @@ impl ChannelManager { manager } + + pub(crate) fn on_statistic(&self) -> String { + let mut channels = self.0.channels.write().unwrap(); + let mut download_session_count = 0; + let mut upload_session_count = 0; + let mut channel_count = 0; + for (_, guard) in &mut channels.entries { + channel_count += 1; + download_session_count += guard.channel.download_session_count(); + upload_session_count += guard.channel.upload_session_count(); + } + + format!("ChannelCount: {}, UploadSessionCount:{}, DownloadSessionCount:{}", channel_count, upload_session_count, download_session_count) + } + pub fn channel_of(&self, remote: &DeviceId) -> Option { self.0.channels.read().unwrap().entries.get(remote).map(|guard| guard.get()) } diff --git a/src/component/cyfs-bdt/src/ndn/chunk/cache/cache.rs b/src/component/cyfs-bdt/src/ndn/chunk/cache/cache.rs index b8684c3c5..9a6a5245b 100644 --- a/src/component/cyfs-bdt/src/ndn/chunk/cache/cache.rs +++ b/src/component/cyfs-bdt/src/ndn/chunk/cache/cache.rs @@ -39,6 +39,19 @@ struct CacheImpl { pub struct ChunkCache(Arc); +impl std::fmt::Display for CacheImpl { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ChunkCache{{chunk:{}}}", self.chunk) + } +} + +impl Drop for CacheImpl { + fn drop(&mut self) { + info!("{} released", self); + } +} + + pub struct WeakChunkCache(Weak); impl WeakChunkCache { @@ -56,7 +69,7 @@ impl ChunkCache { impl std::fmt::Display for ChunkCache { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "ChunkCache{{chunk:{}}}", self.chunk()) + write!(f, "{}", self.0) } } diff --git a/src/component/cyfs-bdt/src/ndn/chunk/download.rs b/src/component/cyfs-bdt/src/ndn/chunk/download.rs index 7f0871fcf..d11d80a8f 100644 --- a/src/component/cyfs-bdt/src/ndn/chunk/download.rs +++ b/src/component/cyfs-bdt/src/ndn/chunk/download.rs @@ -244,6 +244,12 @@ struct ChunkDowloaderImpl { state: RwLock, } +impl std::fmt::Display for ChunkDowloaderImpl { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ChunkDownloader{{chunk:{}}}", self.cache.chunk()) + } +} + #[derive(Clone)] pub struct ChunkDownloader(Arc); @@ -258,6 +264,7 @@ impl Drop for ChunkDowloaderImpl { }; if let Some(session) = session { + info!("{} canceled for drop", self); session.cancel_by_error(BuckyError::new(BuckyErrorCode::UserCanceled, "user canceled")); } } @@ -280,7 +287,7 @@ impl ChunkDownloader { impl std::fmt::Display for ChunkDownloader { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "ChunkDownloader{{chunk:{}}}", self.chunk()) + write!(f, "{}", self.0) } } @@ -408,6 +415,7 @@ impl ChunkDownloader { async fn sync_finished(&self) { if self.cache().wait_exists(0..self.cache().chunk().len(), || self.owner().wait_user_canceled()).await.is_ok() { + info!("{} finished", self); let state = &mut *self.0.state.write().unwrap(); *state = StateImpl::Finished; } diff --git a/src/component/cyfs-bdt/src/ndn/chunk/manager.rs b/src/component/cyfs-bdt/src/ndn/chunk/manager.rs index 76f6bcc01..13ac93dd5 100644 --- a/src/component/cyfs-bdt/src/ndn/chunk/manager.rs +++ b/src/component/cyfs-bdt/src/ndn/chunk/manager.rs @@ -122,6 +122,11 @@ impl ChunkManager { } } + pub(crate) fn on_statistic(&self) -> String { + let caches = self.caches.lock().unwrap(); + format!("ChunkCacheCount:{}", caches.len()) + } + pub fn store(&self) -> &dyn ChunkReader { self.store.as_ref() } @@ -139,6 +144,7 @@ impl ChunkManager { caches.remove(chunk); } let cache = ChunkCache::new(self.stack.clone(), chunk.clone()); + info!("{} create new cache {}", self, cache); caches.insert(chunk.clone(), cache.to_weak()); cache } @@ -146,7 +152,9 @@ impl ChunkManager { pub fn create_downloader(&self, chunk: &ChunkId, task: Box) -> ChunkDownloader { let cache = self.create_cache(chunk); let mut downloaders = self.downloaders.lock().unwrap(); - downloaders.create_downloader(&self.stack, cache, task) + let downloader = downloaders.create_downloader(&self.stack, cache, task); + info!("{} create new downloader {}", self, downloader); + downloader } pub(in super::super) fn on_schedule(&self, _now: Timestamp) { diff --git a/src/component/cyfs-bdt/src/ndn/download/chunk.rs b/src/component/cyfs-bdt/src/ndn/download/chunk.rs index d0d900f21..bba684ad9 100644 --- a/src/component/cyfs-bdt/src/ndn/download/chunk.rs +++ b/src/component/cyfs-bdt/src/ndn/download/chunk.rs @@ -109,6 +109,7 @@ impl LeafDownloadTask for ChunkTask { match &state.task_state { TaskStateImpl::Downloading(_) => { + info!("{} mark finished", self); state.task_state = TaskStateImpl::Finished; }, _ => {} @@ -191,6 +192,7 @@ impl NdnTask for ChunkTask { match &state.task_state { TaskStateImpl::Downloading(_) => { + info!("{} cancel by err {}", self, err); state.task_state = TaskStateImpl::Error(err); }, _ => {} @@ -276,8 +278,10 @@ impl ChunkTaskReader { impl Drop for ChunkTaskReader { fn drop(&mut self) { if self.0.offset() == self.0.cache().chunk().len() { + info!("{} drop after finished", self.0); self.0.task().finish(); } else { + info!("{} drop before finished", self.0); let _ = self.0.task().cancel(); } } diff --git a/src/component/cyfs-bdt/src/ndn/download/chunk_list.rs b/src/component/cyfs-bdt/src/ndn/download/chunk_list.rs index 6f3b0be44..4b2557b16 100644 --- a/src/component/cyfs-bdt/src/ndn/download/chunk_list.rs +++ b/src/component/cyfs-bdt/src/ndn/download/chunk_list.rs @@ -148,6 +148,7 @@ impl LeafDownloadTask for ChunkListTask { match &mut state.task_state { TaskStateImpl::Downloading(downloading) => { + info!("{} mark finished", self); downloading.downloaded += downloading.cur_chunk.0.cache().stream().len() as u64; state.task_state = TaskStateImpl::Finished(downloading.downloaded); }, @@ -217,6 +218,7 @@ impl NdnTask for ChunkListTask { match &state.task_state { TaskStateImpl::Downloading(_) => { + info!("{} cancel by err {}", self, err); state.task_state = TaskStateImpl::Error(err); }, _ => {} @@ -297,8 +299,10 @@ impl ChunkListTaskReader { impl Drop for ChunkListTaskReader { fn drop(&mut self) { if self.offset == self.task.chunk_list().total_len() { + info!("{} drop after finished", self.task()); self.task.finish(); } else { + info!("{} drop before finished", self.task()); let _ = self.task.cancel(); } } diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index e61f4e92f..1d038f7af 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -389,10 +389,13 @@ impl Stack { let arc_stack = stack.clone(); task::spawn(async move { loop { - info!("{} statistic: {}, {}", + info!("{} statistic: {}, {}, {}, {}", arc_stack, arc_stack.tunnel_manager().on_statistic(), - arc_stack.stream_manager().on_statistic()); + arc_stack.stream_manager().on_statistic(), + arc_stack.ndn().channel_manager().on_statistic(), + arc_stack.ndn().chunk_manager().on_statistic() + ); let _ = future::timeout(arc_stack.config().statistic_interval, future::pending::<()>()).await; } }); From cf7dc11af0f37a63bb9fccf595beeeec5c22e5b1 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Tue, 21 Feb 2023 15:25:15 +0800 Subject: [PATCH 116/553] Modify: add some statistic logs for ndn --- .../cyfs-bdt/src/ndn/channel/manager.rs | 4 ++-- .../src/ndn/chunk/cache/raw_cache/manager.rs | 17 ++++++++++++++++- .../cyfs-bdt/src/ndn/chunk/cache/stream.rs | 13 ++++++++++++- .../cyfs-bdt/src/ndn/chunk/manager.rs | 19 ++++++++++++++++--- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-bdt/src/ndn/channel/manager.rs b/src/component/cyfs-bdt/src/ndn/channel/manager.rs index f1b63c071..56430b58a 100644 --- a/src/component/cyfs-bdt/src/ndn/channel/manager.rs +++ b/src/component/cyfs-bdt/src/ndn/channel/manager.rs @@ -101,11 +101,11 @@ impl ChannelManager { pub(crate) fn on_statistic(&self) -> String { - let mut channels = self.0.channels.write().unwrap(); + let channels = self.0.channels.read().unwrap(); let mut download_session_count = 0; let mut upload_session_count = 0; let mut channel_count = 0; - for (_, guard) in &mut channels.entries { + for (_, guard) in &channels.entries { channel_count += 1; download_session_count += guard.channel.download_session_count(); upload_session_count += guard.channel.upload_session_count(); diff --git a/src/component/cyfs-bdt/src/ndn/chunk/cache/raw_cache/manager.rs b/src/component/cyfs-bdt/src/ndn/chunk/cache/raw_cache/manager.rs index 11b7f2ebf..60f9008ec 100644 --- a/src/component/cyfs-bdt/src/ndn/chunk/cache/raw_cache/manager.rs +++ b/src/component/cyfs-bdt/src/ndn/chunk/cache/raw_cache/manager.rs @@ -1,6 +1,7 @@ use std::{ sync::{Arc, RwLock} }; +use cyfs_base::*; use super::{ common::*, mem::* @@ -12,16 +13,24 @@ struct ManagerState { } struct ManagerImpl { + local: DeviceId, config: RawCacheConfig, state: RwLock } +impl std::fmt::Display for RawCacheManager { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "RawCache{{local:{}}}", self.0.local) + } +} + #[derive(Clone)] pub struct RawCacheManager(Arc); impl RawCacheManager { - pub fn new(config: RawCacheConfig) -> Self { + pub fn new(local: DeviceId, config: RawCacheConfig) -> Self { Self(Arc::new(ManagerImpl { + local, config, state: RwLock::new(ManagerState { total_mem: 0 @@ -38,12 +47,18 @@ impl RawCacheManager { self.alloc_mem(capacity) } + pub fn used_mem(&self) -> u64 { + self.0.state.read().unwrap().total_mem + } + pub fn alloc_mem(&self, capacity: usize) -> Box { + info!("{} alloc raw cache {}", self, capacity); self.0.state.write().unwrap().total_mem += capacity as u64; MemCache::new(capacity, Some(self.clone())).clone_as_raw_cache() } pub(super) fn release_mem(&self, capacity: usize) { + info!("{} release raw cache {}", self, capacity); self.0.state.write().unwrap().total_mem -= capacity as u64; } } \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/ndn/chunk/cache/stream.rs b/src/component/cyfs-bdt/src/ndn/chunk/cache/stream.rs index 011f9750a..625380ffb 100644 --- a/src/component/cyfs-bdt/src/ndn/chunk/cache/stream.rs +++ b/src/component/cyfs-bdt/src/ndn/chunk/cache/stream.rs @@ -39,10 +39,21 @@ struct CacheImpl { #[derive(Clone)] pub struct ChunkStreamCache(Arc); +impl std::fmt::Display for CacheImpl { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ChunkStreamCache{{chunk:{}}}", self.chunk) + } +} + +impl Drop for CacheImpl { + fn drop(&mut self) { + info!("{} released", self); + } +} impl std::fmt::Display for ChunkStreamCache { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "ChunkStreamCache{{chunk:{}}}", self.chunk()) + write!(f, "{}", self.0) } } diff --git a/src/component/cyfs-bdt/src/ndn/chunk/manager.rs b/src/component/cyfs-bdt/src/ndn/chunk/manager.rs index 13ac93dd5..74592216c 100644 --- a/src/component/cyfs-bdt/src/ndn/chunk/manager.rs +++ b/src/component/cyfs-bdt/src/ndn/chunk/manager.rs @@ -116,15 +116,14 @@ impl ChunkManager { Self { stack: weak_stack, store: Box::new(EmptyChunkWrapper::new(store)), - raw_caches: RawCacheManager::new(stack.config().ndn.chunk.raw_caches.clone()), + raw_caches: RawCacheManager::new(stack.local_device_id().clone(), stack.config().ndn.chunk.raw_caches.clone()), caches: Mutex::new(Default::default()), downloaders: Mutex::new(Downloaders::new()) } } pub(crate) fn on_statistic(&self) -> String { - let caches = self.caches.lock().unwrap(); - format!("ChunkCacheCount:{}", caches.len()) + format!("ChunkCacheCount:{}, UsedMem: {}", self.caches.lock().unwrap().len(), self.raw_caches().used_mem()) } pub fn store(&self) -> &dyn ChunkReader { @@ -165,5 +164,19 @@ impl ChunkManager { for downloader in downloaders { downloader.on_drain(0); } + + { + let mut remove = LinkedList::new(); + let mut caches = self.caches.lock().unwrap(); + for (chunk, cache) in caches.iter() { + if cache.to_strong().is_none() { + remove.push_back(chunk.clone()); + } + } + + for chunk in remove { + caches.remove(&chunk); + } + } } } \ No newline at end of file From df261ab3b5238427428eb2bbb7f68b50440cdc15 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 16:48:37 +0800 Subject: [PATCH 117/553] Meta db initialization switch to transaction mode --- src/component/cyfs-noc/src/meta/sqlite/db.rs | 40 +++++++++++++++---- src/component/cyfs-noc/src/meta/sqlite/sql.rs | 2 +- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index 6df956a13..bad4aa5d1 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -85,19 +85,45 @@ impl SqliteMetaStorage { } fn init_db(&self) -> BuckyResult<()> { - let (conn, _lock) = self.conn.get_write_conn()?; + let (mut conn, _lock) = self.conn.get_write_conn()?; + + let tx = conn.transaction().map_err(|e| { + let msg = format!("noc meta db transaction error: {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::SqliteError, msg) + })?; + + let ret = (|| { + for sql in INIT_NAMEDOBJECT_META_SQL_LIST.iter() { + info!("will exec: {}", sql); + tx.execute(&sql, []).map_err(|e| { + let msg = format!("init noc table error! sql={}, {}", sql, e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::SqliteError, msg) + })?; + } + + Ok(()) + })(); + + if ret.is_ok() { + tx.commit().map_err(|e| { + let msg = format!("commit init transaction error: {}", e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::SqliteError, msg) + })?; + info!("init noc sqlite meta db success!"); - for sql in INIT_NAMEDOBJECT_META_SQL_LIST.iter() { - info!("will exec: {}", sql); - conn.execute(&sql, []).map_err(|e| { - let msg = format!("init noc table error! sql={}, {}", sql, e); + } else { + tx.rollback().map_err(|e| { + let msg = format!("rollback init transaction error: {}", e); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; } - info!("init noc sqlite table success!"); - Ok(()) + ret } fn check_and_update(&self) -> BuckyResult<()> { diff --git a/src/component/cyfs-noc/src/meta/sqlite/sql.rs b/src/component/cyfs-noc/src/meta/sqlite/sql.rs index d48569299..d3515e192 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/sql.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/sql.rs @@ -47,10 +47,10 @@ CREATE INDEX IF NOT EXISTS `data_namedobject_meta_last_access_time_index` on `da "#; pub(super) const INIT_NAMEDOBJECT_META_SQL_LIST: [&'static str; 4] = [ - SET_DB_VERSION, DATA_NAMEDOBJECT_META_INIT, DATA_NAMEDOBJECT_META_INSERT_TIME_INDEX, DATA_NAMEDOBJECT_META_INSERT_LAST_ACCESS_INDEX, + SET_DB_VERSION, ]; // version 1 alters From 810fdba8c228c679e8eec0fd3cadd1e630950420 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 18:33:14 +0800 Subject: [PATCH 118/553] Improve timeout and retry strategy for repo download in ood-daemon service --- src/Cargo.lock | 1 + src/service/ood-daemon/Cargo.toml | 3 ++- src/service/ood-daemon/src/repo/manager.rs | 2 +- src/service/ood-daemon/src/repo/named_data.rs | 10 ++++++---- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index fbbbbebed..55ede95d7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4475,6 +4475,7 @@ dependencies = [ "log 0.4.17", "once_cell", "ood-control", + "rand 0.7.3", "serde", "serde_json", "tide", diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index a96df7bee..cd8398ccb 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -35,4 +35,5 @@ once_cell = "1.12" toml = "0.5" http-types = "2.12" hex = "0.4" -tide = "0.16" \ No newline at end of file +tide = "0.16" +rand = '0.7' \ No newline at end of file diff --git a/src/service/ood-daemon/src/repo/manager.rs b/src/service/ood-daemon/src/repo/manager.rs index 4a2eea432..b3be3d6b1 100644 --- a/src/service/ood-daemon/src/repo/manager.rs +++ b/src/service/ood-daemon/src/repo/manager.rs @@ -197,7 +197,7 @@ impl RepoManager { local_file: &Path, ) -> BuckyResult<()> { if let Err(e) = repo - .fetch_with_timeout(info, local_file, std::time::Duration::from_secs(60 * 20)) + .fetch_with_timeout(info, local_file, std::time::Duration::from_secs(60 * 60 * 2)) .await { error!( diff --git a/src/service/ood-daemon/src/repo/named_data.rs b/src/service/ood-daemon/src/repo/named_data.rs index 149e5be60..c5834afe7 100644 --- a/src/service/ood-daemon/src/repo/named_data.rs +++ b/src/service/ood-daemon/src/repo/named_data.rs @@ -28,11 +28,10 @@ impl NamedDataRepo { } pub async fn init(&self) -> BuckyResult<()> { - // service desc确保它有固定外网地址,连接不走sn。这里sn_list就可以传None let mut config = NamedCacheClientConfig::default(); - config.retry_times = 3; - config.timeout = Duration::from_secs(10*60); + config.retry_times = 1; + config.timeout = Duration::from_secs(15 * 60); config.tcp_file_manager_port = 5312; config.tcp_chunk_manager_port = 5310; config.conn_strategy = cyfs_client::ConnStrategy::TcpFirst; @@ -130,7 +129,10 @@ impl Repo for NamedDataRepo { } async fn fetch(&self, info: &RepoPackageInfo, local_file: &Path) -> BuckyResult<()> { - let mut retry_interval_secs = 60; + use rand::Rng; + + // Use a random retry interval + let mut retry_interval_secs: u64 = rand::thread_rng().gen_range(60, 60 * 10); let mut retry_count = 0; loop { let info = info.to_owned(); From a27e04198f79e31b81ce56ea82f4b8e8b268ca21 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 18:44:12 +0800 Subject: [PATCH 119/553] Fix error op_env type check in requestor --- .../cyfs-lib/src/root_state/requestor.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-lib/src/root_state/requestor.rs b/src/component/cyfs-lib/src/root_state/requestor.rs index 03da498fa..5650c93c1 100644 --- a/src/component/cyfs-lib/src/root_state/requestor.rs +++ b/src/component/cyfs-lib/src/root_state/requestor.rs @@ -3,8 +3,8 @@ use super::output_request::*; use super::processor::*; use crate::base::*; use crate::non::NONRequestorHelper; -use crate::stack::SharedObjectStackDecID; use crate::requestor::*; +use crate::stack::SharedObjectStackDecID; use cyfs_base::*; use http_types::{Method, Request, Response, Url}; @@ -289,8 +289,13 @@ impl OpEnvRequestor { } async fn load(&self, req: OpEnvLoadOutputRequest) -> BuckyResult<()> { - if self.op_env_type != ObjectMapOpEnvType::Single { - let msg = format!("load method only valid for single_op_env! sid={}", self.sid); + if self.op_env_type != ObjectMapOpEnvType::Single + && self.op_env_type != ObjectMapOpEnvType::IsolatePath + { + let msg = format!( + "load method only valid for single_op_env and isolate_path_op_env! sid={}", + self.sid + ); error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::UnSupport, msg)); } @@ -327,9 +332,11 @@ impl OpEnvRequestor { } async fn load_by_path(&self, req: OpEnvLoadByPathOutputRequest) -> BuckyResult<()> { - if self.op_env_type != ObjectMapOpEnvType::Single { + if self.op_env_type != ObjectMapOpEnvType::Single + && self.op_env_type != ObjectMapOpEnvType::IsolatePath + { let msg = format!( - "load_by_path method only valid for single_op_env! sid={}", + "load_by_path method only valid for single_op_env and isolate_path_op_env! sid={}", self.sid ); error!("{}", msg); From fdae3ea0a8229d9fa79c58410af60c7018b8f2a6 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 19:22:40 +0800 Subject: [PATCH 120/553] Change sync services packages from parallel to serial --- src/Cargo.lock | 1 - src/service/ood-daemon/Cargo.toml | 1 - .../ood-daemon/src/service/service_manager.rs | 36 +++++++++---------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 55ede95d7..1aeba57f7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4464,7 +4464,6 @@ dependencies = [ "cyfs-debug", "cyfs-lib", "cyfs-meta-lib", - "cyfs-stack-loader", "cyfs-util", "fs_extra", "futures", diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index cd8398ccb..c0c092df8 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -18,7 +18,6 @@ cyfs-meta-lib = { path = "../../component/cyfs-meta-lib" } cyfs-client = { path = "../../tools/cyfs-client" } cyfs-lib = { path = "../../component/cyfs-lib" } ood-control = { path = "../ood-control" } -cyfs-stack-loader = { path = "../../component/cyfs-stack-loader" } lazy_static = "1.4" serde = "1.0" serde_json = "1.0" diff --git a/src/service/ood-daemon/src/service/service_manager.rs b/src/service/ood-daemon/src/service/service_manager.rs index 15a9d35b2..2d1540057 100644 --- a/src/service/ood-daemon/src/service/service_manager.rs +++ b/src/service/ood-daemon/src/service/service_manager.rs @@ -1,13 +1,3 @@ -use async_std::sync::Mutex as AsyncMutex; -use cyfs_lib::ZoneRole; -use futures::future::join_all; -use lazy_static::lazy_static; -use std::fmt; -use std::fmt::Formatter; -use std::path::PathBuf; -use std::sync::Arc; -use std::{collections::HashMap, str::FromStr}; - use super::service::Service; use super::service_info::ServicePackageLocalState; use crate::config::*; @@ -15,6 +5,15 @@ use crate::daemon::GATEWAY_MONITOR; use crate::status::*; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult}; use cyfs_debug::Mutex; +use cyfs_lib::ZoneRole; + +use async_std::sync::Mutex as AsyncMutex; +use lazy_static::lazy_static; +use std::fmt; +use std::fmt::Formatter; +use std::path::PathBuf; +use std::sync::Arc; +use std::{collections::HashMap, str::FromStr}; #[derive(Clone)] pub struct ServiceItem { @@ -465,26 +464,25 @@ impl ServiceManager { debug!("will sync all service packages"); - let mut futures = Vec::new(); - let service_list = self.service_list.lock().unwrap().clone(); for (name, service_info) in service_list { if service_info.service.is_none() { - error!("service not init! name={}", name); + error!("service not init yet! name={}", name); continue; } if service_info.target_state() == ServiceState::Run { - futures.push(Self::sync_service_package(service_info)); + if let Err(e) = Self::sync_service_package(&service_info).await { + error!( + "sync service package failed! service={}, {}", + service_info.config.name, e + ); + } } } - - if !futures.is_empty() { - let _ret = join_all(futures).await; - } } - async fn sync_service_package(service_info: ServiceItem) -> BuckyResult<()> { + async fn sync_service_package(service_info: &ServiceItem) -> BuckyResult<()> { let service = service_info.service.as_ref().unwrap(); match service.sync_package().await { Ok(changed) => { From e2aae9c13c0ed55acab422063b8944b790894778 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 18:51:15 +0800 Subject: [PATCH 121/553] Remove two spawn task using for cancel on timeout --- src/service/ood-daemon/src/repo/manager.rs | 14 ++++++-------- src/service/ood-daemon/src/repo/named_data.rs | 6 +----- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/service/ood-daemon/src/repo/manager.rs b/src/service/ood-daemon/src/repo/manager.rs index b3be3d6b1..1b1f3e27f 100644 --- a/src/service/ood-daemon/src/repo/manager.rs +++ b/src/service/ood-daemon/src/repo/manager.rs @@ -125,13 +125,7 @@ impl RepoManager { return Err(BuckyError::new(BuckyErrorCode::NotSupport, msg)); } - let cache_dir = self.cache_dir.clone(); - let fid = fid.to_owned(); - - async_std::task::spawn(async move { - Self::fetch_service_with_repo_list(&cache_dir, &fid, &repo_list).await - }) - .await + Self::fetch_service_with_repo_list(&self.cache_dir, fid, &repo_list).await } async fn fetch_service_with_repo_list( @@ -197,7 +191,11 @@ impl RepoManager { local_file: &Path, ) -> BuckyResult<()> { if let Err(e) = repo - .fetch_with_timeout(info, local_file, std::time::Duration::from_secs(60 * 60 * 2)) + .fetch_with_timeout( + info, + local_file, + std::time::Duration::from_secs(60 * 60 * 2), + ) .await { error!( diff --git a/src/service/ood-daemon/src/repo/named_data.rs b/src/service/ood-daemon/src/repo/named_data.rs index c5834afe7..fa68295fa 100644 --- a/src/service/ood-daemon/src/repo/named_data.rs +++ b/src/service/ood-daemon/src/repo/named_data.rs @@ -139,11 +139,7 @@ impl Repo for NamedDataRepo { let local_file = local_file.to_owned(); let client = self.client.get().unwrap().clone(); - match async_std::task::spawn(async move { - Self::fetch_inner(client, &info, &local_file).await - }) - .await - { + match Self::fetch_inner(client, &info, &local_file).await { Ok(()) => break Ok(()), Err(e) => { async_std::task::sleep(std::time::Duration::from_secs(retry_interval_secs)) From 6b48a407c6e22401a5c9806f8102c26878297240 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 20:07:44 +0800 Subject: [PATCH 122/553] Add check mechanism to noc meta db in case of main table missing --- src/component/cyfs-noc/src/meta/sqlite/db.rs | 96 +++++++++++++++++-- src/component/cyfs-noc/src/meta/sqlite/mod.rs | 3 + .../cyfs-noc/src/meta/sqlite/test.rs | 29 ++++++ src/component/cyfs-noc/src/noc/test.rs | 2 +- src/component/cyfs-util/src/util/db_helper.rs | 5 +- 5 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 src/component/cyfs-noc/src/meta/sqlite/test.rs diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index bad4aa5d1..c68074401 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -58,9 +58,26 @@ impl SqliteMetaStorage { conn: SqliteConnectionHolder::new(data_file), }; - if !file_exists { + let valid = if file_exists { + ret.check_db_valid().map_err(|e| { + error!( + "check noc sqlite meta db valid but got error! file={}, {}", + ret.data_file.display(), + e + ); + e + })? + } else { + false + }; + + if !valid { if let Err(e) = ret.init_db() { - error!("init noc sqlite meta db error! now will delete file, {}", e); + error!( + "init noc sqlite meta db error! now will delete file, file={}, {}", + ret.data_file.display(), + e + ); Self::remove_db_file(&ret.data_file, &ret.data_dir); return Err(e); @@ -84,11 +101,52 @@ impl SqliteMetaStorage { } } + fn check_db_valid(&self) -> BuckyResult { + let sql = + "SELECT name FROM sqlite_master WHERE type='table' AND name='data_namedobject_meta'"; + let ret = { + let (conn, _lock) = self.conn.get_read_conn()?; + + conn.query_row(&sql, [], |row| { + let name: String = row.get(0).unwrap(); + Ok(name) + }) + .optional() + .map_err(|e| { + let msg = format!("noc meta check tables error! sql={}, {}", sql, e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::SqliteError, msg) + })? + }; + + match ret { + Some(name) => { + info!( + "check noc meta db file success! file={}, table={}", + self.data_file.display(), + name + ); + Ok(true) + } + None => { + error!( + "check noc meta db file but main table not exists! file={}", + self.data_file.display() + ); + Ok(false) + } + } + } + fn init_db(&self) -> BuckyResult<()> { let (mut conn, _lock) = self.conn.get_write_conn()?; let tx = conn.transaction().map_err(|e| { - let msg = format!("noc meta db transaction error: {}", e); + let msg = format!( + "noc meta db transaction error: file={}, {}", + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) @@ -98,7 +156,12 @@ impl SqliteMetaStorage { for sql in INIT_NAMEDOBJECT_META_SQL_LIST.iter() { info!("will exec: {}", sql); tx.execute(&sql, []).map_err(|e| { - let msg = format!("init noc table error! sql={}, {}", sql, e); + let msg = format!( + "init noc table error! sql={}, file={}, {}", + sql, + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; @@ -109,15 +172,25 @@ impl SqliteMetaStorage { if ret.is_ok() { tx.commit().map_err(|e| { - let msg = format!("commit init transaction error: {}", e); + let msg = format!( + "commit init transaction error: file={}, {}", + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; - info!("init noc sqlite meta db success!"); - + info!( + "init noc sqlite meta db success! file={}", + self.data_file.display() + ); } else { tx.rollback().map_err(|e| { - let msg = format!("rollback init transaction error: {}", e); + let msg = format!( + "rollback init transaction error: file={}, {}", + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; @@ -133,7 +206,12 @@ impl SqliteMetaStorage { let old = Self::get_db_version(&conn)?; if old < CURRENT_VERSION { - info!("will update noc meta db: {} -> {}", old, CURRENT_VERSION); + info!( + "will update noc meta db: file={}, {} -> {}", + self.data_file.display(), + old, + CURRENT_VERSION + ); self.backup_db_file(old)?; diff --git a/src/component/cyfs-noc/src/meta/sqlite/mod.rs b/src/component/cyfs-noc/src/meta/sqlite/mod.rs index 017760bc3..93cf2f05c 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/mod.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/mod.rs @@ -2,5 +2,8 @@ mod sql; mod db; mod data; +#[cfg(test)] +mod test; + pub(crate) use db::*; pub(crate) use data::*; \ No newline at end of file diff --git a/src/component/cyfs-noc/src/meta/sqlite/test.rs b/src/component/cyfs-noc/src/meta/sqlite/test.rs new file mode 100644 index 000000000..2a70326d2 --- /dev/null +++ b/src/component/cyfs-noc/src/meta/sqlite/test.rs @@ -0,0 +1,29 @@ +use super::db::*; +use crate::meta::*; +use cyfs_base::*; +use cyfs_lib::*; + +async fn test_meta() { + let dir = cyfs_util::get_temp_path().join("test_noc_meta"); + if !dir.is_dir() { + std::fs::create_dir_all(&dir).unwrap(); + } + + let meta = SqliteMetaStorage::new(&dir).unwrap(); + + let req = NamedObjectMetaExistsObjectRequest { + source: RequestSourceInfo::new_local_system(), + object_id: ObjectId::default(), + }; + let ret = meta.exists_object(&req).await.unwrap(); + assert!(!ret); +} + +#[test] +fn main() { + cyfs_base::init_simple_log("cyfs-noc-test-meta", Some("debug")); + + async_std::task::block_on(async move { + test_meta().await; + }); +} diff --git a/src/component/cyfs-noc/src/noc/test.rs b/src/component/cyfs-noc/src/noc/test.rs index 835d8fc30..63184f65d 100644 --- a/src/component/cyfs-noc/src/noc/test.rs +++ b/src/component/cyfs-noc/src/noc/test.rs @@ -244,7 +244,7 @@ async fn test_error_blob() { let resp = noc.get_object(&get_req).await.unwrap(); let data = resp.unwrap(); - let data = Storage::raw_decode(&data.object.object_raw).unwrap(); + let _data = Storage::raw_decode(&data.object.object_raw).unwrap(); info!("test complete!"); } diff --git a/src/component/cyfs-util/src/util/db_helper.rs b/src/component/cyfs-util/src/util/db_helper.rs index 0c0d4f2e8..b6a1c1c2f 100644 --- a/src/component/cyfs-util/src/util/db_helper.rs +++ b/src/component/cyfs-util/src/util/db_helper.rs @@ -64,9 +64,10 @@ impl SqliteConnectionHolder { })?; info!( - "open db for thread={:?}, file={}", + "open db for thread={:?}, file={}, read={}", std::thread::current().id(), - self.data_file.display() + self.data_file.display(), + read_only, ); assert!(conn.is_autocommit()); From 5d63ee00bef613431c0ab9b5836e2b2cee547e5b Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 13:27:04 +0800 Subject: [PATCH 123/553] Add api edition relate header to requestors --- src/component/cyfs-base/src/base/protocol_fields.rs | 2 ++ src/component/cyfs-lib/src/base/protocol.rs | 1 + src/component/cyfs-lib/src/requestor/bdt.rs | 5 ++++- src/component/cyfs-lib/src/requestor/requestor.rs | 10 ++++++++-- src/component/cyfs-lib/src/requestor/surf.rs | 4 +++- src/component/cyfs-lib/src/requestor/tcp.rs | 4 +++- src/component/cyfs-lib/src/requestor/ws.rs | 1 + 7 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-base/src/base/protocol_fields.rs b/src/component/cyfs-base/src/base/protocol_fields.rs index 378e505c9..e3de57561 100644 --- a/src/component/cyfs-base/src/base/protocol_fields.rs +++ b/src/component/cyfs-base/src/base/protocol_fields.rs @@ -1,3 +1,5 @@ +pub const CYFS_API_EDITION: &str = "cyfs-api-edition"; + pub const CYFS_OBJECT_ID: &str = "cyfs-object-id"; pub const CYFS_OBJECT: &str = "cyfs-object"; diff --git a/src/component/cyfs-lib/src/base/protocol.rs b/src/component/cyfs-lib/src/base/protocol.rs index be3e8981d..67dd57f3c 100644 --- a/src/component/cyfs-lib/src/base/protocol.rs +++ b/src/component/cyfs-lib/src/base/protocol.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +pub const CYFS_CURRENT_API_EDITION: u32 = 1; // pub const CYFS_OBJECT_MIME_STRING: &str = "application/cyfs-object"; diff --git a/src/component/cyfs-lib/src/requestor/bdt.rs b/src/component/cyfs-lib/src/requestor/bdt.rs index 2107c4653..e836dfe97 100644 --- a/src/component/cyfs-lib/src/requestor/bdt.rs +++ b/src/component/cyfs-lib/src/requestor/bdt.rs @@ -74,7 +74,10 @@ impl HttpRequestor for BdtHttpRequestor { ); // bdt_stream.display_ref_count(); - match async_h1::connect(bdt_stream, req.take().unwrap()).await { + let req = req.take().unwrap(); + let req = self.add_default_headers(req); + + match async_h1::connect(bdt_stream, req).await { Ok(resp) => { info!( "http-bdt request to {} success! during={}ms, seq={:?}", diff --git a/src/component/cyfs-lib/src/requestor/requestor.rs b/src/component/cyfs-lib/src/requestor/requestor.rs index d4b311dd0..9afb2eb59 100644 --- a/src/component/cyfs-lib/src/requestor/requestor.rs +++ b/src/component/cyfs-lib/src/requestor/requestor.rs @@ -1,8 +1,9 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, DeviceId, Endpoint}; +use crate::base::CYFS_CURRENT_API_EDITION; +use cyfs_base::*; -use http_types::{Request, Response}; use async_std::net::SocketAddr; use async_trait::async_trait; +use http_types::{Request, Response}; use std::sync::Arc; use std::time::Duration; @@ -17,6 +18,11 @@ pub trait HttpRequestor: Send + Sync { fn remote_addr(&self) -> String; fn remote_device(&self) -> Option; + fn add_default_headers(&self, mut req: Request) -> Request { + req.insert_header(CYFS_API_EDITION, CYFS_CURRENT_API_EDITION.to_string()); + req + } + async fn request(&self, req: Request) -> BuckyResult { self.request_ext(&mut Some(req), None).await } diff --git a/src/component/cyfs-lib/src/requestor/surf.rs b/src/component/cyfs-lib/src/requestor/surf.rs index aa4eefd7f..0df32a8b9 100644 --- a/src/component/cyfs-lib/src/requestor/surf.rs +++ b/src/component/cyfs-lib/src/requestor/surf.rs @@ -54,7 +54,9 @@ impl HttpRequestor for SurfHttpRequestor { ); let begin = std::time::Instant::now(); - match self.client.send(req.take().unwrap()).await { + let req = req.take().unwrap(); + let req = self.add_default_headers(req); + match self.client.send(req).await { Ok(resp) => { info!( "http request to {} success! during={}ms", diff --git a/src/component/cyfs-lib/src/requestor/tcp.rs b/src/component/cyfs-lib/src/requestor/tcp.rs index d1d4fa3a5..b76c176a6 100644 --- a/src/component/cyfs-lib/src/requestor/tcp.rs +++ b/src/component/cyfs-lib/src/requestor/tcp.rs @@ -56,7 +56,9 @@ impl HttpRequestor for TcpHttpRequestor { )); } - match async_h1::connect(tcp_stream, req.take().unwrap()).await { + let req = req.take().unwrap(); + let req = self.add_default_headers(req); + match async_h1::connect(tcp_stream, req).await { Ok(resp) => { info!( "http-tcp request to {} success! during={}ms", diff --git a/src/component/cyfs-lib/src/requestor/ws.rs b/src/component/cyfs-lib/src/requestor/ws.rs index 21bfdc87f..17a856bc9 100644 --- a/src/component/cyfs-lib/src/requestor/ws.rs +++ b/src/component/cyfs-lib/src/requestor/ws.rs @@ -88,6 +88,7 @@ impl HttpRequestor for WSHttpRequestor { // request编码到buffer let req = req.take().unwrap(); + let req = self.add_default_headers(req); let mut encoder = async_h1::client::Encoder::new(req); let mut buf = vec![]; encoder.read_to_end(&mut buf).await.map_err(|e| { From ab3c2b2d1fb892e02d7a0d9abde33768d66924d4 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 20:11:41 +0800 Subject: [PATCH 124/553] Fix the panic that may be caused by check db in cyfs-noc --- src/component/cyfs-noc/src/meta/sqlite/db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index c68074401..bcd8aeb1e 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -105,7 +105,7 @@ impl SqliteMetaStorage { let sql = "SELECT name FROM sqlite_master WHERE type='table' AND name='data_namedobject_meta'"; let ret = { - let (conn, _lock) = self.conn.get_read_conn()?; + let (conn, _lock) = self.conn.get_write_conn()?; conn.query_row(&sql, [], |row| { let name: String = row.get(0).unwrap(); From c38fbe3512a8e2a05dec9479602bcf0168173762 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 22 Feb 2023 20:46:54 +0800 Subject: [PATCH 125/553] App-tool support change preview service version, pack script add preview version to service --- scripts/pack.js | 64 +-- src/Cargo.lock | 987 +++++++++++++++++---------------- src/tools/app-tool/Cargo.toml | 1 - src/tools/app-tool/src/main.rs | 569 ++++++------------- 4 files changed, 676 insertions(+), 945 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index 71acbc68e..f3676ea57 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -129,58 +129,15 @@ async function run() { } console.log(`get file repo account ${file_repo_id} balance ${balance}`) - if (type.includes("apps")) { - try { fs.rmSync('dist/app_config.cfg') } catch (error) { } - let app_config = [] - - for (const app of apps) { - if (!app.pub) { - continue - } - if (onlyput !== "onlyput") { - for (const target of targets) { - if (app.exclude && app.exclude.includes(target)) { - continue - } - if (app.include && !app.include.includes(target)) { - continue - } - let project_path = app.path || `app/${app.name}` - let config_path = app.config_file[target] || app.config_file.default - fs.copyFileSync(`${project_path}/${config_path}`, `dist/apps/${app.name}/${target}/package.cfg`) - - if (app.assets && app.assets[target]) { - for (const asset of app.assets[target]) { - fs.copyFileSync(asset.from, `dist/apps/${app.name}/${target}/${asset.to}`) - } - } - } - - child_process.execSync(`bash -c "./pack-tools -d apps/${app.name}"`, { cwd: 'dist', stdio: 'inherit' }) - } - - child_process.execSync(`cyfs-client ${action} apps/${app.name}.zip -f fid -o ${file_repo_path}`, { cwd: 'dist', stdio: 'inherit' }) - let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}); - app_config.apps.push({ "id": app.appid, "ver": `${version}`, "status": 1 }) - - // 运行app-tool,添加版本和fid - if (app.appid !== undefined) { - let cmd = `app-tool app set -v ${version} -s ${fid} ${app.appid} -o ${repo_path}`; - console.log("will run app tool cmd:", cmd) - child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) - } - - } - - fs.writeJSONSync('dist/app_config.cfg', app_config) - } - - if (type.includes("services")) { try { fs.removeSync('dist/device_config.cfg') } catch (error) { } let device_config = []; for (const service of services) { + if (!service.id) { + console.error(`service ${service.name} has no id!`); + process.exit(1); + } if (!service.pub) { continue } @@ -208,16 +165,15 @@ async function run() { } child_process.execSync(`cyfs-client ${action} services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) + + // 运行app-tool,添加版本和fid + let app_version = version + "-preview"; + let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; + console.log("will run app tool cmd:", cmd) + child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) - - // 运行app-tool,添加版本和fid - if (service.id !== undefined) { - let cmd = `app-tool app set -v ${version} -s ${fid} ${service.id} -o ${repo_path}`; - console.log("will run app tool cmd:", cmd) - child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) - } } fs.writeFileSync('dist/device-config.cfg', JSON.stringify(device_config)) diff --git a/src/Cargo.lock b/src/Cargo.lock index 1aeba57f7..ca0aa67f7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -111,9 +111,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" [[package]] name = "android_logger" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" +checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" dependencies = [ "android_log-sys", "env_logger", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "app-manager" @@ -206,7 +206,6 @@ dependencies = [ "cyfs-base-meta", "cyfs-core", "cyfs-debug", - "cyfs-lib", "cyfs-meta-lib", "cyfs-util", "lazy_static", @@ -263,9 +262,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ "concurrent-queue", "event-listener", @@ -284,23 +283,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", @@ -330,31 +329,32 @@ dependencies = [ [[package]] name = "async-io" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ + "async-lock", "autocfg 1.1.0", "concurrent-queue", "futures-lite", "libc", "log 0.4.17", - "once_cell", "parking", "polling", "slab", "socket2", "waker-fn", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -371,27 +371,27 @@ dependencies = [ [[package]] name = "async-process" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" +checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" dependencies = [ "async-io", + "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", - "once_cell", "signal-hook", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ "proc-macro2", "quote", @@ -493,9 +493,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -526,9 +526,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -536,7 +536,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -558,9 +558,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -774,16 +774,16 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", + "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", - "once_cell", ] [[package]] @@ -794,14 +794,14 @@ checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" dependencies = [ "base64 0.13.1", "bollard-stubs", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "dirs-next", "futures-core", "futures-util", "hex", "http", - "hyper 0.14.20", + "hyper 0.14.24", "hyperlocal", "log 0.4.17", "pin-project", @@ -849,13 +849,11 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" dependencies = [ - "lazy_static", "memchr", - "regex-automata", "serde", ] @@ -867,15 +865,15 @@ checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -885,9 +883,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" [[package]] name = "byteorder" @@ -907,15 +905,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -952,9 +950,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -985,16 +983,16 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.44", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -1110,7 +1108,7 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "memchr", ] @@ -1122,11 +1120,11 @@ checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" [[package]] name = "concurrent-queue" -version = "1.2.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ - "cache-padded", + "crossbeam-utils", ] [[package]] @@ -1303,22 +1301,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1326,9 +1324,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -1391,13 +1389,12 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -1432,9 +1429,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -1444,9 +1441,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -1459,15 +1456,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -1514,7 +1511,7 @@ dependencies = [ "simple_logger 2.3.0", "sqlx", "url 2.3.0", - "zip 0.6.3", + "zip 0.6.4", ] [[package]] @@ -1566,7 +1563,7 @@ dependencies = [ "log 0.4.17", "lru_time_cache", "md5", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.7.3", "ringbuf", @@ -1622,7 +1619,7 @@ dependencies = [ "cyfs-util", "dirs 4.0.0", "log 0.4.17", - "sysinfo 0.26.5", + "sysinfo 0.26.9", ] [[package]] @@ -1638,7 +1635,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1662,7 +1659,7 @@ dependencies = [ "scan_dir", "sha2 0.8.2", "shared_memory", - "sysinfo 0.26.5", + "sysinfo 0.26.9", ] [[package]] @@ -1679,7 +1676,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1703,7 +1700,7 @@ version = "0.6.4" dependencies = [ "bip39", "cyfs-base", - "digest 0.10.5", + "digest 0.10.6", "hex", "hmac 0.12.1", "log 0.4.17", @@ -1838,7 +1835,7 @@ dependencies = [ "async-std", "async-trait", "async-tungstenite", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "cyfs-base", "cyfs-bdt", @@ -2125,7 +2122,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.2.1", + "bytes 1.4.0", "clap", "cyfs-base", "cyfs-bdt", @@ -2197,18 +2194,18 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.3", - "prost-build 0.11.3", + "prost 0.11.6", + "prost-build 0.11.6", "protoc-bin-vendored", "rand 0.8.5", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", "sha2 0.8.2", "sqlx", "tide", "toml", - "zip 0.6.3", + "zip 0.6.4", ] [[package]] @@ -2254,7 +2251,7 @@ dependencies = [ "regex", "serde", "toml", - "toml_edit", + "toml_edit 0.15.0", ] [[package]] @@ -2339,7 +2336,7 @@ dependencies = [ "log 0.4.17", "log-panics", "named-lock", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.8.5", "rusqlite", @@ -2352,7 +2349,7 @@ dependencies = [ "url 2.3.0", "walkdir", "winapi", - "zip 0.6.3", + "zip 0.6.4", ] [[package]] @@ -2400,7 +2397,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] @@ -2476,9 +2473,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -2551,9 +2548,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "email-encoding" @@ -2637,9 +2634,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "env_logger" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "log 0.4.17", "regex", @@ -2647,9 +2644,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" +checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" dependencies = [ "serde", ] @@ -2665,7 +2662,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itertools", - "paste 1.0.9", + "paste 1.0.11", "rustc-hex", "serde", "serde_json", @@ -2801,9 +2798,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -2840,14 +2837,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -2870,9 +2867,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -2904,7 +2901,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.4", + "spin 0.9.5", ] [[package]] @@ -2964,9 +2961,9 @@ dependencies = [ [[package]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "fuchsia-cprng" @@ -2982,9 +2979,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -2997,9 +2994,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -3007,15 +3004,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -3025,20 +3022,20 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.12.1", + "parking_lot 0.11.2", ] [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -3057,9 +3054,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -3068,21 +3065,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -3103,7 +3100,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.2.1", + "bytes 1.4.0", "clap", "cyfs-base", "cyfs-bdt", @@ -3183,9 +3180,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" +checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" dependencies = [ "proc-macro2", "quote", @@ -3194,21 +3191,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -3219,9 +3216,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", @@ -3231,11 +3228,11 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "fnv", "futures-core", "futures-sink", @@ -3244,7 +3241,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.4", + "tokio-util 0.7.7", "tracing", ] @@ -3310,9 +3307,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -3326,6 +3323,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -3413,7 +3419,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -3440,13 +3446,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "fnv", - "itoa 1.0.4", + "itoa", ] [[package]] @@ -3455,7 +3461,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "http", "pin-project-lite 0.2.9", ] @@ -3531,7 +3537,7 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time 0.1.44", + "time 0.1.45", "traitobject", "typeable", "unicase 1.4.2", @@ -3540,11 +3546,11 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-channel", "futures-core", "futures-util", @@ -3553,7 +3559,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.4", + "itoa", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -3570,16 +3576,16 @@ checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" dependencies = [ "futures-util", "hex", - "hyper 0.14.20", + "hyper 0.14.24", "pin-project", "tokio", ] [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3681,9 +3687,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -3696,7 +3702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" dependencies = [ "indoc-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -3705,7 +3711,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "syn", @@ -3798,15 +3804,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jni" @@ -3839,18 +3839,21 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] [[package]] name = "kv-log-macro" @@ -3892,7 +3895,7 @@ dependencies = [ "idna 0.2.1", "mime 0.3.16", "native-tls", - "nom 7.1.1", + "nom 7.1.3", "once_cell", "quoted_printable", "socket2", @@ -3913,15 +3916,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libsecp256k1" @@ -3952,9 +3955,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -4023,7 +4026,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" dependencies = [ - "nix 0.23.1", + "nix 0.23.2", "winapi", ] @@ -4035,9 +4038,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "maybe-uninit" @@ -4059,9 +4062,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" dependencies = [ "libc", ] @@ -4075,6 +4078,15 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "memzero" version = "0.1.0" @@ -4156,23 +4168,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] @@ -4207,9 +4219,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -4235,27 +4247,27 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -4271,14 +4283,23 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "ntapi" version = "0.4.0" @@ -4331,9 +4352,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" dependencies = [ "byteorder", "lazy_static", @@ -4390,11 +4411,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -4409,18 +4430,18 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "ood-control" @@ -4445,7 +4466,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sysinfo 0.26.5", + "sysinfo 0.26.9", "tide", ] @@ -4479,7 +4500,7 @@ dependencies = [ "serde_json", "tide", "toml", - "zip 0.6.3", + "zip 0.6.4", ] [[package]] @@ -4529,9 +4550,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.42" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -4561,9 +4582,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.77" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg 1.1.0", "cc", @@ -4591,7 +4612,7 @@ dependencies = [ "sha2 0.8.2", "simple_logger 2.3.0", "walkdir", - "zip 0.6.3", + "zip 0.6.4", ] [[package]] @@ -4614,7 +4635,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -4634,7 +4655,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -4644,14 +4665,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -4663,15 +4684,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec 1.10.0", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -4692,14 +4713,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "paste-impl" @@ -4707,7 +4728,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -4716,7 +4737,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -4756,9 +4777,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -4826,9 +4847,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -4879,16 +4900,16 @@ dependencies = [ [[package]] name = "polling" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -4904,15 +4925,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ "proc-macro2", "syn", @@ -4920,9 +4941,9 @@ dependencies = [ [[package]] name = "primal" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389bfb36ac527b5fe21a57f87bc7956af45cbeb2de7750b90b7ebac6770e715e" +checksum = "4b53cc99c892c461727618e8a63806c94b09ae13c494dc5fc70a7557b3a2f071" dependencies = [ "primal-check", "primal-estimate", @@ -4955,9 +4976,9 @@ checksum = "7374f14c76f23e1271e6be806981ac5dd9e52b59132b0a2f10bcc412495f9159" [[package]] name = "primal-sieve" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fee6031f66b44e8e004ac9bf81fd1c5abcbbb25bd392bc27429daa1759654a" +checksum = "9f2a14766f8c543620824b5b2cec356abf2681b76966a7ac4b4ed2c0011e696a" dependencies = [ "primal-bit", "primal-estimate", @@ -4988,13 +5009,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit 0.18.1", ] [[package]] @@ -5008,9 +5028,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-hack-impl" @@ -5020,9 +5040,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -5033,18 +5053,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b18e655c21ff5ac2084a5ad0611e827b3f92badf79f4910b5a5c58f4d87ff0" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ - "bytes 1.2.1", - "prost-derive 0.11.2", + "bytes 1.4.0", + "prost-derive 0.11.6", ] [[package]] @@ -5053,7 +5073,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "heck 0.3.3", "itertools", "lazy_static", @@ -5069,20 +5089,20 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ - "bytes 1.2.1", - "heck 0.4.0", + "bytes 1.4.0", + "heck 0.4.1", "itertools", "lazy_static", "log 0.4.17", "multimap", "petgraph", "prettyplease", - "prost 0.11.3", - "prost-types 0.11.2", + "prost 0.11.6", + "prost-types 0.11.6", "regex", "syn", "tempfile", @@ -5104,9 +5124,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.2" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -5121,18 +5141,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.2" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ - "bytes 1.2.1", - "prost 0.11.3", + "bytes 1.4.0", + "prost 0.11.6", ] [[package]] @@ -5141,7 +5161,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", ] [[package]] @@ -5281,18 +5301,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "quoted_printable" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f14e071918cbeefc5edc986a7aa92c425dae244e003a35e1cdddb5ca39b5cb" +checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" [[package]] name = "radium" @@ -5492,21 +5512,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg 1.1.0", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -5562,26 +5580,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -5622,7 +5634,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "rustc-hex", ] @@ -5672,8 +5684,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", - "digest 0.10.5", - "num-bigint-dig 0.8.1", + "digest 0.10.6", + "num-bigint-dig 0.8.2", "num-integer", "num-iter", "num-traits", @@ -5809,15 +5821,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "safemem" @@ -5852,7 +5864,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -5869,12 +5881,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -5885,9 +5896,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "sct" @@ -5901,9 +5912,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.7.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -5914,9 +5925,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -5933,9 +5944,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -5945,9 +5956,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -5964,9 +5975,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -5984,11 +5995,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.4", + "itoa", "ryu", "serde", ] @@ -6011,7 +6022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa", "ryu", "serde", ] @@ -6040,13 +6051,13 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6066,7 +6077,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6108,7 +6119,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6154,16 +6165,16 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.17", - "nix 0.23.1", + "nix 0.23.2", "rand 0.8.5", "win-sys", ] [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -6171,9 +6182,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -6207,7 +6218,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "winapi", ] @@ -6220,7 +6231,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "winapi", ] @@ -6233,15 +6244,15 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "windows-sys 0.42.0", ] [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg 1.1.0", ] @@ -6320,9 +6331,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" dependencies = [ "lock_api", ] @@ -6344,7 +6355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom 7.1.1", + "nom 7.1.3", "unicode_categories", ] @@ -6368,11 +6379,11 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "crc", "crossbeam-queue", - "digest 0.10.5", + "digest 0.10.6", "either", "event-listener", "flume", @@ -6385,14 +6396,14 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.4", + "itoa", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "num-bigint 0.3.3", "once_cell", - "paste 1.0.9", + "paste 1.0.11", "percent-encoding 2.2.0", "rand 0.8.5", "rsa 0.6.1", @@ -6417,7 +6428,7 @@ checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.4.0", + "heck 0.4.1", "once_cell", "proc-macro2", "quote", @@ -6571,9 +6582,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -6594,9 +6605,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.5" +version = "0.26.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade661fa5e048ada64ad7901713301c21d2dbc5b65ee7967de8826c111452960" +checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -6676,9 +6687,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -6704,18 +6715,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -6724,10 +6735,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -6765,9 +6777,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -6791,16 +6803,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ - "itoa 1.0.4", + "itoa", "libc", "num_threads", "serde", "time-core", - "time-macros 0.2.5", + "time-macros 0.2.7", ] [[package]] @@ -6815,15 +6827,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "time-macros-impl", ] [[package]] name = "time-macros" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" dependencies = [ "time-core", ] @@ -6834,7 +6846,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "standback", @@ -6871,19 +6883,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.21.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg 1.1.0", - "bytes 1.2.1", + "bytes 1.4.0", "libc", "memchr", "mio", "num_cpus", "pin-project-lite 0.2.9", "socket2", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -6892,7 +6904,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-core", "futures-sink", "log 0.4.17", @@ -6902,11 +6914,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-core", "futures-sink", "pin-project-lite 0.2.9", @@ -6916,9 +6928,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "indexmap", "serde", @@ -6926,9 +6938,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" [[package]] name = "toml_edit" @@ -6942,6 +6954,17 @@ dependencies = [ "toml_datetime", ] +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -6950,9 +6973,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite 0.2.9", @@ -6986,9 +7009,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" @@ -6998,7 +7021,7 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.2.1", + "bytes 1.4.0", "http", "httparse", "log 0.4.17", @@ -7017,15 +7040,15 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "uint" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", @@ -7053,15 +7076,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -7074,9 +7097,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -7098,9 +7121,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unindent" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "universal-hash" @@ -7175,9 +7198,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version-compare" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" @@ -7247,9 +7270,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "serde", @@ -7259,9 +7282,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log 0.4.17", @@ -7274,9 +7297,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7286,9 +7309,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7296,9 +7319,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -7309,15 +7332,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -7362,9 +7385,9 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", @@ -7438,37 +7461,48 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" @@ -7478,15 +7512,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" @@ -7496,15 +7524,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" @@ -7514,15 +7536,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" @@ -7532,21 +7548,15 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" @@ -7556,15 +7566,9 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "wyz" @@ -7592,9 +7596,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", @@ -7613,14 +7617,14 @@ dependencies = [ "crc32fast", "flate2", "thiserror", - "time 0.1.44", + "time 0.1.45", ] [[package]] name = "zip" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" dependencies = [ "aes 0.7.5", "byteorder", @@ -7632,7 +7636,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2", "sha1 0.10.5", - "time 0.3.16", + "time 0.3.19", "zstd", ] @@ -7718,10 +7722,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.7+zstd.1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" dependencies = [ "cc", "libc", + "pkg-config", ] diff --git a/src/tools/app-tool/Cargo.toml b/src/tools/app-tool/Cargo.toml index fbbb9619d..c938dced3 100644 --- a/src/tools/app-tool/Cargo.toml +++ b/src/tools/app-tool/Cargo.toml @@ -14,7 +14,6 @@ cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-base-meta = { path = "../../component/cyfs-base-meta" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-meta-lib = { path = "../../component/cyfs-meta-lib" } -cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-util = { path = "../../component/cyfs-util" } async-std = { version = "1.11", features = ["unstable", "attributes"] } clap = "2.34.0" diff --git a/src/tools/app-tool/src/main.rs b/src/tools/app-tool/src/main.rs index 3c3440024..a5111ce91 100644 --- a/src/tools/app-tool/src/main.rs +++ b/src/tools/app-tool/src/main.rs @@ -6,9 +6,6 @@ use cyfs_base::{ }; use cyfs_base_meta::{Data, SavedMetaObject}; use cyfs_core::{AppList, AppListObj, AppStatus, AppStatusObj, DecApp, DecAppId, DecAppObj}; -use cyfs_lib::{ - NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPutObjectRequest, SharedCyfsStack, -}; use cyfs_meta_lib::{MetaClient, MetaMinerTarget}; use lazy_static::lazy_static; use log::*; @@ -58,58 +55,6 @@ fn add_id_or_file_arg<'a, 'b>(cmd: App<'a, 'b>) -> App<'a, 'b> { ) } -async fn put_object(stack: &SharedCyfsStack, obj: &N) -where - D: ObjectType, - T: RawEncode, - N: RawConvertTo, - N: NamedObject, - ::ContentType: BodyContent, -{ - let object_id = obj.desc().calculate_id(); - match stack - .non_service() - .put_object(NONPutObjectRequest { - common: NONOutputRequestCommon::new(NONAPILevel::Router), - object: NONObjectInfo::new_from_object_raw(obj.to_vec().unwrap()).unwrap(), - access: None - }) - .await - { - Ok(_) => { - info!("put obj [{}] to ood success!", &object_id); - } - Err(e) => { - if e.code() != BuckyErrorCode::Ignored { - error!("put obj [{}] to ood failed! {}", &object_id, e); - } else { - info!("put obj [{}] to ood success!", &object_id); - } - } - } -} - -async fn put_object_ex(obj: &N) -where - D: ObjectType, - T: RawEncode, - N: RawConvertTo, - N: NamedObject, - ::ContentType: BodyContent, -{ - let cyfs_stack = match SharedCyfsStack::open_default(None).await { - Ok(stack) => Some(stack), - Err(e) => { - warn!("cannot open local stack, err {}", e); - None - } - }; - - if let Some(stack) = cyfs_stack { - put_object(&stack, obj).await; - } -} - fn get_owner(matches: &ArgMatches<'_>) -> Option<(StandardObject, PrivateKey)> { if let Some(owner_path) = matches.value_of("owner") { let ret = cyfs_util::get_desc_from_file( @@ -184,38 +129,50 @@ async fn get_list(matches: &ArgMatches<'_>) -> BuckyResult<(AppList, SaveTarget) } } +async fn get_app_from_meta(id: &ObjectId, target: &SaveTarget) -> BuckyResult { + match target { + SaveTarget::Meta(client, _) => { + match client.get_desc(&id).await { + Ok(data) => { + if let SavedMetaObject::Data(data) = data { + let app = DecApp::clone_from_slice(&data.data).unwrap(); + Ok(app) + } else { + error!("get {} from meta failed, unmatch", &id); + Err(BuckyError::from(BuckyErrorCode::NotMatch)) + } + } + Err(e) => { + error!("get {} from meta failed, err {}", &id, e); + Err(e) + } + } + }, + SaveTarget::File(_, _) => { + Err(BuckyError::from(BuckyErrorCode::NotSupport)) + } + } +} + async fn get_app(matches: &ArgMatches<'_>) -> BuckyResult<(DecApp, SaveTarget)> { + let owner = get_owner(matches); if let Some(id_str) = matches.value_of("id") { + let id = ObjectId::from_str(id_str).unwrap(); let meta_client = MetaClient::new_target( MetaMinerTarget::from_str(matches.value_of("meta_target").unwrap()).unwrap(), ); - let id = ObjectId::from_str(id_str).unwrap(); - return match meta_client.get_desc(&id).await { - Ok(data) => { - if let SavedMetaObject::Data(data) = data { - let app = DecApp::clone_from_slice(&data.data).unwrap(); - let owner = get_owner(matches); - Ok((app, SaveTarget::Meta(meta_client, owner))) - } else { - error!("get {} from meta failed, unmatch", &id); - Err(BuckyError::from(BuckyErrorCode::NotMatch)) - } - } - Err(e) => { - error!("get {} from meta failed, err {}", &id, e); - Err(e) - } - }; + let target = SaveTarget::Meta(meta_client, owner); + let app = get_app_from_meta(&id, &target).await?; + Ok((app, target)) } else if let Some(file_path) = matches.value_of("file") { let (app, _) = DecApp::decode_from_file(file_path.as_ref(), &mut vec![])?; - let owner = get_owner(matches); return Ok((app, SaveTarget::File(file_path.to_owned(), owner))); } else { let meta_client = MetaClient::new_target( MetaMinerTarget::from_str(matches.value_of("meta_target").unwrap()).unwrap(), ); - let owner = get_owner(matches); + if owner.is_none() { error!("must use owner and name when no id or file!"); return Err(BuckyError::from(BuckyErrorCode::InvalidInput)); @@ -255,55 +212,54 @@ impl SaveTarget { SaveTarget::File(_, owner) => owner.as_ref().map(|(obj, _)| obj.calculate_id()), } } -} -async fn save_obj(target: SaveTarget, obj: &N) -> BuckyResult<()> -where - D: ObjectType, - N: RawEncode, - N: NamedObject, - ::ContentType: BodyContent, -{ - match target { - SaveTarget::Meta(meta_client, owner) => { - let upload_data = SavedMetaObject::Data(Data { - id: obj.desc().calculate_id(), - data: obj.to_vec().unwrap(), - }); - - match meta_client - .update_desc( - &owner.as_ref().unwrap().0, - &upload_data, - None, - None, - &owner.as_ref().unwrap().1, - ) - .await - { - Ok(txid) => { - info!("upload obj to meta success, TxId {}", &txid); + async fn save_obj(&self, obj: &N) -> BuckyResult<()> + where + D: ObjectType, + N: RawEncode, + N: NamedObject, + ::ContentType: BodyContent, + { + match self { + SaveTarget::Meta(meta_client, owner) => { + let upload_data = SavedMetaObject::Data(Data { + id: obj.desc().calculate_id(), + data: obj.to_vec().unwrap(), + }); + + if let Some((owner, secret)) = owner { + match meta_client.update_desc(owner,&upload_data,None,None, secret).await + { + Ok(txid) => { + info!("upload obj to meta success, TxId {}", &txid); + } + Err(e) => { + error!("upload obj to meta fail, err {}", e); + return Err(e); + } + } + } else { + error!("save obj to meta but no owner desc!"); + return Err(BuckyError::from(BuckyErrorCode::InvalidParam)) + } + } + SaveTarget::File(path, _) => match obj.encode_to_file(path.as_ref(), false) { + Ok(_) => { + info!("write obj to {} success", path); } Err(e) => { - error!("upload obj to meta fail, err {}", e); - return Err(e); + info!("write obj to {} failed, err {}", path, e); + return Err(e) } - } + }, } - SaveTarget::File(path, _) => match obj.encode_to_file(path.as_ref(), false) { - Ok(_) => { - info!("write obj to {} success", path); - } - Err(e) => { - info!("write obj to {} failed, err {}", path, e); - return Err(e) - } - }, - } - Ok(()) + Ok(()) + } } + + lazy_static! { static ref DEFAULT_TARGET: String = MetaMinerTarget::default().to_string(); } @@ -320,201 +276,127 @@ async fn main_run() -> BuckyResult<()> { .long("meta_target") .default_value(&DEFAULT_TARGET) .help("meta target"); - let matches = App::new("app-tool") + let app = App::new("app-tool") .version(cyfs_base::get_version()) .about("manage app list") .subcommand( SubCommand::with_name("list") .about("create/modify/show app list object") - .subcommand( - SubCommand::with_name("create") + .subcommand(SubCommand::with_name("create") .about("create app list object") - .arg( - Arg::with_name("owner") - .short("o") - .long("owner") - .takes_value(true) - .required(true) - .help("app list owner desc/sec file"), - ) - .arg( - Arg::with_name("name") - .short("n") - .long("name") + .arg(Arg::with_name("owner") + .short("o").long("owner") + .takes_value(true).required(true) + .help("app list owner desc/sec file")) + .arg(Arg::with_name("name") + .short("n").long("name") .default_value("") - .help("app list name, default empty string"), - ) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .help("app list name, default empty string")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) - .arg( - Arg::with_name("upload") - .short("u") - .long("upload") - .help("upload app list to chain, use owner account"), - ) + .possible_values(&["app", "service"])) + .arg(Arg::with_name("upload") + .short("u").long("upload") + .help("upload app list to chain, use owner account")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("put").about("put app to app list")) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("put").about("put app to app list")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) - .arg( - Arg::with_name("appid") + .possible_values(&["app", "service"])) + .arg(Arg::with_name("appid") .short("i") - .required(true) - .takes_value(true) - .help("app id add to app list"), - ) - .arg( - Arg::with_name("appver") + .required(true).takes_value(true) + .help("app id add to app list")) + .arg(Arg::with_name("appver") .short("v") - .required(true) - .takes_value(true) - .help("app ver add to app list"), - ) - .arg( - Arg::with_name("status") - .short("s") - .long("start") - .help("start app, default false"), - ) + .required(true).takes_value(true) + .help("app ver add to app list")) + .arg(Arg::with_name("status") + .short("s").long("start") + .help("start app, default false")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg( - SubCommand::with_name("remove").about("remove app from list"), - ) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("remove").about("remove app from list")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) - .arg( - Arg::with_name("appid") + .possible_values(&["app", "service"])) + .arg(Arg::with_name("appid") .short("i") - .takes_value(true) - .required(true) - .help("remove app id"), - ) + .takes_value(true).required(true) + .help("remove app id")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("clear").about("clean all apps")) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("clear").about("clean all apps")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) + .possible_values(&["app", "service"])) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("show").about("show app list obj")) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("show").about("show app list obj")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) + .possible_values(&["app", "service"])) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg( - SubCommand::with_name("update").about("update app list from json"), - ) - .arg( - Arg::with_name("config") - .short("c") - .long("config") + .subcommand(add_id_or_file_arg(SubCommand::with_name("update").about("update app list from json")) + .arg(Arg::with_name("config") + .short("c").long("config") .takes_value(true) - .required(true), - ) - .arg( - Arg::with_name("type") - .short("t") - .long("type") - .default_value("app") - .possible_values(&["app", "service"]), - ).arg( - Arg::with_name("clear") - .long("clear") - .help("cleat list before update") - ) + .required(true)) + .arg(Arg::with_name("type").short("t").long("type").default_value("app").possible_values(&["app", "service"])) + .arg(Arg::with_name("clear").long("clear") + .help("cleat list before update")) + .arg(Arg::with_name("unpreview").long("unpreview") + .help("change app preview version to normal version")) .arg(meta_arg.clone()), ), ) - .subcommand( - SubCommand::with_name("app") + .subcommand(SubCommand::with_name("app") .about("create/modify/show app object") - .subcommand( - SubCommand::with_name("create") + .subcommand(SubCommand::with_name("create") .about("create app object") - .arg( - Arg::with_name("owner") + .arg(Arg::with_name("owner") .short("o") .long("owner") .takes_value(true) .required(true) - .help("app owner desc/sec file"), - ) - .arg( - Arg::with_name("id") + .help("app owner desc/sec file")) + .arg(Arg::with_name("id") .index(1) .takes_value(true) .required(true) - .help("app id"), - ) - .arg( - Arg::with_name("upload") + .help("app id")) + .arg(Arg::with_name("upload") .short("u") .long("upload") - .help("upload app list to chain, use owner account"), - ) + .help("upload app list to chain, use owner account")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("set").about("add source to app")) - .arg( - Arg::with_name("appver") + .subcommand(add_id_or_file_arg(SubCommand::with_name("set").about("add source to app")) + .arg(Arg::with_name("appver") .short("v") .required(true) .takes_value(true) - .help("ver add to app source"), - ) - .arg( - Arg::with_name("source") + .help("ver add to app source")) + .arg(Arg::with_name("source") .short("s") .required(true) .takes_value(true) - .help("fileid add to app source"), - ) + .help("fileid add to app source")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg( - SubCommand::with_name("remove").about("remove source from app"), - ) - .arg( - Arg::with_name("appver") + .subcommand(add_id_or_file_arg(SubCommand::with_name("remove").about("remove source from app")) + .arg(Arg::with_name("appver") .short("v") .takes_value(true) .required(true) - .help("remove app ver"), - ) + .help("remove app ver")) .arg(meta_arg.clone()), ) .subcommand( @@ -525,117 +407,8 @@ async fn main_run() -> BuckyResult<()> { add_id_or_file_arg(SubCommand::with_name("show").about("show app obj")) .arg(meta_arg.clone()), ), - ) - .subcommand( - SubCommand::with_name("cmd") - .about("add/install/uninstall/start/stop/setpermission/setquota") - .subcommand( - SubCommand::with_name("add") - .about("add app") - .arg( - Arg::with_name("owner") - .short("o") - .long("owner") - .takes_value(true) - .required(true) - .help("app owner id"), - ) - .arg( - Arg::with_name("id") - .index(1) - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("install") - .about("install app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg( - Arg::with_name("version") - .short("value") - .long("version") - .takes_value(true) - .required(true) - .help("app version"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("start") - .about("install app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("stop") - .about("stop app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("remove") - .about("remove app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("uninstall") - .about("uninstall app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("setpermission") - .about("set app permission") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("setquota") - .about("set app quota") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ), - ) - .get_matches(); + ); + let matches = app.get_matches(); match matches.subcommand() { ("list", Some(matches)) => { @@ -715,7 +488,7 @@ async fn main_run() -> BuckyResult<()> { matches.is_present("status"), ); list.put(status); - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -728,7 +501,7 @@ async fn main_run() -> BuckyResult<()> { DecAppId::from_str(matches.value_of("appid").unwrap()).unwrap(); list.remove(&app_id); - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -739,7 +512,7 @@ async fn main_run() -> BuckyResult<()> { list.clear(); - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -777,38 +550,36 @@ async fn main_run() -> BuckyResult<()> { } // 需要config格式:[{id, ver, status}] for service in config.as_array().unwrap() { + let service = service.as_object().unwrap(); let app_id = DecAppId::from_str( - service - .as_object() - .unwrap() - .get("id") - .unwrap() - .as_str() - .unwrap(), + service.get("id").unwrap().as_str().unwrap(), ) .unwrap(); - let ver = service - .as_object() - .unwrap() - .get("ver") - .unwrap() - .as_str() - .unwrap() - .to_owned(); - let status = service - .as_object() - .unwrap() - .get("status") - .unwrap() - .as_i64() - .unwrap() - == 1; + let ver = service.get("ver").unwrap().as_str().unwrap(); + let status = service.get("status").unwrap().as_i64().unwrap() == 1; + + if matches.is_present("unpreview") { + info!("check preview version {} for app {}", ver, &app_id); + + if let Ok(mut app) = get_app_from_meta(app_id.object_id(), &target).await { + let pre_version = format!("{}-preview", ver); + if let Ok(id) = app.find_source(&pre_version) { + info!("find preview version {}, change to normal", &pre_version); + let desc = app.find_source_desc(&pre_version).map(|s|s.to_owned()); + app.remove_source(&pre_version); + app.set_source(ver.to_owned(), id, desc); + + target.save_obj(&app).await; + } + } + } + let status = - AppStatus::create(target.owner_id().unwrap(), app_id, ver, status); + AppStatus::create(target.owner_id().unwrap(), app_id, ver.to_owned(), status); list.put(status); } - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -878,7 +649,7 @@ async fn main_run() -> BuckyResult<()> { let ver = matches.value_of("appver").unwrap().to_owned(); app.set_source(ver, source, None); - save_obj(target, &app).await + target.save_obj(&app).await }) .await } @@ -890,7 +661,7 @@ async fn main_run() -> BuckyResult<()> { let ver = matches.value_of("appver").unwrap(); app.remove_source(&ver); - save_obj(target, &app).await + target.save_obj(&app).await }) .await } @@ -901,7 +672,7 @@ async fn main_run() -> BuckyResult<()> { app.clear_source(); - save_obj(target, &app).await + target.save_obj(&app).await }) .await } From bf6fa28ee390bf1f7a54c9ae1b49e1b4b5743ee6 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 21:28:04 +0800 Subject: [PATCH 126/553] Add semver support into dec_app core object and with test cases --- src/Cargo.lock | 1093 +++++++++-------- src/component/cyfs-core/Cargo.toml | 3 +- src/component/cyfs-core/src/app/dec_app.rs | 209 +++- .../cyfs-core/src/trans/trans_context.rs | 2 +- 4 files changed, 782 insertions(+), 525 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index ca0aa67f7..65f7f068f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -111,9 +111,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" [[package]] name = "android_logger" -version = "0.11.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" +checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" dependencies = [ "android_log-sys", "env_logger", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "app-manager" @@ -262,9 +262,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.8.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" dependencies = [ "concurrent-queue", "event-listener", @@ -283,23 +283,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.5.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" dependencies = [ - "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", + "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" dependencies = [ "async-channel", "async-executor", @@ -329,32 +329,31 @@ dependencies = [ [[package]] name = "async-io" -version = "1.12.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" dependencies = [ - "async-lock", "autocfg 1.1.0", "concurrent-queue", "futures-lite", "libc", "log 0.4.17", + "once_cell", "parking", "polling", "slab", "socket2", "waker-fn", - "windows-sys 0.42.0", + "winapi", ] [[package]] name = "async-lock" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" dependencies = [ "event-listener", - "futures-lite", ] [[package]] @@ -371,27 +370,27 @@ dependencies = [ [[package]] name = "async-process" -version = "1.6.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" +checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" dependencies = [ "async-io", - "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", + "once_cell", "signal-hook", - "windows-sys 0.42.0", + "winapi", ] [[package]] name = "async-recursion" -version = "1.0.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" +checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" dependencies = [ "proc-macro2", "quote", @@ -493,9 +492,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", @@ -526,9 +525,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" [[package]] name = "atty" @@ -536,7 +535,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -558,9 +557,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -774,16 +773,16 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" dependencies = [ "async-channel", - "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", + "once_cell", ] [[package]] @@ -794,14 +793,14 @@ checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" dependencies = [ "base64 0.13.1", "bollard-stubs", - "bytes 1.4.0", + "bytes 1.2.1", "chrono", "dirs-next", "futures-core", "futures-util", "hex", "http", - "hyper 0.14.24", + "hyper 0.14.20", "hyperlocal", "log 0.4.17", "pin-project", @@ -849,11 +848,13 @@ dependencies = [ [[package]] name = "bstr" -version = "1.3.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ + "lazy_static", "memchr", + "regex-automata", "serde", ] @@ -865,15 +866,15 @@ checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" [[package]] name = "byte-tools" @@ -883,9 +884,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.13.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" [[package]] name = "byteorder" @@ -905,15 +906,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.4.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "bzip2" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" dependencies = [ "bzip2-sys", "libc", @@ -950,9 +951,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -983,16 +984,16 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.45", + "time 0.1.44", "wasm-bindgen", "winapi", ] @@ -1108,7 +1109,7 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "memchr", ] @@ -1120,11 +1121,11 @@ checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" [[package]] name = "concurrent-queue" -version = "2.1.0" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ - "crossbeam-utils", + "cache-padded", ] [[package]] @@ -1301,22 +1302,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.7.1", + "memoffset", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1324,9 +1325,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if 1.0.0", ] @@ -1389,12 +1390,13 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.0" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ + "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -1429,9 +1431,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.91" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" dependencies = [ "cc", "cxxbridge-flags", @@ -1441,9 +1443,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.91" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" dependencies = [ "cc", "codespan-reporting", @@ -1456,15 +1458,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.91" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" [[package]] name = "cxxbridge-macro" -version = "1.0.91" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" dependencies = [ "proc-macro2", "quote", @@ -1511,7 +1513,7 @@ dependencies = [ "simple_logger 2.3.0", "sqlx", "url 2.3.0", - "zip 0.6.4", + "zip", ] [[package]] @@ -1563,7 +1565,7 @@ dependencies = [ "log 0.4.17", "lru_time_cache", "md5", - "nix 0.24.3", + "nix 0.24.2", "once_cell", "rand 0.7.3", "ringbuf", @@ -1619,7 +1621,7 @@ dependencies = [ "cyfs-util", "dirs 4.0.0", "log 0.4.17", - "sysinfo 0.26.9", + "sysinfo 0.26.5", ] [[package]] @@ -1635,7 +1637,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "time 0.1.45", + "time 0.1.44", "url 2.3.0", ] @@ -1659,7 +1661,7 @@ dependencies = [ "scan_dir", "sha2 0.8.2", "shared_memory", - "sysinfo 0.26.9", + "sysinfo 0.26.5", ] [[package]] @@ -1676,7 +1678,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "time 0.1.45", + "time 0.1.44", "url 2.3.0", ] @@ -1700,7 +1702,7 @@ version = "0.6.4" dependencies = [ "bip39", "cyfs-base", - "digest 0.10.6", + "digest 0.10.5", "hex", "hmac 0.12.1", "log 0.4.17", @@ -1766,6 +1768,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1776,8 +1779,10 @@ dependencies = [ "protoc-bin-vendored", "protoc-rust", "rand 0.8.5", + "semver 1.0.14", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1827,6 +1832,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.8", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.8", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.0" @@ -1835,7 +1899,7 @@ dependencies = [ "async-std", "async-trait", "async-tungstenite", - "bytes 1.4.0", + "bytes 1.2.1", "chrono", "cyfs-base", "cyfs-bdt", @@ -2122,7 +2186,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.4.0", + "bytes 1.2.1", "clap", "cyfs-base", "cyfs-bdt", @@ -2177,6 +2241,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -2194,18 +2260,18 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.6", - "prost-build 0.11.6", + "prost 0.11.8", + "prost-build 0.11.3", "protoc-bin-vendored", "rand 0.8.5", - "semver 1.0.16", + "semver 1.0.14", "serde", "serde_json", "sha2 0.8.2", "sqlx", "tide", "toml", - "zip 0.6.4", + "zip", ] [[package]] @@ -2251,7 +2317,7 @@ dependencies = [ "regex", "serde", "toml", - "toml_edit 0.15.0", + "toml_edit", ] [[package]] @@ -2336,7 +2402,7 @@ dependencies = [ "log 0.4.17", "log-panics", "named-lock", - "nix 0.24.3", + "nix 0.24.2", "once_cell", "rand 0.8.5", "rusqlite", @@ -2349,7 +2415,7 @@ dependencies = [ "url 2.3.0", "walkdir", "winapi", - "zip 0.6.4", + "zip", ] [[package]] @@ -2397,7 +2463,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.4", ] [[package]] @@ -2473,9 +2539,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -2548,9 +2614,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "either" -version = "1.8.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "email-encoding" @@ -2634,9 +2700,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "env_logger" -version = "0.10.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "log 0.4.17", "regex", @@ -2644,9 +2710,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.24" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" +checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" dependencies = [ "serde", ] @@ -2662,7 +2728,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itertools", - "paste 1.0.11", + "paste 1.0.9", "rustc-hex", "serde", "serde_json", @@ -2798,9 +2864,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -2837,14 +2903,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.20" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", - "windows-sys 0.45.0", + "windows-sys 0.42.0", ] [[package]] @@ -2867,9 +2933,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ "crc32fast", "miniz_oxide", @@ -2901,7 +2967,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.5", + "spin 0.9.4", ] [[package]] @@ -2961,9 +3027,9 @@ dependencies = [ [[package]] name = "fs_extra" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" [[package]] name = "fuchsia-cprng" @@ -2979,9 +3045,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", @@ -2994,9 +3060,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -3004,15 +3070,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-executor" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" dependencies = [ "futures-core", "futures-task", @@ -3022,20 +3088,20 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.11.2", + "parking_lot 0.12.1", ] [[package]] name = "futures-io" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-lite" @@ -3054,9 +3120,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", @@ -3065,21 +3131,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-channel", "futures-core", @@ -3100,7 +3166,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.4.0", + "bytes 1.2.1", "clap", "cyfs-base", "cyfs-bdt", @@ -3180,9 +3246,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" +checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" dependencies = [ "proc-macro2", "quote", @@ -3191,21 +3257,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ "aho-corasick", "bstr", @@ -3216,9 +3282,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" dependencies = [ "futures-channel", "futures-core", @@ -3226,13 +3292,42 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.8", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" -version = "0.3.15" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "fnv", "futures-core", "futures-sink", @@ -3241,7 +3336,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.7", + "tokio-util 0.7.4", "tracing", ] @@ -3307,9 +3402,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" dependencies = [ "unicode-segmentation", ] @@ -3323,15 +3418,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - [[package]] name = "hex" version = "0.4.3" @@ -3419,7 +3505,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -3446,13 +3532,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "fnv", - "itoa", + "itoa 1.0.4", ] [[package]] @@ -3461,7 +3547,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "http", "pin-project-lite 0.2.9", ] @@ -3537,7 +3623,7 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time 0.1.45", + "time 0.1.44", "traitobject", "typeable", "unicase 1.4.2", @@ -3546,11 +3632,11 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.24" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "futures-channel", "futures-core", "futures-util", @@ -3559,7 +3645,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 1.0.4", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -3576,16 +3662,16 @@ checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" dependencies = [ "futures-util", "hex", - "hyper 0.14.24", + "hyper 0.14.20", "pin-project", "tokio", ] [[package]] name = "iana-time-zone" -version = "0.1.53" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3687,9 +3773,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -3702,7 +3788,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" dependencies = [ "indoc-impl", - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", ] [[package]] @@ -3711,7 +3797,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", "proc-macro2", "quote", "syn", @@ -3804,9 +3890,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.5" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jni" @@ -3839,21 +3931,18 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" -dependencies = [ - "cpufeatures", -] +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] name = "kv-log-macro" @@ -3895,7 +3984,7 @@ dependencies = [ "idna 0.2.1", "mime 0.3.16", "native-tls", - "nom 7.1.3", + "nom 7.1.1", "once_cell", "quoted_printable", "socket2", @@ -3916,15 +4005,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.139" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libm" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" [[package]] name = "libsecp256k1" @@ -3955,9 +4044,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" dependencies = [ "cc", ] @@ -4026,7 +4115,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" dependencies = [ - "nix 0.23.2", + "nix 0.23.1", "winapi", ] @@ -4038,9 +4127,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.10" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "maybe-uninit" @@ -4062,9 +4151,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.9" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" +checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" dependencies = [ "libc", ] @@ -4078,15 +4167,6 @@ dependencies = [ "autocfg 1.1.0", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "memzero" version = "0.1.0" @@ -4168,23 +4248,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.6" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.36.1", ] [[package]] @@ -4219,9 +4299,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", @@ -4247,27 +4327,27 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.2" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] name = "nix" -version = "0.24.3" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -4283,23 +4363,14 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.3" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", ] -[[package]] -name = "nom8" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" -dependencies = [ - "memchr", -] - [[package]] name = "ntapi" version = "0.4.0" @@ -4352,9 +4423,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" dependencies = [ "byteorder", "lazy_static", @@ -4411,11 +4482,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] @@ -4430,18 +4501,18 @@ dependencies = [ [[package]] name = "object" -version = "0.30.3" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "ood-control" @@ -4466,7 +4537,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sysinfo 0.26.9", + "sysinfo 0.26.5", "tide", ] @@ -4500,7 +4571,7 @@ dependencies = [ "serde_json", "tide", "toml", - "zip 0.6.4", + "zip", ] [[package]] @@ -4550,9 +4621,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.45" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -4582,9 +4653,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.80" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg 1.1.0", "cc", @@ -4612,7 +4683,7 @@ dependencies = [ "sha2 0.8.2", "simple_logger 2.3.0", "walkdir", - "zip 0.6.4", + "zip", ] [[package]] @@ -4635,7 +4706,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.3.0", + "proc-macro-crate 1.2.1", "proc-macro2", "quote", "syn", @@ -4655,7 +4726,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.6", + "parking_lot_core 0.8.5", ] [[package]] @@ -4665,14 +4736,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.4", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", @@ -4684,15 +4755,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec 1.10.0", - "windows-sys 0.45.0", + "windows-sys 0.42.0", ] [[package]] @@ -4713,14 +4784,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", ] [[package]] name = "paste" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "paste-impl" @@ -4728,7 +4799,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", ] [[package]] @@ -4737,7 +4808,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.5", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -4777,9 +4848,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", @@ -4847,9 +4918,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" @@ -4900,16 +4971,16 @@ dependencies = [ [[package]] name = "polling" -version = "2.5.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "windows-sys 0.42.0", + "winapi", ] [[package]] @@ -4925,15 +4996,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "prettyplease" -version = "0.1.23" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" +checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" dependencies = [ "proc-macro2", "syn", @@ -4941,9 +5012,9 @@ dependencies = [ [[package]] name = "primal" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b53cc99c892c461727618e8a63806c94b09ae13c494dc5fc70a7557b3a2f071" +checksum = "389bfb36ac527b5fe21a57f87bc7956af45cbeb2de7750b90b7ebac6770e715e" dependencies = [ "primal-check", "primal-estimate", @@ -4976,9 +5047,9 @@ checksum = "7374f14c76f23e1271e6be806981ac5dd9e52b59132b0a2f10bcc412495f9159" [[package]] name = "primal-sieve" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f2a14766f8c543620824b5b2cec356abf2681b76966a7ac4b4ed2c0011e696a" +checksum = "95fee6031f66b44e8e004ac9bf81fd1c5abcbbb25bd392bc27429daa1759654a" dependencies = [ "primal-bit", "primal-estimate", @@ -5009,12 +5080,13 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ "once_cell", - "toml_edit 0.18.1", + "thiserror", + "toml", ] [[package]] @@ -5028,9 +5100,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.20+deprecated" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-hack-impl" @@ -5040,9 +5112,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -5053,18 +5125,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" +checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" dependencies = [ - "bytes 1.4.0", - "prost-derive 0.11.6", + "bytes 1.2.1", + "prost-derive 0.11.8", ] [[package]] @@ -5073,7 +5145,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "heck 0.3.3", "itertools", "lazy_static", @@ -5089,20 +5161,20 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.6" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" +checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604" dependencies = [ - "bytes 1.4.0", - "heck 0.4.1", + "bytes 1.2.1", + "heck 0.4.0", "itertools", "lazy_static", "log 0.4.17", "multimap", "petgraph", "prettyplease", - "prost 0.11.6", - "prost-types 0.11.6", + "prost 0.11.8", + "prost-types 0.11.2", "regex", "syn", "tempfile", @@ -5124,9 +5196,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" +checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" dependencies = [ "anyhow", "itertools", @@ -5141,18 +5213,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.6" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" +checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" dependencies = [ - "bytes 1.4.0", - "prost 0.11.6", + "bytes 1.2.1", + "prost 0.11.8", ] [[package]] @@ -5161,7 +5233,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", ] [[package]] @@ -5301,18 +5373,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.23" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "quoted_printable" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" +checksum = "20f14e071918cbeefc5edc986a7aa92c425dae244e003a35e1cdddb5ca39b5cb" [[package]] name = "radium" @@ -5512,19 +5584,21 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ + "autocfg 1.1.0", + "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -5580,20 +5654,26 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remove_dir_all" @@ -5634,7 +5714,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "rustc-hex", ] @@ -5684,8 +5764,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", - "digest 0.10.6", - "num-bigint-dig 0.8.2", + "digest 0.10.5", + "num-bigint-dig 0.8.1", "num-integer", "num-iter", "num-traits", @@ -5821,15 +5901,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "safemem" @@ -5864,7 +5944,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.3.0", + "proc-macro-crate 1.2.1", "proc-macro2", "quote", "syn", @@ -5881,11 +5961,12 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ - "windows-sys 0.42.0", + "lazy_static", + "windows-sys 0.36.1", ] [[package]] @@ -5896,9 +5977,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" [[package]] name = "sct" @@ -5912,9 +5993,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.8.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -5925,9 +6006,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -5944,9 +6025,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -5956,9 +6037,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] @@ -5975,9 +6056,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -5995,11 +6076,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" dependencies = [ - "itoa", + "itoa 1.0.4", "ryu", "serde", ] @@ -6022,7 +6103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.4", "ryu", "serde", ] @@ -6051,13 +6132,13 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -6077,7 +6158,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -6119,7 +6200,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.5", ] [[package]] @@ -6165,16 +6246,16 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.17", - "nix 0.23.2", + "nix 0.23.1", "rand 0.8.5", "win-sys", ] [[package]] name = "signal-hook" -version = "0.3.15" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" dependencies = [ "libc", "signal-hook-registry", @@ -6182,9 +6263,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] @@ -6218,7 +6299,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.19", + "time 0.3.16", "winapi", ] @@ -6231,7 +6312,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.19", + "time 0.3.16", "winapi", ] @@ -6244,15 +6325,15 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.19", + "time 0.3.16", "windows-sys 0.42.0", ] [[package]] name = "slab" -version = "0.4.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ "autocfg 1.1.0", ] @@ -6331,9 +6412,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" dependencies = [ "lock_api", ] @@ -6355,7 +6436,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom 7.1.3", + "nom 7.1.1", "unicode_categories", ] @@ -6379,11 +6460,11 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.4.0", + "bytes 1.2.1", "chrono", "crc", "crossbeam-queue", - "digest 0.10.6", + "digest 0.10.5", "either", "event-listener", "flume", @@ -6396,14 +6477,14 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa", + "itoa 1.0.4", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "num-bigint 0.3.3", "once_cell", - "paste 1.0.11", + "paste 1.0.9", "percent-encoding 2.2.0", "rand 0.8.5", "rsa 0.6.1", @@ -6428,7 +6509,7 @@ checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.4.1", + "heck 0.4.0", "once_cell", "proc-macro2", "quote", @@ -6582,9 +6663,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -6605,9 +6686,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.9" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" +checksum = "ade661fa5e048ada64ad7901713301c21d2dbc5b65ee7967de8826c111452960" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -6687,9 +6768,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -6715,18 +6796,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -6735,11 +6816,10 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ - "cfg-if 1.0.0", "once_cell", ] @@ -6777,9 +6857,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -6803,16 +6883,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.19" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" +checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" dependencies = [ - "itoa", + "itoa 1.0.4", "libc", "num_threads", "serde", "time-core", - "time-macros 0.2.7", + "time-macros 0.2.5", ] [[package]] @@ -6827,15 +6907,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", "time-macros-impl", ] [[package]] name = "time-macros" -version = "0.2.7" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" +checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" dependencies = [ "time-core", ] @@ -6846,7 +6926,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", + "proc-macro-hack 0.5.19", "proc-macro2", "quote", "standback", @@ -6883,19 +6963,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.25.0" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg 1.1.0", - "bytes 1.4.0", + "bytes 1.2.1", "libc", "memchr", "mio", "num_cpus", "pin-project-lite 0.2.9", "socket2", - "windows-sys 0.42.0", + "winapi", ] [[package]] @@ -6904,7 +6984,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "futures-core", "futures-sink", "log 0.4.17", @@ -6914,11 +6994,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ - "bytes 1.4.0", + "bytes 1.2.1", "futures-core", "futures-sink", "pin-project-lite 0.2.9", @@ -6928,9 +7008,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "indexmap", "serde", @@ -6938,9 +7018,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" [[package]] name = "toml_edit" @@ -6954,17 +7034,6 @@ dependencies = [ "toml_datetime", ] -[[package]] -name = "toml_edit" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" -dependencies = [ - "indexmap", - "nom8", - "toml_datetime", -] - [[package]] name = "tower-service" version = "0.3.2" @@ -6973,9 +7042,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if 1.0.0", "pin-project-lite 0.2.9", @@ -7009,9 +7078,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" @@ -7021,7 +7090,7 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.4.0", + "bytes 1.2.1", "http", "httparse", "log 0.4.17", @@ -7040,15 +7109,15 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.16.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "uint" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" dependencies = [ "byteorder", "crunchy", @@ -7076,15 +7145,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.10" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" @@ -7097,9 +7166,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" @@ -7121,9 +7190,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unindent" -version = "0.1.11" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" [[package]] name = "universal-hash" @@ -7198,9 +7267,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version-compare" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" [[package]] name = "version_check" @@ -7270,9 +7339,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "serde", @@ -7282,9 +7351,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log 0.4.17", @@ -7297,9 +7366,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7309,9 +7378,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7319,9 +7388,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -7332,15 +7401,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -7385,9 +7454,9 @@ dependencies = [ [[package]] name = "which" -version = "4.4.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", "libc", @@ -7461,48 +7530,37 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.1", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.1", + "windows_x86_64_msvc 0.42.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] name = "windows_aarch64_msvc" @@ -7512,9 +7570,15 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" @@ -7524,9 +7588,15 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" @@ -7536,9 +7606,15 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" @@ -7548,15 +7624,21 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" @@ -7566,9 +7648,15 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "wyz" @@ -7596,9 +7684,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.3" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", @@ -7606,20 +7694,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zip" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" -dependencies = [ - "byteorder", - "bzip2", - "crc32fast", - "flate2", - "thiserror", - "time 0.1.45", -] - [[package]] name = "zip" version = "0.6.4" @@ -7636,19 +7710,19 @@ dependencies = [ "hmac 0.12.1", "pbkdf2", "sha1 0.10.5", - "time 0.3.19", + "time 0.3.16", "zstd", ] [[package]] name = "zip-extract" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c5cc0309f6e81ab96c2b43d5e935025f8732c886690be8f78f68e06bad1d274" +checksum = "bb654964c003959ed64cbd0d7b329bcdcbd9690facd50c8617748d3622543972" dependencies = [ "log 0.4.17", "thiserror", - "zip 0.5.13", + "zip", ] [[package]] @@ -7722,11 +7796,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.7+zstd.1.5.4" +version = "2.0.1+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" +checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" dependencies = [ "cc", "libc", - "pkg-config", ] diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index 67b8928b1..d478a8d58 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -30,4 +30,5 @@ hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } sha2 = { version = '0.8' } -generic-array = { version = '0.12', default-features = false, features = ['serde'] } \ No newline at end of file +generic-array = { version = '0.12', default-features = false, features = ['serde'] } +semver = "1.0" diff --git a/src/component/cyfs-core/src/app/dec_app.rs b/src/component/cyfs-core/src/app/dec_app.rs index 83ca8aab2..1a32ccc1c 100644 --- a/src/component/cyfs-core/src/app/dec_app.rs +++ b/src/component/cyfs-core/src/app/dec_app.rs @@ -1,6 +1,6 @@ +use crate::codec::protos; use crate::coreobj::CoreObjectType; use cyfs_base::*; -use crate::codec::protos; use serde::Serialize; use std::collections::hash_map::RandomState; @@ -34,7 +34,7 @@ pub struct DecAppContent { icon: Option, desc: Option, source_desc: HashMap, - tags: HashMap + tags: HashMap, } impl BodyContent for DecAppContent { @@ -65,7 +65,7 @@ impl ProtobufTransform for DecAppContent { source_desc, icon: None, desc: None, - tags + tags, }; if value.icon.is_some() { @@ -83,19 +83,23 @@ impl ProtobufTransform<&DecAppContent> for protos::DecAppContent { let source_map: BTreeMap = value.source.clone().into_iter().collect(); let mut source = vec![]; for (k, v) in source_map { - source.push(protos::StringBytesMapItem{key: k, value: v.to_vec()?}); + source.push(protos::StringBytesMapItem { + key: k, + value: v.to_vec()?, + }); } - let source_desc_map: BTreeMap = value.source_desc.clone().into_iter().collect(); + let source_desc_map: BTreeMap = + value.source_desc.clone().into_iter().collect(); let mut source_desc = vec![]; for (k, v) in source_desc_map { - source_desc.push(protos::StringStringMapItem {key: k, value: v}); + source_desc.push(protos::StringStringMapItem { key: k, value: v }); } - let tags_map: BTreeMap = value.tags.clone().into_iter().collect(); + let tags_map: BTreeMap = value.tags.clone().into_iter().collect(); let mut tags = vec![]; for (k, v) in tags_map { - tags.push(protos::StringStringMapItem {key: k, value: v}); + tags.push(protos::StringStringMapItem { key: k, value: v }); } let mut ret = Self { @@ -103,7 +107,7 @@ impl ProtobufTransform<&DecAppContent> for protos::DecAppContent { source_desc, icon: None, desc: None, - tags + tags, }; if let Some(icon) = &value.icon { @@ -129,8 +133,15 @@ pub trait DecAppObj { fn name(&self) -> &str; fn app_desc(&self) -> Option<&str>; fn icon(&self) -> Option<&str>; + + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str>; + + fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult; fn find_source(&self, version: &str) -> BuckyResult; + + fn find_source_desc_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult>; fn find_source_desc(&self, version: &str) -> Option<&str>; + fn remove_source(&mut self, version: &str); fn clear_source(&mut self); fn set_source(&mut self, version: String, id: ObjectId, desc: Option); @@ -144,6 +155,31 @@ pub trait DecAppObj { fn generate_id(owner: ObjectId, id: &str) -> ObjectId; } +pub struct SemVerHelper {} + +impl SemVerHelper { + // x.y.?.z => x.y.z + // x.y.?.z-? => x.y.z-? + pub fn fix_semver(ver: &str) -> String { + let mut top: Vec<&str> = ver.split('-').collect(); + let mut ret: Vec<&str> = top[0].split('.').collect(); + if ret.len() == 4 { + ret.remove(2); + } + + let ret = ret.join("."); + let ret = if top.len() > 1 { + top[0] = &ret; + top.join("-") + } else { + ret + }; + + // println!("{} -> {}", ver, ret); + ret + } +} + // 同owner, 同id的AppId应该始终相同,允许不同的话会造成混乱 impl DecAppObj for DecApp { fn create(owner: ObjectId, id: &str) -> Self { @@ -173,6 +209,90 @@ impl DecAppObj for DecApp { self.body_expect("").content().icon.as_deref() } + // https://nodesource.com/blog/semver-tilde-and-caret/ + // When pre is specified, all matching prerelease versions will be included; + // otherwise, only all versions that do not contain any prerelease will be matched + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str> { + let name = self.name(); + let id = self.desc().calculate_id(); + + let req_version = semver::VersionReq::parse(req_semver).map_err(|e| { + let msg = format!( + "invalid semver request string! id={}, name={}, value={}, {}", + id, name, req_semver, e + ); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + let list: Vec<_> = self + .body_expect("") + .content() + .source + .keys() + .map(|key| { + let new_version = SemVerHelper::fix_semver(&key); + (key, new_version) + }) + .collect(); + + let mut semver_list = vec![]; + for (version, new_version) in list { + let mut semver = semver::Version::parse(&new_version).map_err(|e| { + let msg = format!( + "invalid semver string! id={}, name={}, value={}, {}", + id, name, version, e, + ); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + if !semver.pre.is_empty() { + if let Some(pre) = pre { + if semver.pre.as_str() != pre { + continue; + } + semver.pre = semver::Prerelease::EMPTY; + } else { + continue; + } + } + + semver_list.push((version, semver)); + } + + semver_list.sort_by(|left, right| right.1.partial_cmp(&left.1).unwrap()); + + let ret = semver_list.iter().find(|(version, semver)| { + if req_version.matches(semver) { + info!( + "app version matched: id={}, name={}, req={}, got={}", + id, name, req_semver, version + ); + true + } else { + false + } + }); + + if ret.is_none() { + let msg = format!( + "no matching semver found for app: id={}, name={}, req={}", + id, name, req_semver + ); + warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); + } + + let (version, _) = ret.unwrap(); + Ok(version) + } + + fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult { + let version = self.find_version(req_semver, pre)?; + self.find_source(&version) + } + fn find_source(&self, version: &str) -> BuckyResult { self.body_expect("") .content() @@ -182,6 +302,11 @@ impl DecAppObj for DecApp { .ok_or(BuckyError::from(BuckyErrorCode::NotFound)) } + fn find_source_desc_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult> { + let version = self.find_version(req_semver, pre)?; + Ok(self.find_source_desc(&version)) + } + fn find_source_desc(&self, version: &str) -> Option<&str> { self.body_expect("") .content() @@ -248,10 +373,7 @@ impl DecAppObj for DecApp { } fn remove_tag(&mut self, tag: &str) { - self.body_mut_expect("") - .content_mut() - .tags - .remove(tag); + self.body_mut_expect("").content_mut().tags.remove(tag); } fn tags(&self) -> &HashMap { @@ -261,4 +383,65 @@ impl DecAppObj for DecApp { fn generate_id(owner: ObjectId, id: &str) -> ObjectId { Self::create(owner, id).desc().calculate_id() } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test() { + let owner = ObjectId::default(); + let mut dec_app = DecApp::create(owner.clone(), "test-dec-app"); + dec_app.set_source("1.0.0".to_owned(), owner.clone(), None); + dec_app.set_source("1.0.1".to_owned(), owner.clone(), None); + dec_app.set_source("1.0.2".to_owned(), owner.clone(), None); + dec_app.set_source("1.1.2".to_owned(), owner.clone(), None); + dec_app.set_source("1.1.5".to_owned(), owner.clone(), None); + + dec_app.set_source("1.3.7".to_owned(), owner.clone(), None); + dec_app.set_source("1.3.10".to_owned(), owner.clone(), None); + dec_app.set_source("1.4.0.20".to_owned(), owner.clone(), None); + dec_app.set_source("1.4.1.21-preview".to_owned(), owner.clone(), None); + dec_app.set_source("1.5.1.22-preview".to_owned(), owner.clone(), None); + + dec_app.set_source("2.5.28".to_owned(), owner.clone(), None); + dec_app.set_source("2.5.30".to_owned(), owner.clone(), None); + + let ret = dec_app.find_version("*", None).unwrap(); + assert_eq!(ret, "2.5.30"); + + let ret = dec_app.find_version("2.5.28", None).unwrap(); + assert_eq!(ret, "2.5.30"); + + let ret = dec_app.find_version("=1.0", None).unwrap(); + assert_eq!(ret, "1.0.2"); + + // ^ first none zero version seg, and is default if not present + + dec_app.find_version("=1.4.21-preview", None).unwrap_err(); + + let ret = dec_app.find_version("=1.4.21", Some("preview")).unwrap(); + assert_eq!(ret, "1.4.1.21-preview"); + let ret = dec_app.find_version("1.4", Some("preview")).unwrap(); + assert_eq!(ret, "1.5.1.22-preview"); + let ret = dec_app.find_version("1.0", Some("preview")).unwrap(); + assert_eq!(ret, "1.5.1.22-preview"); + + let ret = dec_app.find_version("~1.4", None).unwrap(); + assert_eq!(ret, "1.4.0.20"); + + // ~ second none zero version seg + let ret = dec_app.find_version("~1.1", None).unwrap(); + assert_eq!(ret, "1.1.5"); + + let ret = dec_app.find_version("<1.3", None).unwrap(); + assert_eq!(ret, "1.1.5"); + + let ret = dec_app.find_version("=1.3", None).unwrap(); + assert_eq!(ret, "1.3.10"); + + let ret = dec_app.find_version("<=1.3.8", None).unwrap(); + assert_eq!(ret, "1.3.7"); + } } \ No newline at end of file diff --git a/src/component/cyfs-core/src/trans/trans_context.rs b/src/component/cyfs-core/src/trans/trans_context.rs index 9f2e9328f..ad657cd24 100644 --- a/src/component/cyfs-core/src/trans/trans_context.rs +++ b/src/component/cyfs-core/src/trans/trans_context.rs @@ -308,7 +308,7 @@ mod test { #[test] fn test() { let id = ObjectId::from_str("5r4MYfFdfQ5dvAvD2WZ8wd7iKPFpWLSiAnMuTui912xL").unwrap(); - let mut context = TransContext::new(id, "/a/b/c"); + let mut context = TransContext::new(Some(id), "/a/b/c"); let device = TransContextDevice { target: DeviceId::from_str("5bnZHzXvMmqiiua3iodiaYqWR24QbZE5o8r35bH8y9Yh").unwrap(), From c71e3c731f6b1c93c9279b887c3e599723003f34 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 127/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/Cargo.lock | 1 + src/service/ood-daemon/Cargo.toml | 3 +- .../src/config/device_config_manager.rs | 2 +- .../ood-daemon/src/config/system_config.rs | 76 +++++++---- src/service/ood-daemon/src/config/version.rs | 70 +++++++++-- .../ood-daemon/src/config_repo/meta.rs | 119 +++++++++--------- 6 files changed, 172 insertions(+), 99 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 65f7f068f..485628c38 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4567,6 +4567,7 @@ dependencies = [ "once_cell", "ood-control", "rand 0.7.3", + "semver 1.0.14", "serde", "serde_json", "tide", diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index c0c092df8..dad44f82a 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -35,4 +35,5 @@ toml = "0.5" http-types = "2.12" hex = "0.4" tide = "0.16" -rand = '0.7' \ No newline at end of file +rand = '0.7' +semver = "1.0" \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 179db7c86..9667a5e30 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -38,7 +38,7 @@ impl DeviceConfigManager { Box::new(repo) as Box } else if desc == "cyfs_repo" || desc == "device" { let mut repo = DeviceConfigMetaRepo::new(); - if let Err(e) = repo.init(&desc, &get_system_config().version) { + if let Err(e) = repo.init(&desc, &get_system_config().service_list_version) { return Err(e); } diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 0b5fc2bba..fa50b80f4 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -1,10 +1,11 @@ use super::path::PATHS; -use super::version::ServiceListVersion; +use super::version::{ServiceVersion, ServiceListVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; use std::path::Path; +use std::str::FromStr; use std::sync::Arc; #[derive(Debug)] @@ -13,8 +14,14 @@ pub struct SystemConfig { // ServiceList对象会使用该id+version,来计算当前依赖的ServiceList对象,并从链上拉取 pub config_desc: String, - // 版本 - pub version: ServiceListVersion, + // service list version + pub service_list_version: ServiceListVersion, + + // service version + pub service_version: ServiceVersion, + + // enable preview + pub preview: bool, // 当前平台对应的target pub target: String, @@ -25,8 +32,11 @@ impl SystemConfig { Self { config_desc: String::from("cyfs_repo"), - // now all the channels should use Nightly version, not support any other version anymore! - version: ServiceListVersion::Nightly, + service_list_version: ServiceListVersion::default(), + + service_version: ServiceVersion::default(), + preview: false, + target: String::from(""), } } @@ -47,19 +57,34 @@ impl SystemConfig { let node = self.load_as_json(&config_file).await?; - self.parse_config(node).await + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) } async fn load_as_json(&self, file_path: &Path) -> BuckyResult { - let content = async_std::fs::read_to_string(&file_path).await.map_err(|e| { - let msg = format!("load system config to string error! file={}, {}", file_path.display(), e); - error!("{}", msg); - - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let content = async_std::fs::read_to_string(&file_path) + .await + .map_err(|e| { + let msg = format!( + "load system config to string error! file={}, {}", + file_path.display(), + e + ); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; let node = toml::from_str(&content).map_err(|e| { - let msg = format!("load system config invalid format! content={}, file={}, {}", content, file_path.display(), e); + let msg = format!( + "load system config invalid format! content={}, file={}, {}", + content, + file_path.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -91,9 +116,7 @@ impl SystemConfig { } "repository" => { if v.is_array() { - REPO_MANAGER - .load(v.as_array().unwrap()) - .await?; + REPO_MANAGER.load(v.as_array().unwrap()).await?; } else { let msg = format!("config invalid repository node format"); error!("{}", msg); @@ -115,10 +138,18 @@ impl SystemConfig { "config_desc" => { self.config_desc = TomlHelper::decode_from_string(v)?; } - "version" => { - warn!("version field will be ignored! version={:?}", v); - // let v: String = TomlHelper::decode_from_string(v)?; - // self.version = ServiceListVersion::from_str(&v)?; + "service_list_version" => { + let v: String = TomlHelper::decode_from_string(v)?; + + self.service_list_version = ServiceListVersion::from_str(v.trim())?; + } + "service_version" => { + let v: String = TomlHelper::decode_from_string(v)?; + + self.service_version = ServiceVersion::from_str(v.trim())?; + } + "preview" => { + self.preview = TomlHelper::decode_from_boolean(v)?; } "target" => { self.target = TomlHelper::decode_from_string(v)?; @@ -148,15 +179,14 @@ static SYSTEM_CONFIG: OnceCell> = OnceCell::new(); // 只在进程初始化时候调用一次 pub async fn init_system_config() -> BuckyResult<()> { - let mut system_config = SystemConfig::new(); system_config.load_config().await?; SYSTEM_CONFIG.set(Arc::new(system_config)).unwrap(); - + Ok(()) } pub fn get_system_config() -> Arc { SYSTEM_CONFIG.get().unwrap().clone() -} \ No newline at end of file +} diff --git a/src/service/ood-daemon/src/config/version.rs b/src/service/ood-daemon/src/config/version.rs index fcbd57cf8..fd8a7a1e3 100644 --- a/src/service/ood-daemon/src/config/version.rs +++ b/src/service/ood-daemon/src/config/version.rs @@ -2,13 +2,10 @@ use cyfs_base::*; use std::str::FromStr; -// 版本列表定义 #[derive(Debug)] pub enum ServiceListVersion { - Nightly, - Latest, - Stable, - Specific(String), + Nightly, // default version + Specific(String), // user confined } // FIXME 默认使用nightly,以后会切换成stable @@ -22,8 +19,6 @@ impl ToString for ServiceListVersion { fn to_string(&self) -> String { match *self { Self::Nightly => "nightly", - Self::Latest => "latest", - Self::Stable => "stable", Self::Specific(ref v) => v.as_str(), } .to_owned() @@ -33,11 +28,64 @@ impl ToString for ServiceListVersion { impl FromStr for ServiceListVersion { type Err = BuckyError; fn from_str(s: &str) -> BuckyResult { - let ret = match s { + let ret = match s.trim() { "nightly" => Self::Nightly, - "latest" => Self::Latest, - "stable" => Self::Stable, - _ => Self::Specific(s.to_owned()), + v @ _ => { + Self::Specific(v.to_owned()) + } + }; + + Ok(ret) + } +} + + +// 版本列表定义 +#[derive(Debug)] +pub enum ServiceVersion { + Default, // use the version config in service list + Specific(String), // semver, * as the newest version +} + +impl ServiceVersion { + pub fn is_default(&self) -> bool { + match self { + Self::Default => true, + _ => false, + } + } +} + +impl Default for ServiceVersion { + fn default() -> Self { + Self::Default + } +} + +impl ToString for ServiceVersion { + fn to_string(&self) -> String { + match *self { + Self::Default => "default", + Self::Specific(ref v) => v.as_str(), + } + .to_owned() + } +} + +impl FromStr for ServiceVersion { + type Err = BuckyError; + fn from_str(s: &str) -> BuckyResult { + let ret = match s.trim() { + "default" => Self::Default, + v @ _ => { + let _req_version = semver::VersionReq::parse(v).map_err(|e| { + let msg = format!("invalid semver request string! value={}, {}", v, e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + Self::Specific(v.to_owned()) + } }; Ok(ret) diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 7aa460dca..e57133587 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -78,59 +78,37 @@ impl DeviceConfigGenerator { }); } - pub fn update_service(&mut self, service: &DecApp, fid: &str) { + pub fn update_service(&mut self, service: &DecApp, fid: &str, version: &str) { let id = service.desc().calculate_id().to_string(); let name = service.name(); - info!("will update service: id={}, name={}, fid={}", id, name, fid); + info!( + "will update service: id={}, name={}, fid={}, version={}", + id, name, fid, version + ); for item in self.service.iter_mut() { if item.name == name { item.id = id.clone(); item.fid = fid.to_owned(); + item.version = version.to_owned(); } else if item.id == id { item.name = name.to_owned(); item.fid = fid.to_owned(); + item.version = version.to_owned(); } } } - pub fn update_service_status(&mut self, status: &AppStatus) -> bool { + fn add_service(&mut self, status: &AppStatus) { let id = status.app_id().to_string(); let version = status.version(); + let target_state = match status.status() { true => ServiceState::Run, false => ServiceState::Stop, }; - for item in self.service.iter_mut() { - if item.id == id { - let mut version_changed = false; - - // 检查状态是不是发生改变 - if item.target_state != target_state { - item.target_state = target_state; - info!( - "service target state changed! id={}, name={} target state: {} -> {}", - item.id, item.name, item.target_state, target_state - ); - } - - // 检查版本是不是发生改变 - if item.version != version { - info!( - "service version changed! id={}, name={} version: {} -> {}", - item.id, item.name, item.version, version - ); - item.version = version.to_owned(); - - // 版本更新后,需要拉取最新的fid - version_changed = true; - } - return version_changed; - } - } - - info!("new service item: id={}, version={}", id, version); + debug!("new service item: id={}, version={}", id, version); let mut service = ServiceConfig::new(); service.id = id; service.version = version.to_owned(); @@ -139,8 +117,6 @@ impl DeviceConfigGenerator { self.service.push(service); // fid+name需要从DecApp对象获取 - - true } } @@ -175,11 +151,7 @@ impl DeviceConfigMetaRepo { } } - pub fn init( - &mut self, - config_desc: &str, - version: &ServiceListVersion, - ) -> Result<(), BuckyError> { + pub fn init(&mut self, config_desc: &str, version: &ServiceListVersion) -> Result<(), BuckyError> { assert!(self.desc.len() == 0); self.desc = config_desc.to_owned(); @@ -195,7 +167,7 @@ impl DeviceConfigMetaRepo { ); info!( - "device config repo: device_id={}, app_list_id={}, version={}", + "device config repo: device_id={}, service_list_id={}, version={}", device_id, service_list_id, version ); @@ -328,7 +300,7 @@ impl DeviceConfigMetaRepo { let fid = format!("{}/{}", dir_id, target); - info!("get fid from dir, dir={}, fid={}", dir_id, fid); + debug!("get fid from dir, dir={}, fid={}", dir_id, fid); Ok(fid) } @@ -345,15 +317,38 @@ impl DeviceConfigMetaRepo { &self, device_config: &mut DeviceConfigGenerator, service_id: &ObjectId, - version: &str, + version_in_service_list: &str, ) -> BuckyResult<()> { let service = self.load_service(service_id).await?; - let ret = service.find_source(version); + // first find the correct version + let config_version = match &get_system_config().service_version { + ServiceVersion::Default => version_in_service_list.to_owned(), + ServiceVersion::Specific(v) => v.clone(), + }; + + let preview = match get_system_config().preview { + true => Some("preview"), + false => None, + }; + + let version = service.find_version(&config_version, preview).map_err(|e| { + let msg = format!( + "find version from service object failed! id={}, configed version={}, preview={:?}, {}", + service_id, config_version, preview, e, + ); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::NotFound, msg) + })?; + + let ret = service.find_source(&version); if ret.is_err() { let msg = format!( - "get version from service object failed! id={}, version={}", - service_id, version + "get version from service object failed! id={}, version={}, {}", + service_id, + version, + ret.unwrap_err(), ); error!("{}", msg); @@ -369,7 +364,7 @@ impl DeviceConfigMetaRepo { let fid = self.load_fid(&dir_id, dir)?; // 更新 - device_config.update_service(&service, &fid); + device_config.update_service(&service, &fid, version); Ok(()) } @@ -380,22 +375,19 @@ impl DeviceConfigMetaRepo { ) -> BuckyResult { let mut device_config = DeviceConfigGenerator::new(); for (id, status) in service_list.app_list() { - debug!("got service item from service list: {}", id); - - let version_changed = device_config.update_service_status(status); - if version_changed { - let version = status.version(); - - self.load_service_fid(&mut device_config, id.object_id(), version) - .await - .map_err(|e| { - error!( - "load service fid failed! id={}, version={}, {}", - id, version, e - ); - e - })?; - } + device_config.add_service(status); + + let version = status.version(); + + self.load_service_fid(&mut device_config, id.object_id(), version) + .await + .map_err(|e| { + error!( + "load service fid failed! id={}, version={}, {}", + id, version, e + ); + e + })?; } // info!("list {:?}", self.device_config.lock().uwnrap().service); @@ -438,7 +430,8 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { // 从mete-chain拉取对应的service_list let service_list = self.load_service_list().await?; - { + // Only in the default version case, it will use the cache of servicelist + if get_system_config().service_version.is_default() { let cache = self.cache.lock().unwrap(); if let Some(cache) = &*cache { if Self::compare_service_list(&cache.service_list, &service_list) { From 7d58948dd390689c4e8a03f1ee3d6c6548c7f50a Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 01:53:06 +0800 Subject: [PATCH 128/553] Add meta client helper with object cache --- src/Cargo.lock | 1 + src/component/cyfs-meta-lib/Cargo.toml | 1 + src/component/cyfs-meta-lib/src/client.rs | 463 +++++++++++++--------- src/component/cyfs-meta-lib/src/helper.rs | 121 ++++++ src/component/cyfs-meta-lib/src/lib.rs | 6 + 5 files changed, 399 insertions(+), 193 deletions(-) create mode 100644 src/component/cyfs-meta-lib/src/helper.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 485628c38..4a1a3eb58 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2002,6 +2002,7 @@ dependencies = [ "hex", "http-types", "log 0.4.17", + "lru_time_cache", "primitive-types", "rand 0.7.3", "serde_json", diff --git a/src/component/cyfs-meta-lib/Cargo.toml b/src/component/cyfs-meta-lib/Cargo.toml index 4aeac29db..d19e44fbe 100644 --- a/src/component/cyfs-meta-lib/Cargo.toml +++ b/src/component/cyfs-meta-lib/Cargo.toml @@ -18,3 +18,4 @@ log = '0.4' serde_json = '1.0' rand = '0.7.3' primitive-types = { version = '0.9' } +lru_time_cache = "0.11" diff --git a/src/component/cyfs-meta-lib/src/client.rs b/src/component/cyfs-meta-lib/src/client.rs index 6cc154064..6b2524d35 100644 --- a/src/component/cyfs-meta-lib/src/client.rs +++ b/src/component/cyfs-meta-lib/src/client.rs @@ -1,12 +1,12 @@ +use crate::MetaMinerTarget; use cyfs_base::*; use cyfs_base_meta::*; -use crate::MetaMinerTarget; use http_types::{Method, Request, Url}; use log::*; +use primitive_types::H256; use serde_json::Value; use std::convert::TryFrom; -use primitive_types::H256; use std::time::Duration; pub struct MetaClient { @@ -22,7 +22,11 @@ impl MetaClient { pub fn new_target(target: MetaMinerTarget) -> Self { let url = target.miner_url(); - info!("will select meta service url: target={}, url={}", target.to_string(), &url); + info!( + "will select meta service url: target={}, url={}", + target.to_string(), + &url + ); Self::new(&url) } @@ -47,7 +51,11 @@ impl MetaClient { self.miner_host.join(path).unwrap() } - pub async fn get_balance(&self, account: &ObjectId, coin_id: u8) -> BuckyResult { + pub async fn get_balance( + &self, + account: &ObjectId, + coin_id: u8, + ) -> BuckyResult { let req = self.get_balance_request(account, coin_id); let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?; if let ViewResponse::ViewBalance(br) = resp { @@ -96,7 +104,8 @@ impl MetaClient { ctid: CoinTokenId::Coin(coin_id), to: vec![(to.clone(), v)], }), - 10,10, + 10, + 10, Vec::new(), ) .await @@ -117,7 +126,8 @@ impl MetaClient { ctid: CoinTokenId::Coin(coin_id), to: vec![(to.clone(), v)], }), - 10,10, + 10, + 10, Vec::new(), ) .await @@ -133,7 +143,8 @@ impl MetaClient { tx_data: Vec, ) -> BuckyResult { let caller = TxCaller::try_from(caller)?; - self.create_tx_and_sign_ex(caller, secret, body, gas_price, max_fee, tx_data).await + self.create_tx_and_sign_ex(caller, secret, body, gas_price, max_fee, tx_data) + .await } async fn create_tx_and_sign_ex( @@ -164,7 +175,17 @@ impl MetaClient { ) -> BuckyResult { let mut nonce = self.get_nonce(&caller.id()?).await?; nonce += 1; - let tx = Tx::new(nonce, caller, 0, gas_price, max_fee, None, vec![body].to_vec()?, tx_data).build(); + let tx = Tx::new( + nonce, + caller, + 0, + gas_price, + max_fee, + None, + vec![body].to_vec()?, + tx_data, + ) + .build(); Ok(tx) } @@ -178,7 +199,17 @@ impl MetaClient { ) -> BuckyResult { let mut nonce = self.get_nonce(&caller.id()?).await?; nonce += 1; - let tx = Tx::new(nonce, caller, 0, gas_price, max_fee, None, bodys.to_vec()?, tx_data).build(); + let tx = Tx::new( + nonce, + caller, + 0, + gas_price, + max_fee, + None, + bodys.to_vec()?, + tx_data, + ) + .build(); Ok(tx) } @@ -199,7 +230,9 @@ impl MetaClient { max_fee: u32, data: Vec, ) -> BuckyResult { - let signed_tx = self.create_tx_and_sign(caller, secret, body, gas_price, max_fee, data).await?; + let signed_tx = self + .create_tx_and_sign(caller, secret, body, gas_price, max_fee, data) + .await?; self.commit_signed_tx(signed_tx) } @@ -350,7 +383,8 @@ impl MetaClient { desc_hash: desc.hash()?, price, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -375,7 +409,8 @@ impl MetaClient { desc_hash: desc.hash()?, price, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -389,7 +424,9 @@ impl MetaClient { coin_id: Option, secret: &PrivateKey, ) -> BuckyResult { - let req = self.update_desc_request(owner, desc, price, coin_id, secret).await?; + let req = self + .update_desc_request(owner, desc, price, coin_id, secret) + .await?; self.request_miner(req, &mut Vec::new()).await } @@ -426,7 +463,8 @@ impl MetaClient { }), desc_hash: desc.hash()?, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -451,7 +489,8 @@ impl MetaClient { }), desc_hash: desc.hash()?, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -476,7 +515,8 @@ impl MetaClient { name_price: price, price: rent, }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -518,7 +558,8 @@ impl MetaClient { info, write_flag, }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -540,7 +581,8 @@ impl MetaClient { sub_name: sub_name.map(|str| str.to_owned()), new_owner: new_owner.clone(), }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -573,7 +615,7 @@ impl MetaClient { Err(async_std::future::TimeoutError { .. }) => { let msg = format!("meta request tx timeout!"); error!("{}", msg); - + Err(BuckyError::new(BuckyErrorCode::Timeout, msg)) } } @@ -652,12 +694,14 @@ impl MetaClient { buf: &'de mut Vec, ) -> BuckyResult { if let Some(timeout) = &self.request_timeout { - match async_std::future::timeout(timeout.to_owned(), self.request_miner_impl(req, buf)).await { + match async_std::future::timeout(timeout.to_owned(), self.request_miner_impl(req, buf)) + .await + { Ok(ret) => ret, Err(async_std::future::TimeoutError { .. }) => { let msg = format!("meta request timeout!"); error!("{}", msg); - + Err(BuckyError::new(BuckyErrorCode::Timeout, msg)) } } @@ -695,16 +739,11 @@ impl MetaClient { err })?; */ - let ret_hex = resp.body_string() - .await - .map_err(|err| { - error!("recv body error! err={}", err); - err - })?; - let ret = Result::::clone_from_hex( - ret_hex.as_str(), - buf, - )?; + let ret_hex = resp.body_string().await.map_err(|err| { + error!("recv body error! err={}", err); + err + })?; + let ret = Result::::clone_from_hex(ret_hex.as_str(), buf)?; match ret { Ok(t) => Ok(t), @@ -729,7 +768,8 @@ impl MetaClient { caller, secret, MetaTxBody::CreateUnion(create_union_tx), - 10,10, + 10, + 10, vec![], ) .await?; @@ -743,7 +783,14 @@ impl MetaClient { secret: &PrivateKey, ) -> BuckyResult { let req = self - .commit_request(caller, secret, MetaTxBody::DeviateUnion(deviate_tx), 10,10, vec![]) + .commit_request( + caller, + secret, + MetaTxBody::DeviateUnion(deviate_tx), + 10, + 10, + vec![], + ) .await?; self.request_miner(req, &mut Vec::new()).await } @@ -765,7 +812,8 @@ impl MetaClient { union: union_id.clone(), value, }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -787,7 +835,8 @@ impl MetaClient { key: key.to_owned(), value: value.to_owned(), }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -809,7 +858,8 @@ impl MetaClient { name: name.to_owned(), price: startting_price, }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -829,7 +879,8 @@ impl MetaClient { MetaTxBody::CancelAuctionName(CancelAuctionNameTx { name: name.to_owned(), }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -849,7 +900,8 @@ impl MetaClient { MetaTxBody::BuyBackName(BuyBackNameTx { name: name.to_owned(), }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -869,7 +921,8 @@ impl MetaClient { MetaTxBody::RemoveDesc(RemoveDescTx { id: desc_id.clone(), }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -893,7 +946,8 @@ impl MetaClient { id: file_id.clone(), value: v, }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -911,7 +965,8 @@ impl MetaClient { caller, secret, MetaTxBody::CreateSubChainAccount(miner_group), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -930,7 +985,8 @@ impl MetaClient { caller, secret, MetaTxBody::WithdrawFromSubChain(WithdrawFromSubChainTx { coin_id, value }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -945,7 +1001,14 @@ impl MetaClient { tx_data: Vec, ) -> BuckyResult { let req = self - .commit_request_ex(caller, secret, MetaTxBody::Extension(extension_tx), 10,10, tx_data) + .commit_request_ex( + caller, + secret, + MetaTxBody::Extension(extension_tx), + 10, + 10, + tx_data, + ) .await?; self.request_miner(req, &mut Vec::new()).await } @@ -955,75 +1018,120 @@ impl MetaClient { self.request_miner(req, &mut Vec::new()).await } - pub async fn create_contract(&self, caller: &StandardObject, secret: &PrivateKey, value: u64, init_data: Vec, gas_price: u16, max_fee: u32) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::CreateContract(CreateContractTx { - value, - init_data - }), - gas_price, max_fee, - Vec::new(), - ).await?; + pub async fn create_contract( + &self, + caller: &StandardObject, + secret: &PrivateKey, + value: u64, + init_data: Vec, + gas_price: u16, + max_fee: u32, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::CreateContract(CreateContractTx { value, init_data }), + gas_price, + max_fee, + Vec::new(), + ) + .await?; info!("create request"); self.request_miner(req, &mut vec![]).await } - pub async fn create_contract2(&self, caller: &StandardObject, secret: &PrivateKey, value: u64, init_data: Vec, salt: [u8;32], gas_price: u16, max_fee: u32) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::CreateContract2(CreateContract2Tx::new(value, init_data, salt)), - gas_price, max_fee, - Vec::new(), - ).await?; + pub async fn create_contract2( + &self, + caller: &StandardObject, + secret: &PrivateKey, + value: u64, + init_data: Vec, + salt: [u8; 32], + gas_price: u16, + max_fee: u32, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::CreateContract2(CreateContract2Tx::new(value, init_data, salt)), + gas_price, + max_fee, + Vec::new(), + ) + .await?; self.request_miner(req, &mut vec![]).await } - pub async fn call_contract(&self, caller: &StandardObject, secret: &PrivateKey, address: ObjectId, value: u64, data: Vec, gas_price: u16, max_fee: u32) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::CallContract(CallContractTx { - address, - value, - data - }), - gas_price, max_fee, - Vec::new(), - ).await?; + pub async fn call_contract( + &self, + caller: &StandardObject, + secret: &PrivateKey, + address: ObjectId, + value: u64, + data: Vec, + gas_price: u16, + max_fee: u32, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::CallContract(CallContractTx { + address, + value, + data, + }), + gas_price, + max_fee, + Vec::new(), + ) + .await?; self.request_miner(req, &mut vec![]).await } - pub async fn view_contract(&self, address: ObjectId, data: Vec) -> BuckyResult { + pub async fn view_contract( + &self, + address: ObjectId, + data: Vec, + ) -> BuckyResult { let view = ViewRequest { block: ViewBlockEnum::Tip, - method: ViewMethodEnum::ViewContract(ViewContract { - address, - data - }), + method: ViewMethodEnum::ViewContract(ViewContract { address, data }), }; let req = self.view_request(view); let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?; if let ViewResponse::ViewContract(br) = resp { Ok(br) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } - pub async fn set_benefi(&self, address: &ObjectId, benefi: &ObjectId, caller: &StandardObject, secret: &PrivateKey) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::SetBenefi(SetBenefiTx { - address: address.clone(), - to: benefi.clone() - }), - 10, 10, - Vec::new(), - ).await?; + pub async fn set_benefi( + &self, + address: &ObjectId, + benefi: &ObjectId, + caller: &StandardObject, + secret: &PrivateKey, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::SetBenefi(SetBenefiTx { + address: address.clone(), + to: benefi.clone(), + }), + 10, + 10, + Vec::new(), + ) + .await?; self.request_miner(req, &mut vec![]).await } @@ -1039,18 +1147,27 @@ impl MetaClient { if let ViewResponse::ViewBenefi(br) = resp { Ok(br.address) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } - pub async fn get_logs(&self, address: ObjectId, topics: Vec>, from: i64, to: i64) -> BuckyResult, Vec)>> { + pub async fn get_logs( + &self, + address: ObjectId, + topics: Vec>, + from: i64, + to: i64, + ) -> BuckyResult, Vec)>> { let view = ViewRequest { block: ViewBlockEnum::Tip, method: ViewMethodEnum::ViewLog(ViewLog { address, topics, from, - to + to, }), }; let req = self.view_request(view); @@ -1058,26 +1175,28 @@ impl MetaClient { if let ViewResponse::ViewLog(br) = resp { Ok(br.logs) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } - pub async fn nft_create(&self, - caller: TxCaller, - secret: &PrivateKey, - desc: NFTDesc, - name: String, - state: NFTState) -> BuckyResult { + pub async fn nft_create( + &self, + caller: TxCaller, + secret: &PrivateKey, + desc: NFTDesc, + name: String, + state: NFTState, + ) -> BuckyResult { let req = self .commit_request_ex( caller, secret, - MetaTxBody::NFTCreate(NFTCreateTx { - desc, - name, - state - }), - 10, 10, + MetaTxBody::NFTCreate(NFTCreateTx { desc, name, state }), + 10, + 10, Vec::new(), ) .await?; @@ -1097,7 +1216,10 @@ impl MetaClient { if let ViewResponse::ViewNFT(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1116,7 +1238,10 @@ impl MetaClient { if let ViewResponse::ViewNFTApplyBuyList(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1135,7 +1260,10 @@ impl MetaClient { if let ViewResponse::ViewNFTBidList(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1145,14 +1273,17 @@ impl MetaClient { ) -> BuckyResult> { let view = ViewRequest { block: ViewBlockEnum::Tip, - method: ViewMethodEnum::ViewNFTLargestBuyValue(nft_id) + method: ViewMethodEnum::ViewNFTLargestBuyValue(nft_id), }; let req = self.view_request(view); let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?; if let ViewResponse::ViewNFTLargestBuyValue(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1163,7 +1294,8 @@ impl MetaClient { nft_id: ObjectId, price: u64, coin_id: CoinTokenId, - duration_block_num: u64) -> BuckyResult { + duration_block_num: u64, + ) -> BuckyResult { let req = self .commit_request_ex( caller, @@ -1172,9 +1304,10 @@ impl MetaClient { nft_id, price, coin_id, - duration_block_num + duration_block_num, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1187,7 +1320,7 @@ impl MetaClient { secret: &PrivateKey, nft_id: ObjectId, price: u64, - coin_id: CoinTokenId + coin_id: CoinTokenId, ) -> BuckyResult { let req = self .commit_request_ex( @@ -1198,7 +1331,8 @@ impl MetaClient { price, coin_id, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1211,7 +1345,7 @@ impl MetaClient { secret: &PrivateKey, nft_id: ObjectId, price: u64, - coin_id: CoinTokenId + coin_id: CoinTokenId, ) -> BuckyResult { let req = self .commit_request_ex( @@ -1222,7 +1356,8 @@ impl MetaClient { price, coin_id, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1246,9 +1381,10 @@ impl MetaClient { nft_id, price, coin_id, - duration_block_num + duration_block_num, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1261,7 +1397,7 @@ impl MetaClient { secret: &PrivateKey, nft_id: ObjectId, price: u64, - coin_id: CoinTokenId + coin_id: CoinTokenId, ) -> BuckyResult { let req = self .commit_request_ex( @@ -1272,7 +1408,8 @@ impl MetaClient { price, coin_id, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1289,10 +1426,9 @@ impl MetaClient { .commit_request_ex( caller, secret, - MetaTxBody::NFTCancelApplyBuyTx(NFTCancelApplyBuyTx { - nft_id, - }), - 10, 10, + MetaTxBody::NFTCancelApplyBuyTx(NFTCancelApplyBuyTx { nft_id }), + 10, + 10, Vec::new(), ) .await?; @@ -1310,11 +1446,9 @@ impl MetaClient { .commit_request_ex( caller, secret, - MetaTxBody::NFTAgreeApply(NFTAgreeApplyTx { - nft_id, - user_id, - }), - 10, 10, + MetaTxBody::NFTAgreeApply(NFTAgreeApplyTx { nft_id, user_id }), + 10, + 10, Vec::new(), ) .await?; @@ -1331,17 +1465,15 @@ impl MetaClient { .commit_request_ex( caller, secret, - MetaTxBody::NFTLike(NFTLikeTx { - nft_id, - }), - 10, 10, + MetaTxBody::NFTLike(NFTLikeTx { nft_id }), + 10, + 10, Vec::new(), ) .await?; self.request_miner(req, &mut Vec::new()).await } - // pub async fn public_sn_service(&self, caller: TxCaller, service: SNService, secret: &PrivateKey) -> BuckyResult { // let req = self.commit_request_ex(caller, secret, MetaTxBody::SNService(SNServiceTx::Publish(service)), Vec::new()).await?; // self.request_miner(req, &mut Vec::new()).await @@ -1362,59 +1494,4 @@ impl MetaClient { // let req = Request::new(Method::Get, url); // self.request_miner(req, &mut Vec::new()).await // } -} - - -pub struct MetaClientHelper; - -impl MetaClientHelper { - pub async fn get_object( - meta_client: &MetaClient, - object_id: &ObjectId, - ) -> BuckyResult)>> { - let object_raw = match meta_client.get_raw_data(object_id).await { - Ok(v) => v, - Err(e) => { - if e.code() == BuckyErrorCode::NotFound { - warn!( - "get object from meta chain but not found! obj={} err={}", - object_id, e - ); - - return Ok(None); - } else { - let msg = format!( - "load object from meta chain failed! obj={} err={}", - object_id, e - ); - error!("{}", msg); - return Err(BuckyError::new(e.code(), msg)); - } - } - }; - - info!("get object from meta success: {}", object_id); - let (object, _) = AnyNamedObject::raw_decode(&object_raw).map_err(|e| { - let msg = format!("invalid object format! obj={} err={}", object_id, e); - error!("{}", msg); - - BuckyError::new(BuckyErrorCode::InvalidFormat, msg) - })?; - - // 校验一下对象id,看是否匹配 - let id = object.calculate_id(); - if id != *object_id { - let msg = format!( - "get object from meta but got unmatch object id! expected={}, got={}", - object_id, id - ); - error!("{}", msg); - - return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); - } - - let resp = (object, object_raw); - - Ok(Some(resp)) - } -} +} \ No newline at end of file diff --git a/src/component/cyfs-meta-lib/src/helper.rs b/src/component/cyfs-meta-lib/src/helper.rs new file mode 100644 index 000000000..6185450d4 --- /dev/null +++ b/src/component/cyfs-meta-lib/src/helper.rs @@ -0,0 +1,121 @@ +use super::client::*; +use cyfs_base::*; + +use async_std::sync::Mutex as AsyncMutex; +use std::sync::Arc; + +pub struct MetaClientHelper; + +impl MetaClientHelper { + pub async fn get_object( + meta_client: &MetaClient, + object_id: &ObjectId, + ) -> BuckyResult)>> { + let object_raw = match meta_client.get_raw_data(object_id).await { + Ok(v) => v, + Err(e) => { + if e.code() == BuckyErrorCode::NotFound { + warn!( + "get object from meta chain but not found! obj={} err={}", + object_id, e + ); + + return Ok(None); + } else { + let msg = format!( + "load object from meta chain failed! obj={} err={}", + object_id, e + ); + error!("{}", msg); + return Err(BuckyError::new(e.code(), msg)); + } + } + }; + + info!("get object from meta success: {}", object_id); + let (object, _) = AnyNamedObject::raw_decode(&object_raw).map_err(|e| { + let msg = format!("invalid object format! obj={} err={}", object_id, e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + // 校验一下对象id,看是否匹配 + let id = object.calculate_id(); + if id != *object_id { + let msg = format!( + "get object from meta but got unmatch object id! expected={}, got={}", + object_id, id + ); + error!("{}", msg); + + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let resp = (object, object_raw); + + Ok(Some(resp)) + } +} + +struct MetaClientObjectItem { + object_raw: Option>, +} + +impl MetaClientObjectItem { + pub fn into_object_raw(&self) -> Option> { + self.object_raw + .as_ref() + .map(|object_raw| object_raw.clone()) + } +} + +#[derive(Clone)] +pub struct MetaClientHelperWithObjectCache { + objects: Arc>>, +} + +impl MetaClientHelperWithObjectCache { + pub fn new(timeout: std::time::Duration, capacity: usize) -> Self { + Self { + objects: Arc::new(AsyncMutex::new( + lru_time_cache::LruCache::with_expiry_duration_and_capacity(timeout, capacity), + )), + } + } + + pub async fn get_object( + &self, + meta_client: &MetaClient, + object_id: &ObjectId, + ) -> BuckyResult)>> { + Ok(self + .get_object_raw(meta_client, object_id) + .await? + .map(|object_raw| { + let (object, _) = AnyNamedObject::raw_decode(&object_raw).unwrap(); + (object, object_raw) + })) + } + + pub async fn get_object_raw( + &self, + meta_client: &MetaClient, + object_id: &ObjectId, + ) -> BuckyResult>> { + let mut list = self.objects.lock().await; + if let Some(item) = list.peek(object_id) { + return Ok(item.into_object_raw()); + } + + let ret = MetaClientHelper::get_object(meta_client, object_id).await?; + let ret = ret.map(|(_, object_raw)| object_raw); + let item = MetaClientObjectItem { + object_raw: ret.as_ref().map(|object_raw| object_raw.clone()), + }; + + list.insert(object_id.to_owned(), item); + + Ok(ret) + } +} diff --git a/src/component/cyfs-meta-lib/src/lib.rs b/src/component/cyfs-meta-lib/src/lib.rs index bc74ccc7e..2c043b6c9 100644 --- a/src/component/cyfs-meta-lib/src/lib.rs +++ b/src/component/cyfs-meta-lib/src/lib.rs @@ -1,4 +1,10 @@ mod client; +mod helper; mod meta_target; + +#[macro_use] +extern crate log; + pub use client::*; +pub use helper::*; pub use meta_target::*; \ No newline at end of file From f937926e6b92b4ac2cf804b3071fc270fdcde3f1 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 13:43:42 +0800 Subject: [PATCH 129/553] Add cache for meta config repo in ood-daemon --- src/service/ood-daemon/src/config_repo/meta.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index e57133587..96a4be439 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -3,7 +3,7 @@ use crate::config::*; use cyfs_base::*; use cyfs_core::*; use cyfs_debug::Mutex; -use cyfs_meta_lib::{MetaClient, MetaClientHelper, MetaMinerTarget}; +use cyfs_meta_lib::{MetaClient, MetaClientHelper, MetaClientHelperWithObjectCache, MetaMinerTarget}; use cyfs_util::LOCAL_DEVICE_MANAGER; use async_trait::async_trait; @@ -135,6 +135,9 @@ pub struct DeviceConfigMetaRepo { meta_client: MetaClient, cache: Mutex>, + + service_objects: MetaClientHelperWithObjectCache, + service_dir_objects: MetaClientHelperWithObjectCache, } impl DeviceConfigMetaRepo { @@ -148,6 +151,8 @@ impl DeviceConfigMetaRepo { service_list_id: None, meta_client, cache: Mutex::new(None), + service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), + service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24), 16), } } @@ -227,7 +232,7 @@ impl DeviceConfigMetaRepo { } async fn load_service(&self, service_id: &ObjectId) -> BuckyResult { - let ret = MetaClientHelper::get_object(&self.meta_client, service_id).await?; + let ret = self.service_objects.get_object_raw(&self.meta_client, service_id).await?; if ret.is_none() { let msg = format!( "load service object from meta chain but not found! id={}", @@ -238,7 +243,7 @@ impl DeviceConfigMetaRepo { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - let (_, object_raw) = ret.unwrap(); + let object_raw = ret.unwrap(); // 解码 let service = DecApp::clone_from_slice(&object_raw).map_err(|e| { @@ -252,7 +257,7 @@ impl DeviceConfigMetaRepo { } async fn load_service_dir(&self, dir_id: &ObjectId) -> BuckyResult { - let ret = MetaClientHelper::get_object(&self.meta_client, dir_id).await?; + let ret = self.service_dir_objects.get_object_raw(&self.meta_client, dir_id).await?; if ret.is_none() { let msg = format!( "load service dir from meta chain but not found! id={}", @@ -263,7 +268,7 @@ impl DeviceConfigMetaRepo { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - let (_, object_raw) = ret.unwrap(); + let object_raw = ret.unwrap(); // 解码 let dir = Dir::clone_from_slice(&object_raw).map_err(|e| { @@ -332,7 +337,7 @@ impl DeviceConfigMetaRepo { false => None, }; - let version = service.find_version(&config_version, preview).map_err(|e| { + let (version, semver) = service.find_version(&config_version, preview).map_err(|e| { let msg = format!( "find version from service object failed! id={}, configed version={}, preview={:?}, {}", service_id, config_version, preview, e, From 803479db333a5727c9deaa85fa3d6a44bb1e6afd Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 15:12:03 +0800 Subject: [PATCH 130/553] Add semver epoch check into ood-daemon --- src/component/cyfs-core/src/app/dec_app.rs | 17 ++++---- src/service/ood-daemon/src/config/version.rs | 39 ++++++++++++++++--- .../ood-daemon/src/config_repo/meta.rs | 3 ++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/component/cyfs-core/src/app/dec_app.rs b/src/component/cyfs-core/src/app/dec_app.rs index 1a32ccc1c..e5a0d9b8a 100644 --- a/src/component/cyfs-core/src/app/dec_app.rs +++ b/src/component/cyfs-core/src/app/dec_app.rs @@ -134,7 +134,8 @@ pub trait DecAppObj { fn app_desc(&self) -> Option<&str>; fn icon(&self) -> Option<&str>; - fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str>; + // return (origin version, semversion); + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<(&str, String)>; fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult; fn find_source(&self, version: &str) -> BuckyResult; @@ -212,7 +213,7 @@ impl DecAppObj for DecApp { // https://nodesource.com/blog/semver-tilde-and-caret/ // When pre is specified, all matching prerelease versions will be included; // otherwise, only all versions that do not contain any prerelease will be matched - fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str> { + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<(&str, String)> { let name = self.name(); let id = self.desc().calculate_id(); @@ -284,13 +285,13 @@ impl DecAppObj for DecApp { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - let (version, _) = ret.unwrap(); - Ok(version) + let (version, semver) = ret.unwrap(); + Ok((version, semver.to_string())) } fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult { - let version = self.find_version(req_semver, pre)?; - self.find_source(&version) + let ret = self.find_version(req_semver, pre)?; + self.find_source(&ret.0) } fn find_source(&self, version: &str) -> BuckyResult { @@ -303,8 +304,8 @@ impl DecAppObj for DecApp { } fn find_source_desc_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult> { - let version = self.find_version(req_semver, pre)?; - Ok(self.find_source_desc(&version)) + let ret = self.find_version(req_semver, pre)?; + Ok(self.find_source_desc(&ret.0)) } fn find_source_desc(&self, version: &str) -> Option<&str> { diff --git a/src/service/ood-daemon/src/config/version.rs b/src/service/ood-daemon/src/config/version.rs index fd8a7a1e3..1822f6403 100644 --- a/src/service/ood-daemon/src/config/version.rs +++ b/src/service/ood-daemon/src/config/version.rs @@ -4,7 +4,7 @@ use std::str::FromStr; #[derive(Debug)] pub enum ServiceListVersion { - Nightly, // default version + Nightly, // default version Specific(String), // user confined } @@ -30,16 +30,13 @@ impl FromStr for ServiceListVersion { fn from_str(s: &str) -> BuckyResult { let ret = match s.trim() { "nightly" => Self::Nightly, - v @ _ => { - Self::Specific(v.to_owned()) - } + v @ _ => Self::Specific(v.to_owned()), }; Ok(ret) } } - // 版本列表定义 #[derive(Debug)] pub enum ServiceVersion { @@ -91,3 +88,35 @@ impl FromStr for ServiceVersion { Ok(ret) } } + +pub struct SemVerEpochCheck; + +impl SemVerEpochCheck { + pub fn get_semver_epoch_patch_version() -> u64 { + match cyfs_base::get_channel() { + CyfsChannel::Nightly => 719, + CyfsChannel::Beta => 75, + CyfsChannel::Stable => 0, + } + } + + pub fn check_version_with_semver_epoch(semver: &str) -> BuckyResult<()> { + let version = semver::Version::parse(semver).map_err(|e| { + let msg = format!("invalid semver string! value={}, {}", semver, e,); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + if version.patch < Self::get_semver_epoch_patch_version() { + let msg = format!( + "version that does not support semver! version={}, epoch patch={}", + semver, + Self::get_semver_epoch_patch_version(), + ); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotSupport, msg)) + } + + Ok(()) + } +} diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 96a4be439..7d2babe91 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -347,6 +347,9 @@ impl DeviceConfigMetaRepo { BuckyError::new(BuckyErrorCode::NotFound, msg) })?; + // check if the target service version is valid + SemVerEpochCheck::check_version_with_semver_epoch(&semver)?; + let ret = service.find_source(&version); if ret.is_err() { let msg = format!( From 80ee29fc1325d4935173dc521b1493ca21e83b20 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 18:02:20 +0800 Subject: [PATCH 131/553] Add app repo downloader for ood-installer --- .../ood-installer/src/app_repo_downloader.rs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/tools/ood-installer/src/app_repo_downloader.rs diff --git a/src/tools/ood-installer/src/app_repo_downloader.rs b/src/tools/ood-installer/src/app_repo_downloader.rs new file mode 100644 index 000000000..b7fa7ca18 --- /dev/null +++ b/src/tools/ood-installer/src/app_repo_downloader.rs @@ -0,0 +1,91 @@ +use std::path::PathBuf; +use std::time::Duration; +use app_manager::package::AppPackage; +use cyfs_base::{AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, FileDecoder, NamedObject, ObjectId, OwnerObjectDesc, RawFrom}; +use cyfs_base_meta::SavedMetaObject; +use cyfs_client::{NamedCacheClient, NamedCacheClientConfig}; +use cyfs_core::{AppList, APPLIST_APP_CATEGORY, AppListObj, AppStatusObj, DecApp, DecAppObj}; +use cyfs_meta_lib::{MetaClient, MetaMinerTarget}; +use cyfs_util::get_cyfs_root_path; +use crate::asset::{OODAsset}; + +pub(crate) struct AppRepoDownloader { + repo_path: PathBuf, + client: NamedCacheClient, + meta_client: MetaClient +} + +impl AppRepoDownloader { + pub fn new() -> Self { + // service desc确保它有固定外网地址,连接不走sn。这里sn_list就可以传None + let mut config = NamedCacheClientConfig::default(); + config.retry_times = 3; + config.timeout = Duration::from_secs(10*60); + config.tcp_file_manager_port = 5312; + config.tcp_chunk_manager_port = 5310; + config.conn_strategy = cyfs_client::ConnStrategy::TcpFirst; + Self { + repo_path: get_cyfs_root_path().join("app_repo"), + client: NamedCacheClient::new(config), + meta_client: MetaClient::new_target(MetaMinerTarget::default()) + } + } + + pub async fn init(&mut self) -> BuckyResult<()> { + if let Err(e) = self.client.init().await { + let msg = format!("init named cache client for repo failed! err={}", e); + error!("{}", msg); + + return Err(BuckyError::new(e.code(), msg)); + } + + Ok(()) + } + + pub async fn download(&self, asset: &OODAsset) -> BuckyResult<()> { + asset.extract_app_repo()?; + + let sys_app_list_id = self.get_sys_app_list_id()?; + info!("try get sys app list {}", sys_app_list_id); + + let list = if let SavedMetaObject::Data(data) = self.meta_client.get_desc(&sys_app_list_id).await? { + AppList::clone_from_slice(&data.data) + } else { + Err(BuckyError::new(BuckyErrorCode::NotMatch, format!("app list {} from meta type mismatch!", &sys_app_list_id))) + }?; + + for (id, status) in list.app_list() { + info!("download app {} version {}", id.object_id(), status.version()); + let dec_app = if let SavedMetaObject::Data(data) = self.meta_client.get_desc(id.object_id()).await? { + DecApp::clone_from_slice(&data.data) + } else { + Err(BuckyError::new(BuckyErrorCode::NotMatch, format!("app {} from meta type mismatch!", &id.object_id()))) + }?; + + let owner = dec_app.desc().owner().as_ref().ok_or(BuckyError::from(BuckyErrorCode::InvalidInput))?; + let dir = dec_app.find_source(status.version())?; + + let target_path = self.repo_path.join(dir.to_string()); + AppPackage::download(&dir, owner, &self.client, &target_path).await.map_err(|e| { + error!("download app {} dir {} err {}",id.object_id(), &dir, e); + e + })? + } + + info!("sync app repo from {} success!", &sys_app_list_id); + + Ok(()) + } + + fn get_sys_app_list_id(&self) -> BuckyResult { + let mut repo_path = get_cyfs_root_path(); + repo_path.push("etc"); + repo_path.push("desc"); + repo_path.push("app_repo.desc"); + let (obj, _) = AnyNamedObject::decode_from_file(&repo_path, &mut vec![])?; + let id = obj.calculate_id(); + + Ok(AppList::generate_id(id.clone(), "", APPLIST_APP_CATEGORY)) + + } +} \ No newline at end of file From af9e97dec2a01c839040bf3bab9eaeca546cab14 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 18:16:56 +0800 Subject: [PATCH 132/553] Fix: Missing app-manager lib.rs --- .../cyfs-perf-client/build_ios_perfclient.js | 23 ------------------- .../cyfs-perf-client/build_perfclient.js | 17 -------------- .../cyfs-perf/cyfs-perf-client/cbindgen.toml | 7 ------ .../cyfs-perf-client/header/perf_client.h | 23 ------------------- src/service/app-manager/src/lib.rs | 1 + 5 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h create mode 100644 src/service/app-manager/src/lib.rs diff --git a/src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js b/src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js deleted file mode 100644 index 4254c77ac..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js +++ /dev/null @@ -1,23 +0,0 @@ -const child_process = require('child_process'); - -const env = process.env; - -child_process.execSync('cargo update', { stdio: 'inherit', cwd: __dirname}) -child_process.execSync('rustup target add aarch64-apple-ios x86_64-apple-ios', { stdio: 'inherit', cwd: __dirname}) - -// 编译通用库 -child_process.execSync('cargo install cargo-lipo', { stdio: 'inherit', cwd: __dirname}) -child_process.execSync('cargo lipo -p perf-client --release', { stdio: 'inherit', cwd: __dirname}) - -// 编译模拟器库 -child_process.execSync('cargo build -p perf-client --lib --target x86_64-apple-ios --release', { stdio: 'inherit', cwd: __dirname, env: env }) - -// 编译真机库 -child_process.execSync('cargo build -p perf-client --lib --target aarch64-apple-ios --release', { stdio: 'inherit', cwd: __dirname, env: env }) - -// 生成头文件 -//child_process.execSync('sudo cargo install --force cbindgen', { stdio: 'inherit', cwd: __dirname}) -// cbindgen 可以导出指定crate的pub方法或类型 -//child_process.execSync('sudo cbindgen --config cbindgen.toml --crate perf-client --output header/perf_client.h', { stdio: 'inherit', cwd: __dirname}) - - diff --git a/src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js b/src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js deleted file mode 100644 index 98314ee7a..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js +++ /dev/null @@ -1,17 +0,0 @@ -const child_process = require('child_process'); - -const env = process.env; -const ndk_home = "C:\Users\Bucky\AppData\Local\Android\Sdk\ndk-bundle" - -env["AR_aarch64-linux-android"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android-ar.exe` -env["CC_aarch64-linux-android"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android21-clang.cmd` -env["AR_armv7-linux-androideabi"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\arm-linux-androideabi-ar.exe` -env["CC_armv7-linux-androideabi"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\armv7a-linux-androideabi21-clang.cmd` -const aarch64_linux_android_strip = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android-strip.exe` -const armv7_linux_androideabi_strip = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\arm-linux-androideabi-strip.exe` - -child_process.execSync('cargo update', { stdio: 'inherit', cwd: __dirname}) - -child_process.execSync('cargo build -p perf-client --lib --target aarch64-linux-android --release', { stdio: 'inherit', cwd: __dirname, env: env }) - -// child_process.execSync(`${aarch64_linux_android_strip} target/aarch64-linux-android/release/libimclient.so`) \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml b/src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml deleted file mode 100644 index 906d84437..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml +++ /dev/null @@ -1,7 +0,0 @@ -#language = "c++"或language = "c" -language = "c" -#是否不导入头文件 -no_includes = false - -[export] -prefix = "" diff --git a/src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h b/src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h deleted file mode 100644 index 32a731e1e..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -#include "ios_logger.h" -void startPerfClient(const char *cowner_id, - const char *cdec_id, - const char *cclient_addr, - const char *cbase_path, - const char *cnon_addr, - const char *cws_addr, - int cbdt_port, - const char *cloglevel, - const char *cwifi_addr, - LogCallback log); - -void statPerf(const char *id, - const char *key, - int bytes, - int error_code, - const char *name, - const char *value); diff --git a/src/service/app-manager/src/lib.rs b/src/service/app-manager/src/lib.rs new file mode 100644 index 000000000..8559986ca --- /dev/null +++ b/src/service/app-manager/src/lib.rs @@ -0,0 +1 @@ +pub mod package; \ No newline at end of file From 718c4eb00a021dd2c9f49b3380ecb048edf25a2f Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 18:34:21 +0800 Subject: [PATCH 133/553] Fix: pack script error --- scripts/pack.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pack.js b/scripts/pack.js index f3676ea57..34432d425 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -166,13 +166,14 @@ async function run() { child_process.execSync(`cyfs-client ${action} services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) + let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) + // 运行app-tool,添加版本和fid let app_version = version + "-preview"; let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; console.log("will run app tool cmd:", cmd) child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) - let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) } From 3a348f60a5872db7d15e1b6a7a2c6c4ca24a8e93 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 15:32:20 +0800 Subject: [PATCH 134/553] Switch meta repo to dynamic dependency on system config --- .../src/config/device_config_manager.rs | 4 +- .../ood-daemon/src/config_repo/meta.rs | 58 +++++++------------ 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 9667a5e30..7e52b619e 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -37,8 +37,8 @@ impl DeviceConfigManager { let repo = DeviceConfigLocalRepo::new(); Box::new(repo) as Box } else if desc == "cyfs_repo" || desc == "device" { - let mut repo = DeviceConfigMetaRepo::new(); - if let Err(e) = repo.init(&desc, &get_system_config().service_list_version) { + let repo = DeviceConfigMetaRepo::new(); + if let Err(e) = repo.init() { return Err(e); } diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 7d2babe91..d2e4ee67c 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -126,12 +126,6 @@ struct LocalCache { } pub struct DeviceConfigMetaRepo { - desc: String, - - device_id: Option, - - service_list_id: Option, - meta_client: MetaClient, cache: Mutex>, @@ -146,9 +140,6 @@ impl DeviceConfigMetaRepo { .with_timeout(std::time::Duration::from_secs(60 * 2)); Self { - desc: String::from(""), - device_id: None, - service_list_id: None, meta_client, cache: Mutex::new(None), service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), @@ -156,38 +147,35 @@ impl DeviceConfigMetaRepo { } } - pub fn init(&mut self, config_desc: &str, version: &ServiceListVersion) -> Result<(), BuckyError> { - assert!(self.desc.len() == 0); - self.desc = config_desc.to_owned(); + pub fn init(&self) -> BuckyResult<()> { + Self::gen_service_list_id()?; + + Ok(()) + } - // 首先加载device,用作ServiceList的owner - let device_id = self.load_device()?; - let version = version.to_string(); + fn gen_service_list_id() -> BuckyResult { + let device_id = Self::load_device(&get_system_config().config_desc)?; + let service_list_version = get_system_config().service_list_version.to_string(); // 计算ServiceList对象id let service_list_id = AppList::generate_id( device_id.object_id().to_owned(), - &version, + &service_list_version, APPLIST_SERVICE_CATEGORY, ); info!( - "device config repo: device_id={}, service_list_id={}, version={}", - device_id, service_list_id, version + "device config repo: config_desc={}, device_id={}, service_list_id={}, version={}", + get_system_config().config_desc, device_id, service_list_id, service_list_version ); - self.service_list_id = Some(service_list_id); - self.device_id = Some(device_id); - - Ok(()) + Ok(service_list_id) } - fn load_device(&self) -> BuckyResult { - assert!(self.device_id.is_none()); - - let ret = LOCAL_DEVICE_MANAGER.load(&self.desc); + fn load_device(desc: &str) -> BuckyResult { + let ret = LOCAL_DEVICE_MANAGER.load(&desc); if let Err(e) = ret { - error!("load config desc failed! desc={}, err={}", self.desc, e); + error!("load config desc failed! desc={}, err={}", desc, e); return Err(e); } @@ -198,14 +186,13 @@ impl DeviceConfigMetaRepo { } async fn load_service_list(&self) -> BuckyResult { - assert!(self.service_list_id.is_some()); - - let object_id = self.service_list_id.as_ref().unwrap(); - let ret = MetaClientHelper::get_object(&self.meta_client, object_id).await?; + + let service_list_id = Self::gen_service_list_id()?; + let ret = MetaClientHelper::get_object(&self.meta_client, &service_list_id).await?; if ret.is_none() { let msg = format!( "load service list object from meta chain but not found! id={}", - object_id + service_list_id ); error!("{}", msg); @@ -216,7 +203,7 @@ impl DeviceConfigMetaRepo { // 解码 let list = AppList::clone_from_slice(&object_raw).map_err(|e| { - let msg = format!("decode service list object failed! id={}, {}", object_id, e); + let msg = format!("decode service list object failed! id={}, {}", service_list_id, e); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -224,7 +211,7 @@ impl DeviceConfigMetaRepo { debug!( "load service list object success! id={:?}, list={:?}", - self.service_list_id, + service_list_id, list.app_list() ); @@ -464,8 +451,7 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { } debug!( - "load device_config from meta: device_id={}, config={}", - self.device_id.as_ref().unwrap(), + "load device_config from meta: config={}", device_config_str ); From bc3f9a14174816a1a17cd05afa06dd407207d183 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 15:59:40 +0800 Subject: [PATCH 135/553] Fix two warning after package updated --- src/component/cyfs-base/build.rs | 2 +- .../cyfs-lib/src/base/requestor_helper.rs | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-base/build.rs b/src/component/cyfs-base/build.rs index 9cd52e271..919d0c275 100644 --- a/src/component/cyfs-base/build.rs +++ b/src/component/cyfs-base/build.rs @@ -59,7 +59,7 @@ fn main() { println!( "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + chrono::Local::now().format("%y-%m-%d") ); println!("cargo:rerun-if-changed=protos"); diff --git a/src/component/cyfs-lib/src/base/requestor_helper.rs b/src/component/cyfs-lib/src/base/requestor_helper.rs index 23d6a49dc..1b63024b2 100644 --- a/src/component/cyfs-lib/src/base/requestor_helper.rs +++ b/src/component/cyfs-lib/src/base/requestor_helper.rs @@ -809,12 +809,19 @@ impl RequestorHelper { 0 }; - let time = NaiveDateTime::from_timestamp(secs as i64, nsecs as u32); - - let dt = DateTime::::from_utc(time, Utc); - let s = dt.to_rfc2822(); - - req.insert_header(name, s); + let time = NaiveDateTime::from_timestamp_opt(secs as i64, nsecs as u32); + match time { + Some(time) => { + let dt = DateTime::::from_utc(time, Utc); + let s = dt.to_rfc2822(); + + req.insert_header(name, s); + } + None => { + error!("invalid timestamp format! {}.{}", secs, nsecs); + } + } + } pub async fn request_to_service( From e1b8b2ad1e39a346a1204ec98acbbd8a79d67471 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 136/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/Cargo.lock | 1164 ++++++++--------- src/service/ood-daemon/Cargo.toml | 3 +- .../src/config/device_config_manager.rs | 58 +- .../ood-daemon/src/config/system_config.rs | 51 +- src/service/ood-daemon/src/config/version.rs | 4 +- .../ood-daemon/src/config_repo/test.rs | 11 +- src/service/ood-daemon/src/daemon/daemon.rs | 12 +- src/service/ood-daemon/src/daemon/stop.rs | 9 +- src/service/ood-daemon/src/repo/manager.rs | 29 +- .../ood-daemon/src/status/service_status.rs | 6 +- 10 files changed, 704 insertions(+), 643 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 4a1a3eb58..b892d402f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -111,9 +111,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" [[package]] name = "android_logger" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" +checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" dependencies = [ "android_log-sys", "env_logger", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "app-manager" @@ -262,9 +262,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ "concurrent-queue", "event-listener", @@ -283,23 +283,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", @@ -329,31 +329,32 @@ dependencies = [ [[package]] name = "async-io" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ + "async-lock", "autocfg 1.1.0", "concurrent-queue", "futures-lite", "libc", "log 0.4.17", - "once_cell", "parking", "polling", "slab", "socket2", "waker-fn", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -370,27 +371,27 @@ dependencies = [ [[package]] name = "async-process" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" +checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" dependencies = [ "async-io", + "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", - "once_cell", "signal-hook", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ "proc-macro2", "quote", @@ -492,9 +493,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -525,9 +526,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -535,7 +536,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -557,9 +558,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -773,16 +774,16 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", + "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", - "once_cell", ] [[package]] @@ -793,14 +794,14 @@ checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" dependencies = [ "base64 0.13.1", "bollard-stubs", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "dirs-next", "futures-core", "futures-util", "hex", "http", - "hyper 0.14.20", + "hyper 0.14.24", "hyperlocal", "log 0.4.17", "pin-project", @@ -848,13 +849,11 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" dependencies = [ - "lazy_static", "memchr", - "regex-automata", "serde", ] @@ -866,15 +865,15 @@ checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -884,9 +883,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" [[package]] name = "byteorder" @@ -906,15 +905,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -951,9 +950,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -984,16 +983,16 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.44", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -1109,7 +1108,7 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "memchr", ] @@ -1121,11 +1120,11 @@ checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" [[package]] name = "concurrent-queue" -version = "1.2.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ - "cache-padded", + "crossbeam-utils", ] [[package]] @@ -1302,22 +1301,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1325,9 +1324,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -1390,13 +1389,12 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -1431,9 +1429,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -1443,9 +1441,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -1458,15 +1456,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -1513,7 +1511,7 @@ dependencies = [ "simple_logger 2.3.0", "sqlx", "url 2.3.0", - "zip", + "zip 0.6.4", ] [[package]] @@ -1565,7 +1563,7 @@ dependencies = [ "log 0.4.17", "lru_time_cache", "md5", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.7.3", "ringbuf", @@ -1621,7 +1619,7 @@ dependencies = [ "cyfs-util", "dirs 4.0.0", "log 0.4.17", - "sysinfo 0.26.5", + "sysinfo 0.26.9", ] [[package]] @@ -1637,7 +1635,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1661,7 +1659,7 @@ dependencies = [ "scan_dir", "sha2 0.8.2", "shared_memory", - "sysinfo 0.26.5", + "sysinfo 0.26.9", ] [[package]] @@ -1678,7 +1676,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1702,7 +1700,7 @@ version = "0.6.4" dependencies = [ "bip39", "cyfs-base", - "digest 0.10.5", + "digest 0.10.6", "hex", "hmac 0.12.1", "log 0.4.17", @@ -1768,7 +1766,6 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", - "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1779,10 +1776,9 @@ dependencies = [ "protoc-bin-vendored", "protoc-rust", "rand 0.8.5", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", - "sha2 0.8.2", ] [[package]] @@ -1832,65 +1828,6 @@ dependencies = [ "sha2 0.8.2", ] -[[package]] -name = "cyfs-group" -version = "0.1.1" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "chrono", - "cyfs-base", - "cyfs-bdt", - "cyfs-chunk-lib", - "cyfs-core", - "cyfs-debug", - "cyfs-group-lib", - "cyfs-lib", - "futures", - "itertools", - "lazy_static", - "log 0.4.17", - "prost 0.11.8", - "prost-build 0.9.0", - "protobuf", - "protoc-bin-vendored", - "protoc-rust", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", -] - -[[package]] -name = "cyfs-group-lib" -version = "0.1.1" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "chrono", - "cyfs-base", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-util", - "futures", - "http-types", - "itertools", - "lazy_static", - "log 0.4.17", - "prost 0.11.8", - "prost-build 0.9.0", - "protobuf", - "protoc-bin-vendored", - "protoc-rust", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", -] - [[package]] name = "cyfs-lib" version = "0.8.0" @@ -1899,7 +1836,7 @@ dependencies = [ "async-std", "async-trait", "async-tungstenite", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "cyfs-base", "cyfs-bdt", @@ -2187,7 +2124,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.2.1", + "bytes 1.4.0", "clap", "cyfs-base", "cyfs-bdt", @@ -2242,8 +2179,6 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", - "cyfs-group", - "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -2261,18 +2196,18 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.8", - "prost-build 0.11.3", + "prost 0.11.6", + "prost-build 0.11.6", "protoc-bin-vendored", "rand 0.8.5", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", "sha2 0.8.2", "sqlx", "tide", "toml", - "zip", + "zip 0.6.4", ] [[package]] @@ -2318,7 +2253,7 @@ dependencies = [ "regex", "serde", "toml", - "toml_edit", + "toml_edit 0.15.0", ] [[package]] @@ -2403,7 +2338,7 @@ dependencies = [ "log 0.4.17", "log-panics", "named-lock", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.8.5", "rusqlite", @@ -2416,7 +2351,7 @@ dependencies = [ "url 2.3.0", "walkdir", "winapi", - "zip", + "zip 0.6.4", ] [[package]] @@ -2464,7 +2399,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] @@ -2540,9 +2475,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -2615,9 +2550,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "email-encoding" @@ -2701,9 +2636,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "env_logger" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "log 0.4.17", "regex", @@ -2711,9 +2646,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" +checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" dependencies = [ "serde", ] @@ -2729,7 +2664,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itertools", - "paste 1.0.9", + "paste 1.0.11", "rustc-hex", "serde", "serde_json", @@ -2865,9 +2800,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -2904,14 +2839,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -2934,9 +2869,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -2968,7 +2903,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.4", + "spin 0.9.5", ] [[package]] @@ -3028,9 +2963,18 @@ dependencies = [ [[package]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] [[package]] name = "fuchsia-cprng" @@ -3046,9 +2990,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -3061,9 +3005,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -3071,15 +3015,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -3089,20 +3033,20 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.12.1", + "parking_lot 0.11.2", ] [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -3121,9 +3065,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -3132,21 +3076,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -3167,7 +3111,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.2.1", + "bytes 1.4.0", "clap", "cyfs-base", "cyfs-bdt", @@ -3247,9 +3191,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" +checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" dependencies = [ "proc-macro2", "quote", @@ -3258,21 +3202,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -3283,9 +3227,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", @@ -3293,42 +3237,13 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "group-example" -version = "0.1.0" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "cyfs-base", - "cyfs-bdt", - "cyfs-bdt-ext", - "cyfs-chunk-lib", - "cyfs-core", - "cyfs-debug", - "cyfs-group-lib", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-stack", - "cyfs-util", - "futures", - "lazy_static", - "log 0.4.17", - "prost 0.11.8", - "protobuf", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", -] - [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "fnv", "futures-core", "futures-sink", @@ -3337,7 +3252,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.4", + "tokio-util 0.7.7", "tracing", ] @@ -3403,9 +3318,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -3419,6 +3334,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -3506,7 +3430,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -3533,13 +3457,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "fnv", - "itoa 1.0.4", + "itoa", ] [[package]] @@ -3548,7 +3472,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "http", "pin-project-lite 0.2.9", ] @@ -3624,7 +3548,7 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time 0.1.44", + "time 0.1.45", "traitobject", "typeable", "unicase 1.4.2", @@ -3633,11 +3557,11 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-channel", "futures-core", "futures-util", @@ -3646,7 +3570,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.4", + "itoa", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -3663,16 +3587,16 @@ checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" dependencies = [ "futures-util", "hex", - "hyper 0.14.20", + "hyper 0.14.24", "pin-project", "tokio", ] [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3774,9 +3698,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -3789,7 +3713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" dependencies = [ "indoc-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -3798,7 +3722,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "syn", @@ -3811,6 +3735,26 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -3891,15 +3835,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jni" @@ -3932,18 +3870,41 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] [[package]] name = "kv-log-macro" @@ -3985,7 +3946,7 @@ dependencies = [ "idna 0.2.1", "mime 0.3.16", "native-tls", - "nom 7.1.1", + "nom 7.1.3", "once_cell", "quoted_printable", "socket2", @@ -4006,15 +3967,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libsecp256k1" @@ -4045,9 +4006,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -4116,7 +4077,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" dependencies = [ - "nix 0.23.1", + "nix 0.23.2", "winapi", ] @@ -4128,9 +4089,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "maybe-uninit" @@ -4152,9 +4113,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" dependencies = [ "libc", ] @@ -4168,6 +4129,15 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "memzero" version = "0.1.0" @@ -4249,23 +4219,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] @@ -4300,9 +4270,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -4328,27 +4298,27 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -4364,14 +4334,41 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "notify" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.42.0", +] + [[package]] name = "ntapi" version = "0.4.0" @@ -4424,9 +4421,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" dependencies = [ "byteorder", "lazy_static", @@ -4483,11 +4480,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -4502,18 +4499,18 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "ood-control" @@ -4538,7 +4535,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sysinfo 0.26.5", + "sysinfo 0.26.9", "tide", ] @@ -4565,15 +4562,16 @@ dependencies = [ "http-types", "lazy_static", "log 0.4.17", + "notify", "once_cell", "ood-control", "rand 0.7.3", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", "tide", "toml", - "zip", + "zip 0.6.4", ] [[package]] @@ -4623,9 +4621,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.42" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -4655,9 +4653,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.77" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg 1.1.0", "cc", @@ -4685,7 +4683,7 @@ dependencies = [ "sha2 0.8.2", "simple_logger 2.3.0", "walkdir", - "zip", + "zip 0.6.4", ] [[package]] @@ -4708,7 +4706,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -4728,7 +4726,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -4738,14 +4736,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -4757,15 +4755,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec 1.10.0", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -4786,14 +4784,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "paste-impl" @@ -4801,7 +4799,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -4810,7 +4808,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -4850,9 +4848,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -4920,9 +4918,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -4973,16 +4971,16 @@ dependencies = [ [[package]] name = "polling" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -4998,15 +4996,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ "proc-macro2", "syn", @@ -5014,9 +5012,9 @@ dependencies = [ [[package]] name = "primal" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389bfb36ac527b5fe21a57f87bc7956af45cbeb2de7750b90b7ebac6770e715e" +checksum = "4b53cc99c892c461727618e8a63806c94b09ae13c494dc5fc70a7557b3a2f071" dependencies = [ "primal-check", "primal-estimate", @@ -5049,9 +5047,9 @@ checksum = "7374f14c76f23e1271e6be806981ac5dd9e52b59132b0a2f10bcc412495f9159" [[package]] name = "primal-sieve" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fee6031f66b44e8e004ac9bf81fd1c5abcbbb25bd392bc27429daa1759654a" +checksum = "9f2a14766f8c543620824b5b2cec356abf2681b76966a7ac4b4ed2c0011e696a" dependencies = [ "primal-bit", "primal-estimate", @@ -5082,13 +5080,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit 0.18.1", ] [[package]] @@ -5102,9 +5099,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-hack-impl" @@ -5114,9 +5111,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -5127,18 +5124,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ - "bytes 1.2.1", - "prost-derive 0.11.8", + "bytes 1.4.0", + "prost-derive 0.11.6", ] [[package]] @@ -5147,7 +5144,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "heck 0.3.3", "itertools", "lazy_static", @@ -5163,20 +5160,20 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ - "bytes 1.2.1", - "heck 0.4.0", + "bytes 1.4.0", + "heck 0.4.1", "itertools", "lazy_static", "log 0.4.17", "multimap", "petgraph", "prettyplease", - "prost 0.11.8", - "prost-types 0.11.2", + "prost 0.11.6", + "prost-types 0.11.6", "regex", "syn", "tempfile", @@ -5198,9 +5195,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -5215,18 +5212,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.2" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ - "bytes 1.2.1", - "prost 0.11.8", + "bytes 1.4.0", + "prost 0.11.6", ] [[package]] @@ -5235,7 +5232,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", ] [[package]] @@ -5375,18 +5372,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "quoted_printable" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f14e071918cbeefc5edc986a7aa92c425dae244e003a35e1cdddb5ca39b5cb" +checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" [[package]] name = "radium" @@ -5586,21 +5583,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg 1.1.0", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -5656,26 +5651,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -5716,7 +5705,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "rustc-hex", ] @@ -5766,8 +5755,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", - "digest 0.10.5", - "num-bigint-dig 0.8.1", + "digest 0.10.6", + "num-bigint-dig 0.8.2", "num-integer", "num-iter", "num-traits", @@ -5903,15 +5892,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "safemem" @@ -5946,7 +5935,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -5963,12 +5952,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -5979,9 +5967,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "sct" @@ -5995,9 +5983,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.7.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -6008,9 +5996,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -6027,9 +6015,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -6039,9 +6027,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -6058,9 +6046,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -6078,11 +6066,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.4", + "itoa", "ryu", "serde", ] @@ -6105,7 +6093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa", "ryu", "serde", ] @@ -6134,13 +6122,13 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6160,7 +6148,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6202,7 +6190,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6248,16 +6236,16 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.17", - "nix 0.23.1", + "nix 0.23.2", "rand 0.8.5", "win-sys", ] [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -6265,9 +6253,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -6301,7 +6289,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "winapi", ] @@ -6314,7 +6302,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "winapi", ] @@ -6327,15 +6315,15 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "windows-sys 0.42.0", ] [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg 1.1.0", ] @@ -6414,9 +6402,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" dependencies = [ "lock_api", ] @@ -6438,7 +6426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom 7.1.1", + "nom 7.1.3", "unicode_categories", ] @@ -6462,11 +6450,11 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "crc", "crossbeam-queue", - "digest 0.10.5", + "digest 0.10.6", "either", "event-listener", "flume", @@ -6479,14 +6467,14 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.4", + "itoa", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "num-bigint 0.3.3", "once_cell", - "paste 1.0.9", + "paste 1.0.11", "percent-encoding 2.2.0", "rand 0.8.5", "rsa 0.6.1", @@ -6511,7 +6499,7 @@ checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.4.0", + "heck 0.4.1", "once_cell", "proc-macro2", "quote", @@ -6665,9 +6653,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -6688,9 +6676,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.5" +version = "0.26.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade661fa5e048ada64ad7901713301c21d2dbc5b65ee7967de8826c111452960" +checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -6770,9 +6758,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -6798,18 +6786,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -6818,10 +6806,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -6859,9 +6848,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -6885,16 +6874,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ - "itoa 1.0.4", + "itoa", "libc", "num_threads", "serde", "time-core", - "time-macros 0.2.5", + "time-macros 0.2.7", ] [[package]] @@ -6909,15 +6898,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "time-macros-impl", ] [[package]] name = "time-macros" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" dependencies = [ "time-core", ] @@ -6928,7 +6917,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "standback", @@ -6965,19 +6954,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.21.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg 1.1.0", - "bytes 1.2.1", + "bytes 1.4.0", "libc", "memchr", "mio", "num_cpus", "pin-project-lite 0.2.9", "socket2", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -6986,7 +6975,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-core", "futures-sink", "log 0.4.17", @@ -6996,11 +6985,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-core", "futures-sink", "pin-project-lite 0.2.9", @@ -7010,9 +6999,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "indexmap", "serde", @@ -7020,9 +7009,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" [[package]] name = "toml_edit" @@ -7036,6 +7025,17 @@ dependencies = [ "toml_datetime", ] +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -7044,9 +7044,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite 0.2.9", @@ -7080,9 +7080,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" @@ -7092,7 +7092,7 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.2.1", + "bytes 1.4.0", "http", "httparse", "log 0.4.17", @@ -7111,15 +7111,15 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "uint" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", @@ -7147,15 +7147,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -7168,9 +7168,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -7192,9 +7192,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unindent" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "universal-hash" @@ -7269,9 +7269,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version-compare" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" @@ -7341,9 +7341,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "serde", @@ -7353,9 +7353,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log 0.4.17", @@ -7368,9 +7368,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7380,9 +7380,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7390,9 +7390,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -7403,15 +7403,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -7456,9 +7456,9 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", @@ -7532,37 +7532,48 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" @@ -7572,15 +7583,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" @@ -7590,15 +7595,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" @@ -7608,15 +7607,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" @@ -7626,21 +7619,15 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" @@ -7650,15 +7637,9 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "wyz" @@ -7686,9 +7667,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", @@ -7696,6 +7677,20 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zip" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "flate2", + "thiserror", + "time 0.1.45", +] + [[package]] name = "zip" version = "0.6.4" @@ -7712,19 +7707,19 @@ dependencies = [ "hmac 0.12.1", "pbkdf2", "sha1 0.10.5", - "time 0.3.16", + "time 0.3.19", "zstd", ] [[package]] name = "zip-extract" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb654964c003959ed64cbd0d7b329bcdcbd9690facd50c8617748d3622543972" +checksum = "4c5cc0309f6e81ab96c2b43d5e935025f8732c886690be8f78f68e06bad1d274" dependencies = [ "log 0.4.17", "thiserror", - "zip", + "zip 0.5.13", ] [[package]] @@ -7798,10 +7793,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.7+zstd.1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" dependencies = [ "cc", "libc", + "pkg-config", ] diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index dad44f82a..cef02b40b 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -36,4 +36,5 @@ http-types = "2.12" hex = "0.4" tide = "0.16" rand = '0.7' -semver = "1.0" \ No newline at end of file +semver = "1.0" +notify = "5.1" \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 7e52b619e..7394a575f 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -7,30 +7,59 @@ use cyfs_base::*; use cyfs_debug::Mutex; use lazy_static::lazy_static; -use once_cell::sync::OnceCell; use std::sync::Arc; use std::time::Duration; +struct DeviceConfigRepoItem { + desc: String, + repo: DeviceConfigRepoRef, +} + pub struct DeviceConfigManager { - repo: OnceCell, + repo: Mutex>, device_config_hash: Mutex>, device_config: DeviceConfig, } impl DeviceConfigManager { - pub fn new() -> Self { + fn new() -> Self { Self { - repo: OnceCell::new(), + repo: Mutex::new(None), device_config_hash: Mutex::new(None), device_config: DeviceConfig::new(), } } pub fn init(&self) -> BuckyResult<()> { + self.init_repo()?; + + // 计算当前device_config的hash + let hash = Self::calc_config_hash(); + *self.device_config_hash.lock().unwrap() = hash; + + Ok(()) + } + + // can be init multi times! + pub fn init_repo(&self) -> BuckyResult<()> { // 从system_config获取device_config依赖的desc let desc = &get_system_config().config_desc; + { + let current = self.repo.lock().unwrap(); + match &*current { + Some(item) => { + if item.desc == *desc { + return Ok(()); + } + + info!("device config's desc changed! {} -> {}", item.desc, desc); + } + None => {} + } + } + info!("will init device_config repo: {}", desc); let repo = if desc == "local" { @@ -38,9 +67,7 @@ impl DeviceConfigManager { Box::new(repo) as Box } else if desc == "cyfs_repo" || desc == "device" { let repo = DeviceConfigMetaRepo::new(); - if let Err(e) = repo.init() { - return Err(e); - } + repo.init()?; Box::new(repo) as Box } else if desc.starts_with("http") { @@ -54,17 +81,18 @@ impl DeviceConfigManager { return Err(BuckyError::new(BuckyErrorCode::NotSupport, msg)); }; - if let Err(_) = self.repo.set(Arc::new(repo)) { - unreachable!(); - } - - // 计算当前device_config的hash - let hash = Self::calc_config_hash(); - *self.device_config_hash.lock().unwrap() = hash; + *self.repo.lock().unwrap() = Some(DeviceConfigRepoItem { + desc: desc.to_owned(), + repo: Arc::new(repo), + }); Ok(()) } + pub fn get_repo(&self) -> DeviceConfigRepoRef { + self.repo.lock().unwrap().as_ref().unwrap().repo.clone() + } + pub async fn load_and_apply_config(&self) -> BuckyResult<()> { self.device_config .load_and_apply_config() @@ -117,7 +145,7 @@ impl DeviceConfigManager { } pub async fn fetch_config(&self) -> Result { - let repo = self.repo.get().unwrap().clone(); + let repo = self.get_repo(); // 从mete-chain拉取对应desc let ret = async_std::future::timeout(Duration::from_secs(60), repo.fetch()).await; diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index fa50b80f4..0560c025d 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -1,14 +1,16 @@ use super::path::PATHS; -use super::version::{ServiceVersion, ServiceListVersion}; +use super::version::{ServiceListVersion, ServiceVersion}; +use super::DEVICE_CONFIG_MANAGER; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; use std::sync::Arc; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct SystemConfig { // device_config动态更新依赖的desc文件,默认从cyfs_repo,可以指定device标识当前设备 // ServiceList对象会使用该id+version,来计算当前依赖的ServiceList对象,并从链上拉取 @@ -28,7 +30,7 @@ pub struct SystemConfig { } impl SystemConfig { - pub fn new() -> Self { + fn new() -> Self { Self { config_desc: String::from("cyfs_repo"), @@ -53,14 +55,12 @@ impl SystemConfig { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - info!("will load system-config file: {}", config_file.display()); + debug!("will load system-config file: {}", config_file.display()); let node = self.load_as_json(&config_file).await?; self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } @@ -165,28 +165,47 @@ impl SystemConfig { return Err(BuckyError::from(msg)); } - info!( - "system-config: config_desc={}, target={}", - self.config_desc, self.target - ); - Ok(()) } } -use once_cell::sync::OnceCell; -static SYSTEM_CONFIG: OnceCell> = OnceCell::new(); +use std::sync::Mutex; +static SYSTEM_CONFIG: Mutex>> = Mutex::new(None); // 只在进程初始化时候调用一次 pub async fn init_system_config() -> BuckyResult<()> { let mut system_config = SystemConfig::new(); system_config.load_config().await?; - SYSTEM_CONFIG.set(Arc::new(system_config)).unwrap(); + info!("init system config: {:?}", system_config); + *SYSTEM_CONFIG.lock().unwrap() = Some(Arc::new(system_config)); + + SystemConfigMonitor::start(); Ok(()) } -pub fn get_system_config() -> Arc { - SYSTEM_CONFIG.get().unwrap().clone() +pub async fn reload_system_config() -> BuckyResult<()> { + let mut system_config = SystemConfig::new(); + system_config.load_config().await?; + + debug!("reload system config success! {:?}", system_config); + { + let mut current = SYSTEM_CONFIG.lock().unwrap(); + if current.as_deref() != Some(&system_config) { + info!( + "reload system config and changed! {:?} -> {:?}", + current.as_deref(), system_config + ); + *current = Some(Arc::new(system_config)); + } + } + + let _ = DEVICE_CONFIG_MANAGER.init_repo(); + + Ok(()) } + +pub fn get_system_config() -> Arc { + SYSTEM_CONFIG.lock().unwrap().clone().unwrap() +} \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/version.rs b/src/service/ood-daemon/src/config/version.rs index 1822f6403..d29d91009 100644 --- a/src/service/ood-daemon/src/config/version.rs +++ b/src/service/ood-daemon/src/config/version.rs @@ -2,7 +2,7 @@ use cyfs_base::*; use std::str::FromStr; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum ServiceListVersion { Nightly, // default version Specific(String), // user confined @@ -38,7 +38,7 @@ impl FromStr for ServiceListVersion { } // 版本列表定义 -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum ServiceVersion { Default, // use the version config in service list Specific(String), // semver, * as the newest version diff --git a/src/service/ood-daemon/src/config_repo/test.rs b/src/service/ood-daemon/src/config_repo/test.rs index 81ee0f461..ec734df71 100644 --- a/src/service/ood-daemon/src/config_repo/test.rs +++ b/src/service/ood-daemon/src/config_repo/test.rs @@ -1,14 +1,13 @@ -use crate::config::DeviceConfigManager; +use crate::config::DEVICE_CONFIG_MANAGER; use crate::init_system_config; async fn test() { init_system_config().await.unwrap(); + + DEVICE_CONFIG_MANAGER.init().unwrap(); - let config_manager = DeviceConfigManager::new(); - config_manager.init().unwrap(); - - config_manager.fetch_config().await.unwrap(); - config_manager.fetch_config().await.unwrap(); + DEVICE_CONFIG_MANAGER.fetch_config().await.unwrap(); + DEVICE_CONFIG_MANAGER.fetch_config().await.unwrap(); } #[test] diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index c4f6d0c6b..34737f778 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -1,5 +1,5 @@ use super::gateway_monitor::GATEWAY_MONITOR; -use crate::config::{init_system_config, DeviceConfigManager}; +use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER}; use crate::service::ServiceMode; use crate::service::SERVICE_MANAGER; use cyfs_base::{bucky_time_now, BuckyResult}; @@ -46,7 +46,6 @@ impl Default for ActionActive { #[derive(Clone)] pub struct Daemon { mode: ServiceMode, - device_config_manager: Arc, no_monitor: bool, last_active: Arc, } @@ -54,11 +53,8 @@ pub struct Daemon { impl Daemon { // add code here pub fn new(mode: ServiceMode, no_monitor: bool) -> Self { - let device_config_manager = DeviceConfigManager::new(); - Self { mode, - device_config_manager: Arc::new(device_config_manager), no_monitor, last_active: Arc::new(ActionActive::default()), } @@ -67,7 +63,7 @@ impl Daemon { pub async fn run(&self) -> BuckyResult<()> { init_system_config().await?; - self.device_config_manager.init()?; + DEVICE_CONFIG_MANAGER.init()?; OOD_STATUS_MANAGER.start().await?; @@ -101,7 +97,7 @@ impl Daemon { .map(|v| v.config.fid.clone()); // 首先尝试下载同步配置 - match self.device_config_manager.fetch_config().await { + match DEVICE_CONFIG_MANAGER.fetch_config().await { Ok(changed) => { if changed { need_load_config = true; @@ -115,7 +111,7 @@ impl Daemon { } if need_load_config { - if let Err(e) = self.device_config_manager.load_and_apply_config().await { + if let Err(e) = DEVICE_CONFIG_MANAGER.load_and_apply_config().await { // 加载配置失败,那么需要等下一个周期继续尝试load error!("load config failed! now will retry on next loop! {}", e); } else { diff --git a/src/service/ood-daemon/src/daemon/stop.rs b/src/service/ood-daemon/src/daemon/stop.rs index b0e635901..1d669c2bf 100644 --- a/src/service/ood-daemon/src/daemon/stop.rs +++ b/src/service/ood-daemon/src/daemon/stop.rs @@ -1,26 +1,23 @@ use crate::config::ServiceState; -use crate::config::{init_system_config, DeviceConfigManager, OOD_DAEMON_SERVICE}; +use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER, OOD_DAEMON_SERVICE}; use crate::service::SERVICE_MANAGER; use cyfs_base::*; pub struct ServicesStopController { - device_config_manager: DeviceConfigManager, } impl ServicesStopController { pub fn new() -> Self { - let device_config_manager = DeviceConfigManager::new(); Self { - device_config_manager, } } pub async fn stop_all(&self) -> BuckyResult<()> { init_system_config().await?; - self.device_config_manager.init()?; + DEVICE_CONFIG_MANAGER.init()?; - let mut list = self.device_config_manager.load_config()?; + let mut list = DEVICE_CONFIG_MANAGER.load_config()?; info!("service list: {:?}", list); diff --git a/src/service/ood-daemon/src/repo/manager.rs b/src/service/ood-daemon/src/repo/manager.rs index 1b1f3e27f..eff36e9d4 100644 --- a/src/service/ood-daemon/src/repo/manager.rs +++ b/src/service/ood-daemon/src/repo/manager.rs @@ -73,6 +73,7 @@ pub trait Repo: Send + Sync { pub struct RepoManager { cache_dir: PathBuf, + repo_config: Mutex>, repo_list: Mutex>>>, } @@ -99,6 +100,7 @@ impl RepoManager { pub fn new() -> RepoManager { let cache_dir = Self::cache_dir(); RepoManager { + repo_config: Mutex::new(None), repo_list: Mutex::new(Vec::new()), cache_dir, } @@ -112,6 +114,7 @@ impl RepoManager { let repo = Arc::new(Box::new(repo) as Box); Ok(Self { + repo_config: Mutex::new(None), repo_list: Mutex::new(vec![repo]), cache_dir, }) @@ -221,13 +224,23 @@ impl RepoManager { // 从system_config的repo字段加载配置 pub async fn load(&self, repo_node: &Vec) -> BuckyResult<()> { assert!(repo_node.len() > 0); - assert!(self.repo_list.lock().unwrap().is_empty()); + let config_string = serde_json::to_string(&repo_node).unwrap(); + { + let current = self.repo_config.lock().unwrap(); + if current.as_deref() == Some(&config_string) { + return Ok(()); + } + + info!("repo config changed! {:?} -> {}", &*current, config_string); + } + + let mut list = vec![]; for item in repo_node.iter() { info!("new repo item: {:?}", item); if let toml::Value::Table(m) = item { let repo = Self::load_repo_item(&m).await?; - self.repo_list.lock().unwrap().push(Arc::new(repo)); + list.push(Arc::new(repo)); } else { let msg = format!("unsupport repo item format!"); error!("{}", msg); @@ -235,6 +248,18 @@ impl RepoManager { } } + // Support for repeated loading + { + let mut current = self.repo_list.lock().unwrap(); + if !current.is_empty() { + warn!("will replace current repo list!"); + } + + *current = list; + } + + *self.repo_config.lock().unwrap() = Some(config_string); + Ok(()) } diff --git a/src/service/ood-daemon/src/status/service_status.rs b/src/service/ood-daemon/src/status/service_status.rs index 8fa4b1278..e19b25b7f 100644 --- a/src/service/ood-daemon/src/status/service_status.rs +++ b/src/service/ood-daemon/src/status/service_status.rs @@ -1,5 +1,5 @@ -use crate::SERVICE_MANAGER; -use crate::config::{ServiceState, ServiceConfig, DeviceConfigManager}; +use crate::{SERVICE_MANAGER}; +use crate::config::{ServiceState, ServiceConfig, DEVICE_CONFIG_MANAGER}; use crate::service::ServicePackageLocalState; use cyfs_base::bucky_time_now; @@ -71,7 +71,7 @@ impl OODDaemonStatusGenerator { } fn gen() -> OODDaemonStatus { - let device_config = match DeviceConfigManager::new().load_config() { + let device_config = match DEVICE_CONFIG_MANAGER.load_config() { Ok(list) => list, Err(_) => vec![], }; From 7551587087825056ce8a266aa05ead692a584664 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:35:08 +0800 Subject: [PATCH 137/553] Add dynamic monitoring mechanism for system-config.toml --- src/service/ood-daemon/src/config/mod.rs | 1 + src/service/ood-daemon/src/config/monitor.rs | 75 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/service/ood-daemon/src/config/monitor.rs diff --git a/src/service/ood-daemon/src/config/mod.rs b/src/service/ood-daemon/src/config/mod.rs index 6836c142d..5383a844a 100644 --- a/src/service/ood-daemon/src/config/mod.rs +++ b/src/service/ood-daemon/src/config/mod.rs @@ -4,6 +4,7 @@ mod path; mod device_config_manager; mod device_config; mod version; +mod monitor; pub use device_config::DeviceConfig; pub use service_config::*; diff --git a/src/service/ood-daemon/src/config/monitor.rs b/src/service/ood-daemon/src/config/monitor.rs new file mode 100644 index 000000000..925be909d --- /dev/null +++ b/src/service/ood-daemon/src/config/monitor.rs @@ -0,0 +1,75 @@ +use super::path::PATHS; +use super::reload_system_config; +use cyfs_base::*; + + + +pub struct SystemConfigMonitor { + watcher: Option, +} + +impl SystemConfigMonitor { + pub fn start() { + use once_cell::sync::OnceCell; + + static INIT: OnceCell = OnceCell::new(); + INIT.get_or_init(|| { + let watcher = Self::start_monitor().ok(); + + Self::start_periodic_check(); + Self { + watcher, + } + }); + } + + fn start_periodic_check() { + async_std::task::spawn(async move { + loop { + async_std::task::sleep(std::time::Duration::from_secs(60 * 15)).await; + let _ = reload_system_config().await; + } + }); + } + + fn start_monitor() -> BuckyResult { + use notify::{RecursiveMode, Watcher}; + + let mut watcher = notify::recommended_watcher(|res| match res { + Ok(event) => { + info!("got system config file event: {:?}", event); + + if PATHS.system_config.is_file() { + async_std::task::spawn(async move { + let _ = reload_system_config().await; + }); + } + } + Err(e) => error!("watch system config file error: {:?}", e), + }) + .map_err(|e| { + let msg = format!("create system-config.toml monitor failed! {}", e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::NotSupport, msg) + })?; + + watcher + .watch(&PATHS.system_config, RecursiveMode::NonRecursive) + .map_err(|e| { + let msg = format!( + "watch system-config.toml monitor failed! file={}, {}", + PATHS.system_config.display(), + e + ); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + info!( + "start monitor system-config file change! file={}", + PATHS.system_config.display() + ); + + Ok(watcher) + } +} \ No newline at end of file From a82bf94d033f0f88f09748ebcd844f81e7db4498 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:43:37 +0800 Subject: [PATCH 138/553] Fix two log param errors --- .../cyfs-base/src/objects/object_map/isolate_path_env.rs | 2 +- src/component/cyfs-base/src/objects/object_map/single_env.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs b/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs index f871a9d6c..2cc26a3f1 100644 --- a/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs +++ b/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs @@ -130,7 +130,7 @@ impl ObjectMapIsolatePathOpEnv { if value.is_none() { let msg = format!( "load ioslate_path_op_env with inner_path but not found! root={}, inner_path={}", - obj_map_id, obj_map_id, + obj_map_id, inner_path, ); error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); diff --git a/src/component/cyfs-base/src/objects/object_map/single_env.rs b/src/component/cyfs-base/src/objects/object_map/single_env.rs index 9cfc50cd2..e529df0cd 100644 --- a/src/component/cyfs-base/src/objects/object_map/single_env.rs +++ b/src/component/cyfs-base/src/objects/object_map/single_env.rs @@ -140,7 +140,7 @@ impl ObjectMapSingleOpEnv { if value.is_none() { let msg = format!( "load single_op_env with inner_path but not found! root={}, inner_path={}", - obj_map_id, obj_map_id, + obj_map_id, inner_path, ); error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); From 24e6e615f7fe535df178ddbdf31d67c999ad98ea Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 19:07:13 +0800 Subject: [PATCH 139/553] Add mechanism that trigger immediate update after system config changes --- src/service/ood-daemon/src/config/mod.rs | 3 +- src/service/ood-daemon/src/config/monitor.rs | 57 +++++++++++++------ .../ood-daemon/src/config/system_config.rs | 16 ++---- src/service/ood-daemon/src/daemon/daemon.rs | 40 ++++++++----- .../ood-daemon/src/service/service_manager.rs | 8 ++- 5 files changed, 78 insertions(+), 46 deletions(-) diff --git a/src/service/ood-daemon/src/config/mod.rs b/src/service/ood-daemon/src/config/mod.rs index 5383a844a..d623631bc 100644 --- a/src/service/ood-daemon/src/config/mod.rs +++ b/src/service/ood-daemon/src/config/mod.rs @@ -11,4 +11,5 @@ pub use service_config::*; pub use system_config::*; pub use path::*; pub use version::*; -pub use device_config_manager::{DeviceConfigManager, DEVICE_CONFIG_MANAGER}; \ No newline at end of file +pub use device_config_manager::{DeviceConfigManager, DEVICE_CONFIG_MANAGER}; +pub use monitor::SystemConfigMonitor; \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/monitor.rs b/src/service/ood-daemon/src/config/monitor.rs index 925be909d..d7246003f 100644 --- a/src/service/ood-daemon/src/config/monitor.rs +++ b/src/service/ood-daemon/src/config/monitor.rs @@ -1,47 +1,68 @@ use super::path::PATHS; use super::reload_system_config; +use crate::config::DEVICE_CONFIG_MANAGER; +use crate::daemon::Daemon; use cyfs_base::*; +use std::sync::Arc; - +#[derive(Clone)] pub struct SystemConfigMonitor { - watcher: Option, + watcher: Arc>, + daemon: Daemon, } impl SystemConfigMonitor { - pub fn start() { + fn new(daemon: Daemon) -> Self { + let watcher = Self::start_monitor(daemon.clone()).ok(); + + Self::start_periodic_check(daemon.clone()); + Self { + watcher: Arc::new(watcher), + daemon, + } + } + + pub fn start(daemon: Daemon) { use once_cell::sync::OnceCell; static INIT: OnceCell = OnceCell::new(); - INIT.get_or_init(|| { - let watcher = Self::start_monitor().ok(); - - Self::start_periodic_check(); - Self { - watcher, - } - }); + INIT.get_or_init(|| Self::new(daemon)); } - fn start_periodic_check() { + async fn on_changed(daemon: &Daemon) -> BuckyResult<()> { + let changed = reload_system_config().await?; + if !changed { + return Ok(()); + } + + let _ = DEVICE_CONFIG_MANAGER.init_repo(); + + daemon.wakeup_check_update(); + + Ok(()) + } + + fn start_periodic_check(daemon: Daemon) { async_std::task::spawn(async move { loop { - async_std::task::sleep(std::time::Duration::from_secs(60 * 15)).await; - let _ = reload_system_config().await; + async_std::task::sleep(std::time::Duration::from_secs(60 * 60)).await; + let _ = Self::on_changed(&daemon).await; } }); } - fn start_monitor() -> BuckyResult { + fn start_monitor(daemon: Daemon) -> BuckyResult { use notify::{RecursiveMode, Watcher}; - let mut watcher = notify::recommended_watcher(|res| match res { + let mut watcher = notify::recommended_watcher(move |res| match res { Ok(event) => { info!("got system config file event: {:?}", event); if PATHS.system_config.is_file() { + let daemon = daemon.clone(); async_std::task::spawn(async move { - let _ = reload_system_config().await; + let _ = Self::on_changed(&daemon).await; }); } } @@ -72,4 +93,4 @@ impl SystemConfigMonitor { Ok(watcher) } -} \ No newline at end of file +} diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 0560c025d..1f5341cc0 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -1,10 +1,8 @@ use super::path::PATHS; use super::version::{ServiceListVersion, ServiceVersion}; -use super::DEVICE_CONFIG_MANAGER; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; -use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -59,9 +57,7 @@ impl SystemConfig { let node = self.load_as_json(&config_file).await?; - self.parse_config(node).await?; - - Ok(()) + self.parse_config(node).await } async fn load_as_json(&self, file_path: &Path) -> BuckyResult { @@ -180,16 +176,15 @@ pub async fn init_system_config() -> BuckyResult<()> { info!("init system config: {:?}", system_config); *SYSTEM_CONFIG.lock().unwrap() = Some(Arc::new(system_config)); - SystemConfigMonitor::start(); - Ok(()) } -pub async fn reload_system_config() -> BuckyResult<()> { +pub async fn reload_system_config() -> BuckyResult { let mut system_config = SystemConfig::new(); system_config.load_config().await?; debug!("reload system config success! {:?}", system_config); + let mut changed = false; { let mut current = SYSTEM_CONFIG.lock().unwrap(); if current.as_deref() != Some(&system_config) { @@ -198,12 +193,11 @@ pub async fn reload_system_config() -> BuckyResult<()> { current.as_deref(), system_config ); *current = Some(Arc::new(system_config)); + changed = true; } } - let _ = DEVICE_CONFIG_MANAGER.init_repo(); - - Ok(()) + Ok(changed) } pub fn get_system_config() -> Arc { diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index 34737f778..4c59ca60e 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -1,11 +1,11 @@ use super::gateway_monitor::GATEWAY_MONITOR; -use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER}; +use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER, SystemConfigMonitor}; use crate::service::ServiceMode; use crate::service::SERVICE_MANAGER; +use crate::status::OOD_STATUS_MANAGER; use cyfs_base::{bucky_time_now, BuckyResult}; use cyfs_util::*; use ood_control::OOD_CONTROLLER; -use crate::status::OOD_STATUS_MANAGER; use async_std::task; use futures::future::{AbortHandle, Abortable}; @@ -48,6 +48,7 @@ pub struct Daemon { mode: ServiceMode, no_monitor: bool, last_active: Arc, + check_update_waker: Arc>>, } impl Daemon { @@ -57,6 +58,7 @@ impl Daemon { mode, no_monitor, last_active: Arc::new(ActionActive::default()), + check_update_waker: Arc::new(Mutex::new(None)), } } @@ -75,6 +77,8 @@ impl Daemon { let _ = GATEWAY_MONITOR.init().await; + SystemConfigMonitor::start(self.clone()); + self.start_check_active(); self.start_check_service_state(); @@ -84,6 +88,13 @@ impl Daemon { Ok(()) } + pub fn wakeup_check_update(&self) { + if let Some(abort_handle) = self.check_update_waker.lock().unwrap().take() { + info!("will wakeup check update now!"); + abort_handle.abort(); + } + } + async fn run_check_update(&self, notify: BindNotify) { let mut need_load_config = true; loop { @@ -177,19 +188,20 @@ impl Daemon { // 检查绑定状态 let timer = task::sleep(Duration::from_secs(60 * 10)); - if OOD_CONTROLLER.is_bind() { - timer.await; - } else { - let (abort_handle, abort_registration) = AbortHandle::new_pair(); - *notify.abort_handle.lock().unwrap() = Some(abort_handle); - match Abortable::new(timer, abort_registration).await { - Ok(_) => { - debug!("check loop wait timeout, now will check once"); - } - Err(futures::future::Aborted { .. }) => { - info!("check loop waked up, now will check once"); - } + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + + if !OOD_CONTROLLER.is_bind() { + *notify.abort_handle.lock().unwrap() = Some(abort_handle.clone()); + } + *self.check_update_waker.lock().unwrap() = Some(abort_handle); + + match Abortable::new(timer, abort_registration).await { + Ok(_) => { + debug!("check update loop wait timeout, now will check once"); + } + Err(futures::future::Aborted { .. }) => { + info!("check update loop waked up, now will check once"); } } } diff --git a/src/service/ood-daemon/src/service/service_manager.rs b/src/service/ood-daemon/src/service/service_manager.rs index 2d1540057..4f656c614 100644 --- a/src/service/ood-daemon/src/service/service_manager.rs +++ b/src/service/ood-daemon/src/service/service_manager.rs @@ -462,9 +462,13 @@ impl ServiceManager { pub async fn sync_service_packages(&self) { let _lock = self.sync_lock.lock().await; - debug!("will sync all service packages"); - let service_list = self.service_list.lock().unwrap().clone(); + if service_list.is_empty() { + warn!("sync all service packages but is empty!"); + return; + } + + debug!("will sync all service packages"); for (name, service_info) in service_list { if service_info.service.is_none() { error!("service not init yet! name={}", name); From b50259c718350df559436d6ce6dd8a4f8fc629d5 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 19:27:37 +0800 Subject: [PATCH 140/553] Try using git commit logs to organize changelog --- CHANGELOG-nightly.md | 743 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 743 insertions(+) create mode 100644 CHANGELOG-nightly.md diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md new file mode 100644 index 000000000..0c79dfc4b --- /dev/null +++ b/CHANGELOG-nightly.md @@ -0,0 +1,743 @@ +## [1.0.0.718] -- 2023/2/21 +1b0cf118 Change sync services packages from parallel to serial +638848a2 Remove two spawn task using for cancel on timeout +70837da7 Fix error op_env type check in requestor +e3f55f6e Improve timeout and retry strategy for repo download in ood-daemon service +9c3c63ab Meta db initialization switch to transaction mode +1e4e4277 Modify: add some statistic logs for ndn +94d8f7a4 Merge branch '104-appmanager-suppport-local-app-repo-store' +34580770 Modify: add some statistic logs for ndn +7522c0fe Email Sender support starttls +10d27023 App Manager support install app from local repo +2a3c1dc1 ood-installer support sync app repo +51f0be28 WIP: App Manager Support Local Repo +e6392f5b WIP: App Manager reflator app install logic +e65fe061 WIP: AppManager add repo type, use zip_extract to extract app service package + +## [1.0.0.715] -- 2023/2/20 +e51af4f2 Set docker api timeout to 300s +b213c3fe Fix: tcp not update active time when recv packet +24553a9c Improve the object layer strategy detection of after pass the first layer rpath access verification +574cfddf OOD-daemon will now report an error and exit if it fails to load the repo +0ab51327 Add version output in process alive check log +14c004b6 Fix meta-stat email format +4daab080 App-manager report app status to ood-daemon +c09ddea9 Fix field names of ood status +f3449363 Fix: monitor create desc when desc not existed on chain +a4e0e755 Fix: stream break when loss fin ack packet +0d2393f3 Fix: monitor create desc error +ba302dd4 Merge remote-tracking branch 'origin/107-support-multiple-global-states-in-cyfs-stack' into main +3d70797d Add group state test case +63e3e712 Fix a assert error when global state is init +61a5eff1 Cyfs monitor use generated identify to test metachain read and write +3d4aefc9 Improve the use of u64::MAX in two places +ee5323ea Delete some useless logs +90d9b5c8 meta spv support storage anbd query objects by object id, body hash +1101829c Add isolate_id method for GlobalStateRawProcessor +e3765b61 Add global state raw processor for use by external components of cyfs-stack +ff03c824 Add the persistence mechanism of all the global state list +b4c4de04 Refactor GlobalStateManager to support multiple global-states +937c7dbe Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +b4284830 Add exists methods into collection for to check if exists +5bcc2984 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +da09ed21 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +412d03ff Merge branch '99-recycle-unused-bdt-tunnel-instances' +979773da Fix: implement stream reserving 2*msl state with lru cache +25c53b07 Refactory: export private methods with pub(crate) +114f1d1b Fix: bdt unit test sn with ipv6 endpoints +fdde1948 Merge branch '95-ipv6-support-refactory' +1b91764a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8d522ec7 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +1875de3d Add object and name for meta in cyfs-stack +3e12b1be Fix cyfs-perf deps Improve the format of some tomls +e83890fc Add noc meta cache to optimize update last access write operation +2ff85f4d Publish cyfs-core new version +d917d648 Bump cyfs-core version +0dd49104 Fix cyfs-core deps +220c7ab2 Fix compile error +dd2f2f17 Publish new cargo packages +fb63c476 Bump cargo package version and dependences +89917227 Merge branch 'main' into beta +75aea584 Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8f60a00b Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +2ebd1e20 Add object and name for meta in cyfs-stack +4d5a9e90 Fix cyfs-perf deps Improve the format of some tomls +2121a11e Add noc meta cache to optimize update last access write operation +078b27d3 Publish cyfs-core new version +019b09d9 Bump cyfs-core version +51e4365b Fix cyfs-core deps +a04d6e88 Fix compile error +038b75b4 Publish new cargo packages +279ce4bd Bump cargo package version and dependences +026c1383 Merge branch 'main' into beta +ccb044db Integrate ood-daemon services status +4af47a92 Improve ServiceState fields spelling +f9eaed01 Add service status related def +ec1ba569 ood-daemon adds independent status http server +5bc02595 Add service status support to ood-daemon +ff14b0d1 Add external http server support to ood control +287c9468 Fix app-manager compile error +08249fa5 Cyfs Monitor restore case interval time after success +c6c372dc Add noc test cases +b176d6a5 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +97bd7bb9 Print warning when decapp missing status or stop scripts +9f85c599 Stream shutdown success at closed state +71ffede0 Fix: fix reset key logic +ec2194ec Integrate ood-daemon services status +2b30769b Improve ServiceState fields spelling +eb881d46 Add service status related def +5dc9c661 ood-daemon adds independent status http server +b2882ff5 Add service status support to ood-daemon +cfc87989 Add external http server support to ood control +d54866c2 Fix app-manager compile error +f0822e79 Cyfs Monitor restore case interval time after success +ab37ea21 Add noc test cases +fa1cc5c0 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +13cdfe46 Print warning when decapp missing status or stop scripts +5ad5d183 Fix: bdt unit test sn with ipv6 endpoints +9607470d Merge branch '95-ipv6-support-refactory' +a8ba267a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +5c2a8d77 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +c88a5e76 Add object and name for meta in cyfs-stack +598df4a8 Fix cyfs-perf deps Improve the format of some tomls +1952c7ee Add noc meta cache to optimize update last access write operation +ba181cef Publish cyfs-core new version +139a9ab6 Bump cyfs-core version +11c7205a Fix cyfs-core deps +76f871ea Fix compile error +30f99d3d Publish new cargo packages +4228e263 Bump cargo package version and dependences +34cb38f4 Merge branch 'main' into beta +87956987 Integrate ood-daemon services status +086dcd8a Improve ServiceState fields spelling +51f135c6 Add service status related def +0bd37768 ood-daemon adds independent status http server +933ed8cd Add isolate_path_env stub test cases +1be055d0 Add service status support to ood-daemon +d3e16c4d Add native ioslate_path_env component test cases and fix some test warnings +25fa3e85 Add external http server support to ood control +60b04789 Add ioslate path env stub +4b32f2b0 Optimize objectmap path to support non-transactional mode +5a6aa9b7 Integrate isolate path env into global-state services +6ccd4ef9 Add isolate path env impl +c78ae028 Fix app-manager compile error +429bddd8 Cyfs Monitor restore case interval time after success +9dd5aac3 Add noc test cases +c7132f26 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +cbf80ee3 Print warning when decapp missing status or stop scripts +2451a583 Fix: package enter write closed state correctly +0d4443ff Panic manager supports multiple bug reporters +f6749bb1 Stream shutdown success at closed state +f1a4cc60 Create a directory if it does not exist when downloading to a local file +28a37154 Improve cyfs-stack's control strategy for task manager resume_task +a63d6854 Fix: fix reset key logic +b7a3e3c9 Add dingtalk_bug_report method to PanicBuilder for external use +445fc501 Optimize some logs output +cc70a84b Add init-ood-daemon param to ood-installer +28fbed65 Remove cyfs-bdt's dependence on os-id lib +18d1534d Improve the ndn request logs output +8538be10 Add req_path suport to front o protocol for acl +1a621713 Send start notify when cyfs-monitor started +e8752b2a Improve the problem that the front r protocol cannot correctly handle data req_path for acl +4abdcf6b Use search instead of get for device in context +c8ad90a8 Add target device prompt info to access reject msg for better debug +4cc08abb Improve cyfs stack test cases +9cf2aafe Improve some logs output about chunk cache +b30d8cd6 Fix: chunk list task download split chunks dumplicatedly +c2570da0 Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +b7ecdbc7 Fix: using channel got reserved correctly +a8a9a3b9 Fix: cyfs-monitor report, use sn-online-test to test sn server status +c3964a38 impl: log udp socket's recv loop thread os id +cb239140 Improve some logs output +67b2aed5 Add seperate sn-online-test program +b6e22b0f Fix: cyfs stack resp interest with NotFound if chunk not exists on default +e1bbe10d Fix: Add some log for dectecting zero speed source +d3535025 Fix: modify resend piece control send time +04629f0f Fix: channel ignore estimate request for sequence lost +11bfb5a5 Correct the use of sync mechanism on bdt download context +d2d9ff8f Bdt acl callback can correctly handle empty referer now +a2ebb0df Changed to auto cancel strategy for ndn task with context param +d653c967 Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +a2cb418a Remove useless ood_resolver field from ndn service relate codes +236abdbb Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +cb0cba8a Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +dce764a9 Add object and name for meta in cyfs-stack +e0dac397 Fix: tcp stream don't reset tunnel when break +5af0b5fb Fix: implement stream reserving 2*msl state with lru cache +3da42793 Fix cyfs-perf deps Improve the format of some tomls +9867ad29 Add noc meta cache to optimize update last access write operation +e11ff3ef Publish cyfs-core new version +95a5c99d Bump cyfs-core version +c168c17a Fix cyfs-core deps +427050c6 Fix compile error +2412d747 Integrate ood-daemon services status +aa5ff976 Publish new cargo packages +0249ba77 Bump cargo package version and dependences +96e3bb69 Merge branch 'main' into beta +0493c935 Improve ServiceState fields spelling +5a88c564 Add service status related def +00bf2764 ood-daemon adds independent status http server +c013612e Fix: bdt mem device cache limited size +39de9529 Refactory: export private methods with pub(crate) +7785029d Fix: package enter write closed state correctly +101db063 Stream shutdown success at closed state +3fca43d8 Create a directory if it does not exist when downloading to a local file +ac0e4f2a Improve cyfs-stack's control strategy for task manager resume_task +4d8bfacc Fix: fix reset key logic +96e1c1e6 Panic manager supports multiple bug reporters +8d9b7929 Add dingtalk_bug_report method to PanicBuilder for external use +7825a4ea Optimize some logs output +fa6867c6 Add init-ood-daemon param to ood-installer +9aa4489c Remove cyfs-bdt's dependence on os-id lib +66b856fc Improve the ndn request logs output +c0622388 Add req_path suport to front o protocol for acl +cc24f8e0 Send start notify when cyfs-monitor started +10ace371 Improve the problem that the front r protocol cannot correctly handle data req_path for acl +6c59337d Use search instead of get for device in context +ef0f880d Add target device prompt info to access reject msg for better debug +beb0e7be Add service status support to ood-daemon +edc1d1f6 Add external http server support to ood control +e5e9a3a5 Refactory: stream release tunnel guard when closed +009c3c8a Refactory: export private methods with pub(crate) +8e21764a Refactory: export private methods with pub(crate) +743c2fcf Impl: recycle unused tunnel +b4eb9f85 Add isolate_path_env stub test cases +b0c6fd63 Add native ioslate_path_env component test cases and fix some test warnings +3f14f978 Impl: add a test for sn ipv6 ping +ff916188 Add ioslate path env stub +dd437a1f Impl: sn support ipv6 ping +b69709df Optimize objectmap path to support non-transactional mode +0de3fc0c Integrate isolate path env into global-state services +edacc65a Add isolate path env impl +29fed496 Remove complie warning +f3f66501 Impl: Add transfered and recursion close method to ndn task +027e9ae4 Impl: Add transfered and recursion close method to ndn task +6a1f7ed1 Rebase: rebase to 74-integrate-bdt-task-context-and-group +aa682520 Refactory: impl trans api for close upload group +260cbdf8 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +c2bd5612 Refactory: impl trans api for close upload group +99bbebfc Refactory: impl trans api for upload group +c19064b5 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +2f47bcc0 Fix: reserve or recycle channels when all reference released +ae3f02eb Impl: cancel task with user defined error +82692c64 Fix: download task progress/speed +bc3ba88e Rebase: rebase to 74-integrate-bdt-task-context-and-group +58d6d195 Refactory: impl trans api for close upload group +5dad1539 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +30aa07ae Fix: reserve or recycle channels when all reference released +acaa42fb Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +09076f70 Add uptime and boot_time into get_system_info +2b81e62a Fix: correctly wait dapp process +3bbbcfc3 Add total trans bytes field in get_system_info Added network card deduplication in some environments +80fa0863 Publish new cargo packages +ae40d694 Fix cyfs-util publish error +ee957a29 Bump cargo packages version +89341b52 Fix: retry sn list when offline +1370e83c Improve ndn test case with get_data +3584395e Improve the resp's return logic of get_data with error prompt +a3a5172e Use of http requestor for get_data and put_data methods as default +0347e50e Error of reading resp is returned correctly in ws mode +87d26ad6 Merge remote-tracking branch 'origin/main' into main +0df70f89 Sync projects for trans and stack object relate apis's changes +2ef0d178 Fix a compile error with requestor config and some warnings +4b716f44 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +1a15a767 Fix: trigger chunk downloader's on_drain method +e9faea63 Add some logs +a8dedd60 Add serialization support for storage base on global state +6effd696 Add log for named-data-client chunk reading +9edf7c31 Merge branch '74-integrate-bdt-task-context-and-group' +3fcdbf0c Improve ood-daemon's upgrade detection and restart logic +e0323ea1 Add host mode support to browser sanbox +91e519ec Also check app exclude list when install or start app +66acc69e Merge pull request #88 from buckyos/fix-container-dns +f1a63712 Ood-installer support only start ood-daemon +6514acec Fix AppManager startup param +ee80ce8c Fix AppManager config path, load config after log init +cb2ac1ee Mixed the usage of different requestor config for zone simulator stacks +be10f64b Add shared stack cache logic to zone simulator +5da765af Remove shared stack support and cache from cyfs-stack-loader +c2708f59 Improve open shared stack relate logic and add requestor config params +6150617a Temporarily disable all ipv6 addresses for bdt stack +95654ae5 App Manager AppSource logic +e849439c AppManager supports more detailed configuration +715e851e WIP: add new config for app manager +2ded38db Modify the way to start file uploader +0a50ed5f Improve the update state relate logic for service in ood-daemon service +c7de6539 Fix: avoid duplicate hole punching process when retry sn call +e828e7b5 Merge remote-tracking branch 'origin/fix-container-dns' +f8f4381b Add --startup-mode for ood-daemon startup script +c7bf12f2 Add startup-mode to ood-daemon service with network verify on system startup +b9aca01d Add active check in daemon update and state check loop +dc6aa3d9 Add timeout for repo in ood-daemon service +20ec54d1 Start the monitor service synchronously on startup +2e66ff4a Add service_list cache mechanism for meta config repo +d758151b Remove the local status of meta config repo in ood-daemon service +f99caadc Fix: retry sn list when builder not establish in time +b143379f Integrate surf requestor into shared stack +7eed812f App-tool and app-tool-ex return error correctly +09f79e9a Remove redundant service requestors constructor +cd8588de Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f5873108 Add surf based requestor +889d7f81 Adjust the file directory structure of requestsors in cyfs-lib +e7e9781e Fix some compile errors and warnings +3aa50d32 Remove the useless base project +4de7e33d Add app-manager.toml config file support to ood-installer tool +9317c01d Remove the useless old configuration of acl.toml +5af28985 Improve the error status of build relate tasks +a762fecf Merge branch 'fix-container-dns' into beta +b3231559 Fix compile +832e7a20 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b2471088 Fix container dns, when resolv contain 127.0.0.53 +bde55b1a Merge branch 'main' into beta +4dd330fe Merge branch 'main' into beta +35cabb3f Merge branch 'main' into beta +bd9326c9 File upload tool only support windows & mac for now. +01a46434 Open upload tool with "open" cmd on Mac +b45d377f Fix:ping client doesn't update local device +b36e728e Fix:ping client doesn't update local device +d9bd6698 Remove handler and event manager's none mode +980b5392 Add some field compatibility with the old version's data on new db format +6541571a Fix: pannic on time escape of call session +c0ceda78 Improve ws session and manager stop-related timing logic +f30cc9c8 Fix: some warning with while let +473e56d6 Add delayed start mechanism for router handler and events +74e30500 Fix: downloading speed/progress for chunk_list/file task use percent +172c5c9e Add shared stack stop test case +d670b458 Improve ws and event manager stop strategy +5841a4fb Improve ws session and ws client stop strategy +b62c204a Refactor ws session related logic and improve packet parser logic +706f06e6 Add stop method to shared stack with requestors +b45ddcf1 Enable none mode for handler and event system in shared stack +a1d67489 Optimize the use of requestor by the service component and adopt the shared mode +6acc40fa Remove http handler support for shared stack +5c3abc42 Add stop method to handler and event manager +b24935d7 Add stop method for ws client +6f55517f Publish new cargo packages +8c933ffc Fix cyfs-util publish error +bf75d29e Bump cargo packages version +bce2a745 Merge branch 'main' into beta +acbd636a Refactory: Add track chunk method option to publish dir/file methods +a022c2cc Fix the bug that search context will enter an infinite loop +a8a57c27 Improve the result of router get_object with flash flags is true +9f3d4e8d Fix the bug for decode context path param without fix +4236102e Add router support for group relate methods Add target check for publish_file method +3d758fcd Merge branch 'main' into beta +0843bbba Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead (#87) +387362a2 Rebase: rebase to 74-integrate-bdt-task-context-and-group +8bdf227b Refactory: impl trans api for close upload group +18ed9311 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +3f52efd9 Impl: cancel task with user defined error +9627d57a Fix: download task progress/speed +e0292e40 Fix: download task progress/speed +addd1976 Refactory: impl trans api for close upload group +dcb4395e Refactory: impl trans api for upload group +db6750fd Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +9f10434a Fix: reserve or recycle channels when all reference released +3ffb8c7e Refactor the file task and chunk task and use a consistent impls at the lower layer +603b5377 Impl: cancel task with user defined error +e66ab510 Fix: download task progress/speed +538a7111 Rebase: rebase to 74-integrate-bdt-task-context-and-group +f720dac7 Refactory: impl trans api for close upload group +a3d86db0 Refactory: impl trans api for upload group +31a93c96 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +f2287d89 Fix query_tasks error and add some logs for task +8ed9f7f2 Sync context manager modifications with bdt +7d6ceaa8 Refactor the context state session manager with source and chunk as unique index +50fb0345 Refactor the download task to better support state switching and task release +a9fe0654 Fix the read logic error for SharedMemChunk +2f89e98d Refactory: change context update_at to async function +f9bbc140 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +4643e4d5 Refactory: add update at property for download context +da234ea1 Fix: reserve or recycle channels when all reference released +a63f74ea Router handler support empty string as filter and will treat as none +5475581f Improve the local file & chunk writers logs +3758c0a0 Refactor the file task and chunk task and use a consistent impls at the lower layer +680f18e2 Add chunk type support for verify_file_task +f237b25b Add state manager with context for ndn task to cancel task on source error +d46a8abb Refactory: add method on_drain for download context +b88929fd Impl: cancel task with user defined error +81c297f0 Sync test cases with interface modification +9ead4762 Add access support for build_dir_from_object_map source object's access +078811fa Add get_object_map_ex with access field return for object_map relate cache +2e1d1924 Add access param support for publish_file and build_file relate methods +eb62b863 Add access support to put_object_map relate methods +dd1caba5 Add some logs for task manager +2b843a47 Fix: download task progress/speed +db13d228 Improve some logs output +f00b77c2 Add from_str support for access string +7c92e607 Add alias for trans output requests +c08c3e36 Improve the log and error codes for local file relate codes +7821234f Use insert_chunk instead of update_chunk_state for chunk state updater +91f0177a Improve insert_chunk logic with update state when already exists for ndc module +ddd8f8e6 Improve some logs output for ndn relate codes +4f637a9d Refactory: interest reponse upload field tokens +1c12c499 Fix: download task finish directly when total length is zero +a43ef9db Fix: download task progress/speed +e94e9560 Fix: download task progress/speed +307c10b5 Refactory: impl trans api for close upload group +a9071c13 Refactory: impl trans api for upload group +763791ba Refactory: upload handler with group_path filter; upload handler response with upload from path +96603e3c Refactory: impl download task progress +191497e7 Fix: finish download leaf task +311aba18 Refactory: upload task group cancel/close +38d8d707 Refactory: Add logic leaf download task +f0141ccc Refactory: chunk downloader send interest with group_path field +6291029a Refactory: chunk downloader not mergable +1684b91f Fix: pannic on udp call +0cf29489 Merge branch 'main' into bdt-beta +5bd73033 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +7805227c Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +a4dbe34f Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +8611caff Fix: add log for ping clients +71af78d7 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +7a1d4b82 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +5540f89e Fix: the status of udp stream +e5307fac Fix: cc loss bytes in stream write +229dbc6a Add reset_sn_list() function in Stack's ineterface. +b469a288 Upload get-nearest SN Server in client call. The build-tunnel-params's remote-sn is priority over get-nearest sn-list. +a564d9ee Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta + +## [1.0.0.713] -- 2023/2/11 +ab8a2a6c Fix app-manager compile error +cd7eb6b4 Cyfs Monitor restore case interval time after success +7a03fdb3 Add noc test cases +bb596b85 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +20d14f19 Print warning when decapp missing status or stop scripts + +## [1.0.0.711] -- 2023/2/11 +2c798622 Fix: package enter write closed state correctly +be780df7 Stream shutdown success at closed state +21aef793 Create a directory if it does not exist when downloading to a local file +b6b7e7f8 Improve cyfs-stack's control strategy for task manager resume_task +c0f775cc Fix: fix reset key logic +c90f6ae9 Panic manager supports multiple bug reporters +07f2717d Add dingtalk_bug_report method to PanicBuilder for external use +db4acc4b Optimize some logs output +fb13f654 Add init-ood-daemon param to ood-installer +8f8e88c2 Remove cyfs-bdt's dependence on os-id lib +c05e88b7 Improve the ndn request logs output +7e0c03b0 Add req_path suport to front o protocol for acl +e3d042a0 Send start notify when cyfs-monitor started +2b3a433e Improve the problem that the front r protocol cannot correctly handle data req_path for acl +11e6ed60 Use search instead of get for device in context +06498f24 Add target device prompt info to access reject msg for better debug +7c753b20 Improve cyfs stack test cases +851f1a04 Improve some logs output about chunk cache +7cce9079 Fix: chunk list task download split chunks dumplicatedly + +## [1.0.0.709] -- 2023/2/7 +3005944e Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +0a004af9 Fix: using channel got reserved correctly +1bfe7b55 Fix: cyfs-monitor report, use sn-online-test to test sn server status +8aa6a426 impl: log udp socket's recv loop thread os id +a1d30562 Improve some logs output +4bf5e29c Add seperate sn-online-test program +82e71892 Fix: cyfs stack resp interest with NotFound if chunk not exists on default +7af6ce69 Fix: Add some log for dectecting zero speed source +d593800f Fix: modify resend piece control send time +b5c41727 Fix: channel ignore estimate request for sequence lost +21a3cb11 Correct the use of sync mechanism on bdt download context +42b7029e Bdt acl callback can correctly handle empty referer now +52709bc8 Changed to auto cancel strategy for ndn task with context param +acde7c48 Remove complie warning +6834b67a Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +4c3370f4 Remove useless ood_resolver field from ndn service relate codes + +## [1.0.0.708] -- 2023/2/6 +4e1122df Fix: the status of udp stream +58c545d7 Improve the handling of non.get_object when the target object cannot be found in (dir or objectmap) + inner_path mode +78904db7 Switch cyfs-ndc and cyfs-tracker-cache db to use SqliteConnectionHolder +932f1c61 Add SqliteConnectionHolder for general db connection management Switch cyfs-noc db to use SqliteConnectionHolder +5f1db008 impl: add a download context strategy to cancel source when zero speed +044bc59c Fix: ndn timer triggered correctly +d6bccc0f The read and write mode of Meta db is separated to support read-only in special cases such as disk is full etc + +## [1.0.0.707] -- 2023/2/3 +0ac77054 Fix the coding stability problem of Dir about HashMap +85cdd9cb Change some Mutex to cyfs-debug's checked Mutex in ood-daemon +5a448ccd Fix the deadlock bug that may be caused by service state detection +24177f29 Add test cases for config repo in ood-daemon project +8c7465ea Fix the coding stability problem of AppList and AppLocalStatus about HashMap +47d820ae Add sort by name strategy for device-config.toml +df39550f Fix the init error of trans store when the db dir is missing +bad1a48d Add inner path support for SingleOpEnvStub +cec8822c Add inner_path support for single_op_env.load method +26c68baa Fix some warning and add some comments +dc3b6e74 Update cyfs-bdt-ext deps +e977dcc9 Move LocalDeviceManager from cyfs-stack-loader to cyfs-util Remove the dependency on cyfs-stack-loader of ood-daemon and ood-installer +b09291cb Add stop_all support to stop all the services for ood-daemon +e031b4b5 Remove useless codes in cyfs-stack project +efb2431c Merge remote-tracking branch 'origin/92-more-convenient-and-suitable-to-use-cyfs-bdt' into main +170eedcf Move group and data relate codes to cyfs-bdt-ext project +259c46c4 Switched cyfs-stack to rely on cyfs-bdt-ext +965803d5 Move relate components to cyfs-bdt-ext project +00f5b35b Add cyfs-bdt-ext project +50036402 Add uptime and boot_time into get_system_info +a166c72d Fix: correctly wait dapp process +20ddf1d0 Add total trans bytes field in get_system_info Added network card deduplication in some environments +ec08c584 Publish new cargo packages +b6db6f9b Fix cyfs-util publish error +cd204231 Bump cargo packages version +cd120a75 Fix: retry sn list when offline +338c31b8 Improve ndn test case with get_data +9ee1a6d4 Improve the resp's return logic of get_data with error prompt +87b0693e Use of http requestor for get_data and put_data methods as default +6f4d47a0 Error of reading resp is returned correctly in ws mode +114c040a Merge remote-tracking branch 'origin/main' into main +a5c5da0e Sync projects for trans and stack object relate apis's changes +b51738f3 Fix a compile error with requestor config and some warnings +d7950257 Fix: trigger chunk downloader's on_drain method +95abf250 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +fd22bdec Add some logs +4a459fd3 Add serialization support for storage base on global state +068cde9a Add log for named-data-client chunk reading +cd0f3c5f Fix a compile error +ab7cf9e1 Merge branch '74-integrate-bdt-task-context-and-group' +63a37de6 Improve ood-daemon's upgrade detection and restart logic +6850633e Add host mode support to browser sanbox +d4d2639d Improve the error status of build relate tasks +7aa93795 Fix the bug that search context will enter an infinite loop +3ff1412f Improve the result of router get_object with flash flags is true +1ff3ff2e Fix the bug for decode context path param without fix +6bd563c9 Integrate surf requestor into shared stack +dc6d5ebb Remove redundant service requestors constructor +066ebd0e Add surf based requestor +066fe787 Also check app exclude list when install or start app +32b62e13 Adjust the file directory structure of requestsors in cyfs-lib +4ed6ddd2 Merge pull request #88 from buckyos/fix-container-dns +7404ab2e Merge branch 'fix-container-dns' into beta +93c35af4 Add router support for group relate methods Add target check for publish_file method +647b53ba Fix query_tasks error and add some logs for task +37c9bd9c Sync context manager modifications with bdt +78dd780c Refactor the context state session manager with source and chunk as unique index +f05bcd8b Refactor the download task to better support state switching and task release +c028b5bc Fix the read logic error for SharedMemChunk +f50bf84b Refactory: change context update_at to async function +7a2582f6 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +475de4ad Refactory: add update at property for download context +d0200673 Fix: reserve or recycle channels when all reference released +eda71af7 Ood-installer support only start ood-daemon +a491c000 Fix AppManager startup param +d2fa72e0 Fix AppManager config path, load config after log init +409c38f9 Router handler support empty string as filter and will treat as none +51d8dc8f Mixed the usage of different requestor config for zone simulator stacks +70e1e833 Add shared stack cache logic to zone simulator +37cae961 Remove shared stack support and cache from cyfs-stack-loader +eb77a092 Improve open shared stack relate logic and add requestor config params +00b8cf65 Improve the local file & chunk writers logs +e0f14387 Refactor the file task and chunk task and use a consistent impls at the lower layer +e138e06c Add chunk type support for verify_file_task +3fb583e0 Add state manager with context for ndn task to cancel task on source error +200c8922 Refactory: add method on_drain for download context +72e2bb30 Impl: cancel task with user defined error +a0413319 Sync test cases with interface modification +473334df Add access support for build_dir_from_object_map source object's access +973718a1 Add get_object_map_ex with access field return for object_map relate cache +4a547ca3 Add access param support for publish_file and build_file relate methods +78d8f93e Add access support to put_object_map relate methods +750e65d5 Add some logs for task manager +58d90843 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b398e932 Fix: download task finish directly when total length is zero +2b415e37 Fix: download task progress/speed +54965e6c Improve some logs output +f62cb4df Refactory: impl download task progress +bbec1935 Fix: finish download leaf task +fd230411 Refactory: upload task group cancel/close +4c2f95b4 Refactory: Add logic leaf download task +eab160ec Refactory: chunk downloader send interest with group_path field +50db1d5c Refactory: chunk downloader not mergable +062bf19e Add from_str support for access string +2243fa7b Add alias for trans output requests +ebb67790 Improve the log and error codes for local file relate codes +ff7dd4c1 Use insert_chunk instead of update_chunk_state for chunk state updater +0525944c Improve insert_chunk logic with update state when already exists for ndc module +fc2d8b18 Improve some logs output for ndn relate codes +128a7cc5 Fix: some warning with while let +f1890ba3 Add chunk exists check for ndn get_data cache mechanism +18c94cf2 Improve some error process in std::io poll relate methods +06f03a6a Improve the conversion between BuckyError and std::io::Error +e801b468 Improve put_chunk for local chunk cache +23a61570 Add cache mechanism to ndn get_data +9055ec35 Refactory: add group_path field to interest packet +1093046b Add range support for ndn get_data with chunk +e3797e31 Add group test case +5061b962 Refactory: poll split read +e700a047 Use {dec_id}/ as default group when no group param is specified +14339d1a Remove dec_id field of context object Add global context support for context +6922dfa0 Put_context is adjusted to depend on context manager Add access field for put_context request +968e5e6d Fix context path fix error & add test case +b70f7990 Fix error when context manager parse context string with object_id +de18c885 Add ndn context test cases Fix compile errors of trans relate methods +8687e171 Fix ndn referer param encode error +be8f06b3 Add debug output for changed of context +abcc02d8 Remove context_id field for query tasks request +21421faf Fix: build error for cyfs-stack +4f62dbad Fix: build error for cyfs-stack +6d6ccad3 Improve resp process for trans & sync api methods +3eb6ca28 Refactor put_context and get_context methods for trans +5ad7e7f1 Improve the clone_from_slice method for ObjectId +9ece347b Refactor context support for trans +7340db07 Refactor ndn api target related codes to support context +458ad1f6 Refactor context to support target mode +9ea97744 Add context field for ndn get_data request +4a0aa1b6 Adapt to bdt new context relate params and types +b51eed19 Add cache and path search category to context manager +f0427489 Add dec_id field for context object, and add strict limit to context_path field +3441fdb0 Refactory: rename ChunkEncodeDesc => ChunkCodecDesc; declare context.source_of as async function; +04db0d46 Add context holder generator for context manager +6081a426 Add context manager and holder core impls +23eb4af0 Refactor the TransContext core object +73d7dcb1 Add dec limit for trans task group relate methods +abda8cfc Improve the param of TransOutputProcessor methods +a3678c4e Improve the trans.query_tasks request path +0fb35dbb Add task group relate methods for trans api +c78b3568 Add a common impl of serde code for JsonCodec +70366e60 Refactor get_task_state method's response to add group support +2d335eff Add group field for DownloadTaskState +ba606857 Add task group for ndn get_data resp +bbb16276 Improve the url query parse for referer and group params +5fae309c Add task group support for NDN/Trans modules +71414249 Rename the task range reader +a5107424 Optimize the ChunkWriter write method +b5ba81fb DirLoader switch to reply on chunk_store_reader instead of local_data_manager +89df6fcc NDN local_data_manager's get relate impls switch to reply on target_data_manager instead +bdfabe75 Fix: split read test +12610350 Fix: cyfs stack ndn event apply to new bdt ndn interface +816e7f6b Refactor the param model of ndc/tracker/chunk_manager +a397bd52 Adapt to bdt's new download stream model +2d5eb444 Impl: split read for download task reader +6cd9410e Impl: Add Single source context +95c8554a Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +5a1f23af Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +6111f439 Fix: Release chunk cache and downloader with weak reference +ffc56abe Refactory:create seperate downloader when context is not mergable +1ff8388e Refactory: add loading state to chunk cache +8e3590a2 Refactory: split chunk downloader from chunk cache +f2a3672f Fix: call cc on_loss with error loss count value +1dd8bae3 Fix: Donwload task path logic +4f3a92c4 Fix: return download task speed +371792c0 Fix: use BuckyError instead of BuckyErrorCode in some state +167664c9 Fix: add chunk_list_writer method to TrackedChunkStore +b4a67578 Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta +2e42dae0 Fix: stream chunk encoder always read cache with sync reader +bb954d5f Impl: Unit test for upload from path +8b7aa861 Refactory: Add start_upload_from_cache method +81014478 Refactory: Move ndn default event handler to utils +def00192 Refactory: remove default ndc/tracker from bdt stack +67f29271 Refactory: Taskgroup makesure path +896b39ba Impl: File raw cache for chunk +bc043adc In SN statistic, add endpoint's statistic. +ecb58708 Call sn support MTU_LARGE +2cf4567b Add Mutlity SN。 +2321e02c Fix: tcp tunnel send piece buffer with mtu +2ac27f33 Refactory: add DownloadContext trait +6832e73e Refactory: add DownloadContext trait +330a8940 Support large mtu and question&answer +e03962a7 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +d1cc885e Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +06d89662 Fix: chunk list task reader +f4d20813 Fix: close/finish download task group +5bd2ec64 Fix: task.reader return unexpected not found error +7d2e6f6f Fix:panic on download reader +de837c47 Refactory: write chunk from task.reader +677e444b Refactory: Reader of download task +c0a479e3 Refactory: Upload session wait establish +22e9cc0f Refactory: download/upload differs in tcp/udp tunnel +638a8fc4 Refactory: download/upload differs in tcp/udp tunnel +23251581 Fix: bind tunnel with upload/download session +70292ce4 Fix: cache packages in tunnel.build_send, send them when tunnel actived +197e241a Merge branch 'ndn-cache' into bdt-beta +51d5b714 Merge branch 'ndn-cache' into bdt-beta +ea1dae46 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +16d25537 Merge branch 'ndn-cache' into bdt-beta +c6bf684a log decrypt aeskey error info +79bceeea Fix: chunk list task reader +bc380433 Fix: close/finish download task group +61714a7b Fix: task.reader return unexpected not found error +97c955d7 Fix:panic on download reader +1e95e4da Refactory: write chunk from task.reader +9ad964fb Refactory: Reader of download task +d8bf33a0 Refactory: Upload session wait establish +06f3affc Refactory: download/upload differs in tcp/udp tunnel +2ef44f99 Refactory: download/upload differs in tcp/udp tunnel +8519534c Fix: bind tunnel with upload/download session +b2925e95 Fix: cache packages in tunnel.build_send, send them when tunnel actived +7235f3dc Merge branch 'ndn-cache' into bdt-beta +04e2a5a0 Merge branch 'ndn-cache' into bdt-beta +eaa0b650 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +3d711110 Merge branch 'ndn-cache' into bdt-beta +8c8b6039 log decrypt aeskey error info +43ccf15c Impl: Cancel download chunk task +6efb6eca Test: download from uploader test ok +439635f5 Merge branch 'ndn-cache' into bdt-beta +0e08b03a Refactory: download/upload session support reverse step stream +96ffaef7 Refactory: impl download/upload session with new cache +292cf4ae Refactory: impl download/upload session with new cache +d38e31ba Refactory: impl download/upload session with new cache +07b40c65 Refactory: impl download/upload session with new cache +d525a649 Refactory: implement memory raw cache +e07a4b0e Refactory: chunk downloader with stream cache + +## [1.0.0.703] -- 2023/1/13 +cfd654ac Temporarily disable all ipv6 addresses for bdt stack + +## [1.0.0.702] -- 2023/1/12 +bb72348e App Manager AppSource logic +413edbad AppManager supports more detailed configuration +7b0704ec WIP: add new config for app manager +2eb6dce1 Modify the way to start file uploader +6076a69f Improve the update state relate logic for service in ood-daemon service +44fbe781 Fix: avoid duplicate hole punching process when retry sn call +ea48e120 Merge remote-tracking branch 'origin/fix-container-dns' +56f22e21 Add --startup-mode for ood-daemon startup script +cf1f363c Add startup-mode to ood-daemon service with network verify on system startup +56b755e6 Add active check in daemon update and state check loop +b7943988 Fix compile +2b355960 Fix container dns, when resolv contain 127.0.0.53 +d6b5bb06 Add timeout for repo in ood-daemon service +628649f0 Start the monitor service synchronously on startup +de1e9960 Add service_list cache mechanism for meta config repo +a84bfafe Remove the local status of meta config repo in ood-daemon service +a807f171 Fix: retry sn list when builder not establish in time +5639e004 App-tool and app-tool-ex return error correctly +26b234cb Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f136c262 Fix some compile errors and warnings +a4ece723 Remove the useless base project +2d216910 Add app-manager.toml config file support to ood-installer tool +e111f3b2 Remove the useless old configuration of acl.toml +eae9d604 Merge branch 'main' into beta +d5463188 Merge branch 'main' into beta +b34744c3 Merge branch 'main' into beta +180ae196 Remove handler and event manager's none mode +d10953b2 Improve ws session and manager stop-related timing logic +8b84ef3f Add delayed start mechanism for router handler and events +c13cc029 Add shared stack stop test case +faf04a09 Improve ws and event manager stop strategy +c5d02ab9 Improve ws session and ws client stop strategy +007247e2 Refactor ws session related logic and improve packet parser logic +b0463c83 Add stop method to shared stack with requestors +1b80f43a Enable none mode for handler and event system in shared stack +8ec0888b Optimize the use of requestor by the service component and adopt the shared mode +d9d69051 Remove http handler support for shared stack +bb0e005e Add stop method to handler and event manager +1a2ada09 Add stop method for ws client +77ea26c6 Fix: cyfs-client correct get sn list from local stack +e29cd15c Merge branch 'main' into beta +0bb5dcd7 Sync service list method use the lock for services in ood-daemon +19b338e6 Improve some logs output +7e8cb267 Improve cmd status check return value and compare mechanism +fc800657 Improve the agent check for the browser disable mode +67a2179e NamedDataClient use init config, use GetData instead of GetDataWithMeta +e160a62a Improve the get_data logic of chunk_manager +9f7263bc Add memory cache for chunk_manager get_data_with_meta Improve the get_chunk_data resp body mechanism and remove the chunk_id verify temporarily +270778a9 Fix: stream pool use sn list in device cache +b1abf319 Fix: ignore sn list in build param's remote desc +ff05f5ff Fix: beta use correct built-in sn list +02fe10ef Fix: Add logs for build params info +26989db3 Merge branch 'main' into beta +440b90f9 Merge branch 'main' into beta +c377c61f Merge branch 'main' into beta +b0fe871d Merge branch 'main' into beta +ef8a124a Merge branch 'main' into beta +71e9e52b Merge branch 'main' into beta +2fa6be68 Fix: disable cyfs_debug::mutex check in some fraquently called functions From f022818a79a3bdc64c066ee28a61b0e54259f8b3 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 19:51:53 +0800 Subject: [PATCH 141/553] Fix changelog markdown format --- CHANGELOG-nightly.md | 1486 +++++++++++++++++++++--------------------- 1 file changed, 743 insertions(+), 743 deletions(-) diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md index 0c79dfc4b..527382d38 100644 --- a/CHANGELOG-nightly.md +++ b/CHANGELOG-nightly.md @@ -1,743 +1,743 @@ -## [1.0.0.718] -- 2023/2/21 -1b0cf118 Change sync services packages from parallel to serial -638848a2 Remove two spawn task using for cancel on timeout -70837da7 Fix error op_env type check in requestor -e3f55f6e Improve timeout and retry strategy for repo download in ood-daemon service -9c3c63ab Meta db initialization switch to transaction mode -1e4e4277 Modify: add some statistic logs for ndn -94d8f7a4 Merge branch '104-appmanager-suppport-local-app-repo-store' -34580770 Modify: add some statistic logs for ndn -7522c0fe Email Sender support starttls -10d27023 App Manager support install app from local repo -2a3c1dc1 ood-installer support sync app repo -51f0be28 WIP: App Manager Support Local Repo -e6392f5b WIP: App Manager reflator app install logic -e65fe061 WIP: AppManager add repo type, use zip_extract to extract app service package - -## [1.0.0.715] -- 2023/2/20 -e51af4f2 Set docker api timeout to 300s -b213c3fe Fix: tcp not update active time when recv packet -24553a9c Improve the object layer strategy detection of after pass the first layer rpath access verification -574cfddf OOD-daemon will now report an error and exit if it fails to load the repo -0ab51327 Add version output in process alive check log -14c004b6 Fix meta-stat email format -4daab080 App-manager report app status to ood-daemon -c09ddea9 Fix field names of ood status -f3449363 Fix: monitor create desc when desc not existed on chain -a4e0e755 Fix: stream break when loss fin ack packet -0d2393f3 Fix: monitor create desc error -ba302dd4 Merge remote-tracking branch 'origin/107-support-multiple-global-states-in-cyfs-stack' into main -3d70797d Add group state test case -63e3e712 Fix a assert error when global state is init -61a5eff1 Cyfs monitor use generated identify to test metachain read and write -3d4aefc9 Improve the use of u64::MAX in two places -ee5323ea Delete some useless logs -90d9b5c8 meta spv support storage anbd query objects by object id, body hash -1101829c Add isolate_id method for GlobalStateRawProcessor -e3765b61 Add global state raw processor for use by external components of cyfs-stack -ff03c824 Add the persistence mechanism of all the global state list -b4c4de04 Refactor GlobalStateManager to support multiple global-states -937c7dbe Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' -b4284830 Add exists methods into collection for to check if exists -5bcc2984 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' -da09ed21 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' -412d03ff Merge branch '99-recycle-unused-bdt-tunnel-instances' -979773da Fix: implement stream reserving 2*msl state with lru cache -25c53b07 Refactory: export private methods with pub(crate) -114f1d1b Fix: bdt unit test sn with ipv6 endpoints -fdde1948 Merge branch '95-ipv6-support-refactory' -1b91764a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -8d522ec7 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -1875de3d Add object and name for meta in cyfs-stack -3e12b1be Fix cyfs-perf deps Improve the format of some tomls -e83890fc Add noc meta cache to optimize update last access write operation -2ff85f4d Publish cyfs-core new version -d917d648 Bump cyfs-core version -0dd49104 Fix cyfs-core deps -220c7ab2 Fix compile error -dd2f2f17 Publish new cargo packages -fb63c476 Bump cargo package version and dependences -89917227 Merge branch 'main' into beta -75aea584 Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -8f60a00b Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -2ebd1e20 Add object and name for meta in cyfs-stack -4d5a9e90 Fix cyfs-perf deps Improve the format of some tomls -2121a11e Add noc meta cache to optimize update last access write operation -078b27d3 Publish cyfs-core new version -019b09d9 Bump cyfs-core version -51e4365b Fix cyfs-core deps -a04d6e88 Fix compile error -038b75b4 Publish new cargo packages -279ce4bd Bump cargo package version and dependences -026c1383 Merge branch 'main' into beta -ccb044db Integrate ood-daemon services status -4af47a92 Improve ServiceState fields spelling -f9eaed01 Add service status related def -ec1ba569 ood-daemon adds independent status http server -5bc02595 Add service status support to ood-daemon -ff14b0d1 Add external http server support to ood control -287c9468 Fix app-manager compile error -08249fa5 Cyfs Monitor restore case interval time after success -c6c372dc Add noc test cases -b176d6a5 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -97bd7bb9 Print warning when decapp missing status or stop scripts -9f85c599 Stream shutdown success at closed state -71ffede0 Fix: fix reset key logic -ec2194ec Integrate ood-daemon services status -2b30769b Improve ServiceState fields spelling -eb881d46 Add service status related def -5dc9c661 ood-daemon adds independent status http server -b2882ff5 Add service status support to ood-daemon -cfc87989 Add external http server support to ood control -d54866c2 Fix app-manager compile error -f0822e79 Cyfs Monitor restore case interval time after success -ab37ea21 Add noc test cases -fa1cc5c0 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -13cdfe46 Print warning when decapp missing status or stop scripts -5ad5d183 Fix: bdt unit test sn with ipv6 endpoints -9607470d Merge branch '95-ipv6-support-refactory' -a8ba267a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -5c2a8d77 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -c88a5e76 Add object and name for meta in cyfs-stack -598df4a8 Fix cyfs-perf deps Improve the format of some tomls -1952c7ee Add noc meta cache to optimize update last access write operation -ba181cef Publish cyfs-core new version -139a9ab6 Bump cyfs-core version -11c7205a Fix cyfs-core deps -76f871ea Fix compile error -30f99d3d Publish new cargo packages -4228e263 Bump cargo package version and dependences -34cb38f4 Merge branch 'main' into beta -87956987 Integrate ood-daemon services status -086dcd8a Improve ServiceState fields spelling -51f135c6 Add service status related def -0bd37768 ood-daemon adds independent status http server -933ed8cd Add isolate_path_env stub test cases -1be055d0 Add service status support to ood-daemon -d3e16c4d Add native ioslate_path_env component test cases and fix some test warnings -25fa3e85 Add external http server support to ood control -60b04789 Add ioslate path env stub -4b32f2b0 Optimize objectmap path to support non-transactional mode -5a6aa9b7 Integrate isolate path env into global-state services -6ccd4ef9 Add isolate path env impl -c78ae028 Fix app-manager compile error -429bddd8 Cyfs Monitor restore case interval time after success -9dd5aac3 Add noc test cases -c7132f26 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -cbf80ee3 Print warning when decapp missing status or stop scripts -2451a583 Fix: package enter write closed state correctly -0d4443ff Panic manager supports multiple bug reporters -f6749bb1 Stream shutdown success at closed state -f1a4cc60 Create a directory if it does not exist when downloading to a local file -28a37154 Improve cyfs-stack's control strategy for task manager resume_task -a63d6854 Fix: fix reset key logic -b7a3e3c9 Add dingtalk_bug_report method to PanicBuilder for external use -445fc501 Optimize some logs output -cc70a84b Add init-ood-daemon param to ood-installer -28fbed65 Remove cyfs-bdt's dependence on os-id lib -18d1534d Improve the ndn request logs output -8538be10 Add req_path suport to front o protocol for acl -1a621713 Send start notify when cyfs-monitor started -e8752b2a Improve the problem that the front r protocol cannot correctly handle data req_path for acl -4abdcf6b Use search instead of get for device in context -c8ad90a8 Add target device prompt info to access reject msg for better debug -4cc08abb Improve cyfs stack test cases -9cf2aafe Improve some logs output about chunk cache -b30d8cd6 Fix: chunk list task download split chunks dumplicatedly -c2570da0 Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system -b7ecdbc7 Fix: using channel got reserved correctly -a8a9a3b9 Fix: cyfs-monitor report, use sn-online-test to test sn server status -c3964a38 impl: log udp socket's recv loop thread os id -cb239140 Improve some logs output -67b2aed5 Add seperate sn-online-test program -b6e22b0f Fix: cyfs stack resp interest with NotFound if chunk not exists on default -e1bbe10d Fix: Add some log for dectecting zero speed source -d3535025 Fix: modify resend piece control send time -04629f0f Fix: channel ignore estimate request for sequence lost -11bfb5a5 Correct the use of sync mechanism on bdt download context -d2d9ff8f Bdt acl callback can correctly handle empty referer now -a2ebb0df Changed to auto cancel strategy for ndn task with context param -d653c967 Fix the bug that the device_list param of trans.create_task cannot correctly find the device object -a2cb418a Remove useless ood_resolver field from ndn service relate codes -236abdbb Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -cb0cba8a Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -dce764a9 Add object and name for meta in cyfs-stack -e0dac397 Fix: tcp stream don't reset tunnel when break -5af0b5fb Fix: implement stream reserving 2*msl state with lru cache -3da42793 Fix cyfs-perf deps Improve the format of some tomls -9867ad29 Add noc meta cache to optimize update last access write operation -e11ff3ef Publish cyfs-core new version -95a5c99d Bump cyfs-core version -c168c17a Fix cyfs-core deps -427050c6 Fix compile error -2412d747 Integrate ood-daemon services status -aa5ff976 Publish new cargo packages -0249ba77 Bump cargo package version and dependences -96e3bb69 Merge branch 'main' into beta -0493c935 Improve ServiceState fields spelling -5a88c564 Add service status related def -00bf2764 ood-daemon adds independent status http server -c013612e Fix: bdt mem device cache limited size -39de9529 Refactory: export private methods with pub(crate) -7785029d Fix: package enter write closed state correctly -101db063 Stream shutdown success at closed state -3fca43d8 Create a directory if it does not exist when downloading to a local file -ac0e4f2a Improve cyfs-stack's control strategy for task manager resume_task -4d8bfacc Fix: fix reset key logic -96e1c1e6 Panic manager supports multiple bug reporters -8d9b7929 Add dingtalk_bug_report method to PanicBuilder for external use -7825a4ea Optimize some logs output -fa6867c6 Add init-ood-daemon param to ood-installer -9aa4489c Remove cyfs-bdt's dependence on os-id lib -66b856fc Improve the ndn request logs output -c0622388 Add req_path suport to front o protocol for acl -cc24f8e0 Send start notify when cyfs-monitor started -10ace371 Improve the problem that the front r protocol cannot correctly handle data req_path for acl -6c59337d Use search instead of get for device in context -ef0f880d Add target device prompt info to access reject msg for better debug -beb0e7be Add service status support to ood-daemon -edc1d1f6 Add external http server support to ood control -e5e9a3a5 Refactory: stream release tunnel guard when closed -009c3c8a Refactory: export private methods with pub(crate) -8e21764a Refactory: export private methods with pub(crate) -743c2fcf Impl: recycle unused tunnel -b4eb9f85 Add isolate_path_env stub test cases -b0c6fd63 Add native ioslate_path_env component test cases and fix some test warnings -3f14f978 Impl: add a test for sn ipv6 ping -ff916188 Add ioslate path env stub -dd437a1f Impl: sn support ipv6 ping -b69709df Optimize objectmap path to support non-transactional mode -0de3fc0c Integrate isolate path env into global-state services -edacc65a Add isolate path env impl -29fed496 Remove complie warning -f3f66501 Impl: Add transfered and recursion close method to ndn task -027e9ae4 Impl: Add transfered and recursion close method to ndn task -6a1f7ed1 Rebase: rebase to 74-integrate-bdt-task-context-and-group -aa682520 Refactory: impl trans api for close upload group -260cbdf8 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -c2bd5612 Refactory: impl trans api for close upload group -99bbebfc Refactory: impl trans api for upload group -c19064b5 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -2f47bcc0 Fix: reserve or recycle channels when all reference released -ae3f02eb Impl: cancel task with user defined error -82692c64 Fix: download task progress/speed -bc3ba88e Rebase: rebase to 74-integrate-bdt-task-context-and-group -58d6d195 Refactory: impl trans api for close upload group -5dad1539 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -30aa07ae Fix: reserve or recycle channels when all reference released -acaa42fb Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -09076f70 Add uptime and boot_time into get_system_info -2b81e62a Fix: correctly wait dapp process -3bbbcfc3 Add total trans bytes field in get_system_info Added network card deduplication in some environments -80fa0863 Publish new cargo packages -ae40d694 Fix cyfs-util publish error -ee957a29 Bump cargo packages version -89341b52 Fix: retry sn list when offline -1370e83c Improve ndn test case with get_data -3584395e Improve the resp's return logic of get_data with error prompt -a3a5172e Use of http requestor for get_data and put_data methods as default -0347e50e Error of reading resp is returned correctly in ws mode -87d26ad6 Merge remote-tracking branch 'origin/main' into main -0df70f89 Sync projects for trans and stack object relate apis's changes -2ef0d178 Fix a compile error with requestor config and some warnings -4b716f44 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main -1a15a767 Fix: trigger chunk downloader's on_drain method -e9faea63 Add some logs -a8dedd60 Add serialization support for storage base on global state -6effd696 Add log for named-data-client chunk reading -9edf7c31 Merge branch '74-integrate-bdt-task-context-and-group' -3fcdbf0c Improve ood-daemon's upgrade detection and restart logic -e0323ea1 Add host mode support to browser sanbox -91e519ec Also check app exclude list when install or start app -66acc69e Merge pull request #88 from buckyos/fix-container-dns -f1a63712 Ood-installer support only start ood-daemon -6514acec Fix AppManager startup param -ee80ce8c Fix AppManager config path, load config after log init -cb2ac1ee Mixed the usage of different requestor config for zone simulator stacks -be10f64b Add shared stack cache logic to zone simulator -5da765af Remove shared stack support and cache from cyfs-stack-loader -c2708f59 Improve open shared stack relate logic and add requestor config params -6150617a Temporarily disable all ipv6 addresses for bdt stack -95654ae5 App Manager AppSource logic -e849439c AppManager supports more detailed configuration -715e851e WIP: add new config for app manager -2ded38db Modify the way to start file uploader -0a50ed5f Improve the update state relate logic for service in ood-daemon service -c7de6539 Fix: avoid duplicate hole punching process when retry sn call -e828e7b5 Merge remote-tracking branch 'origin/fix-container-dns' -f8f4381b Add --startup-mode for ood-daemon startup script -c7bf12f2 Add startup-mode to ood-daemon service with network verify on system startup -b9aca01d Add active check in daemon update and state check loop -dc6aa3d9 Add timeout for repo in ood-daemon service -20ec54d1 Start the monitor service synchronously on startup -2e66ff4a Add service_list cache mechanism for meta config repo -d758151b Remove the local status of meta config repo in ood-daemon service -f99caadc Fix: retry sn list when builder not establish in time -b143379f Integrate surf requestor into shared stack -7eed812f App-tool and app-tool-ex return error correctly -09f79e9a Remove redundant service requestors constructor -cd8588de Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main -f5873108 Add surf based requestor -889d7f81 Adjust the file directory structure of requestsors in cyfs-lib -e7e9781e Fix some compile errors and warnings -3aa50d32 Remove the useless base project -4de7e33d Add app-manager.toml config file support to ood-installer tool -9317c01d Remove the useless old configuration of acl.toml -5af28985 Improve the error status of build relate tasks -a762fecf Merge branch 'fix-container-dns' into beta -b3231559 Fix compile -832e7a20 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead -b2471088 Fix container dns, when resolv contain 127.0.0.53 -bde55b1a Merge branch 'main' into beta -4dd330fe Merge branch 'main' into beta -35cabb3f Merge branch 'main' into beta -bd9326c9 File upload tool only support windows & mac for now. -01a46434 Open upload tool with "open" cmd on Mac -b45d377f Fix:ping client doesn't update local device -b36e728e Fix:ping client doesn't update local device -d9bd6698 Remove handler and event manager's none mode -980b5392 Add some field compatibility with the old version's data on new db format -6541571a Fix: pannic on time escape of call session -c0ceda78 Improve ws session and manager stop-related timing logic -f30cc9c8 Fix: some warning with while let -473e56d6 Add delayed start mechanism for router handler and events -74e30500 Fix: downloading speed/progress for chunk_list/file task use percent -172c5c9e Add shared stack stop test case -d670b458 Improve ws and event manager stop strategy -5841a4fb Improve ws session and ws client stop strategy -b62c204a Refactor ws session related logic and improve packet parser logic -706f06e6 Add stop method to shared stack with requestors -b45ddcf1 Enable none mode for handler and event system in shared stack -a1d67489 Optimize the use of requestor by the service component and adopt the shared mode -6acc40fa Remove http handler support for shared stack -5c3abc42 Add stop method to handler and event manager -b24935d7 Add stop method for ws client -6f55517f Publish new cargo packages -8c933ffc Fix cyfs-util publish error -bf75d29e Bump cargo packages version -bce2a745 Merge branch 'main' into beta -acbd636a Refactory: Add track chunk method option to publish dir/file methods -a022c2cc Fix the bug that search context will enter an infinite loop -a8a57c27 Improve the result of router get_object with flash flags is true -9f3d4e8d Fix the bug for decode context path param without fix -4236102e Add router support for group relate methods Add target check for publish_file method -3d758fcd Merge branch 'main' into beta -0843bbba Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead (#87) -387362a2 Rebase: rebase to 74-integrate-bdt-task-context-and-group -8bdf227b Refactory: impl trans api for close upload group -18ed9311 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -3f52efd9 Impl: cancel task with user defined error -9627d57a Fix: download task progress/speed -e0292e40 Fix: download task progress/speed -addd1976 Refactory: impl trans api for close upload group -dcb4395e Refactory: impl trans api for upload group -db6750fd Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -9f10434a Fix: reserve or recycle channels when all reference released -3ffb8c7e Refactor the file task and chunk task and use a consistent impls at the lower layer -603b5377 Impl: cancel task with user defined error -e66ab510 Fix: download task progress/speed -538a7111 Rebase: rebase to 74-integrate-bdt-task-context-and-group -f720dac7 Refactory: impl trans api for close upload group -a3d86db0 Refactory: impl trans api for upload group -31a93c96 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -f2287d89 Fix query_tasks error and add some logs for task -8ed9f7f2 Sync context manager modifications with bdt -7d6ceaa8 Refactor the context state session manager with source and chunk as unique index -50fb0345 Refactor the download task to better support state switching and task release -a9fe0654 Fix the read logic error for SharedMemChunk -2f89e98d Refactory: change context update_at to async function -f9bbc140 Refactory: chunk downloader triggers context's on_drain when all existing sources tried -4643e4d5 Refactory: add update at property for download context -da234ea1 Fix: reserve or recycle channels when all reference released -a63f74ea Router handler support empty string as filter and will treat as none -5475581f Improve the local file & chunk writers logs -3758c0a0 Refactor the file task and chunk task and use a consistent impls at the lower layer -680f18e2 Add chunk type support for verify_file_task -f237b25b Add state manager with context for ndn task to cancel task on source error -d46a8abb Refactory: add method on_drain for download context -b88929fd Impl: cancel task with user defined error -81c297f0 Sync test cases with interface modification -9ead4762 Add access support for build_dir_from_object_map source object's access -078811fa Add get_object_map_ex with access field return for object_map relate cache -2e1d1924 Add access param support for publish_file and build_file relate methods -eb62b863 Add access support to put_object_map relate methods -dd1caba5 Add some logs for task manager -2b843a47 Fix: download task progress/speed -db13d228 Improve some logs output -f00b77c2 Add from_str support for access string -7c92e607 Add alias for trans output requests -c08c3e36 Improve the log and error codes for local file relate codes -7821234f Use insert_chunk instead of update_chunk_state for chunk state updater -91f0177a Improve insert_chunk logic with update state when already exists for ndc module -ddd8f8e6 Improve some logs output for ndn relate codes -4f637a9d Refactory: interest reponse upload field tokens -1c12c499 Fix: download task finish directly when total length is zero -a43ef9db Fix: download task progress/speed -e94e9560 Fix: download task progress/speed -307c10b5 Refactory: impl trans api for close upload group -a9071c13 Refactory: impl trans api for upload group -763791ba Refactory: upload handler with group_path filter; upload handler response with upload from path -96603e3c Refactory: impl download task progress -191497e7 Fix: finish download leaf task -311aba18 Refactory: upload task group cancel/close -38d8d707 Refactory: Add logic leaf download task -f0141ccc Refactory: chunk downloader send interest with group_path field -6291029a Refactory: chunk downloader not mergable -1684b91f Fix: pannic on udp call -0cf29489 Merge branch 'main' into bdt-beta -5bd73033 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -7805227c Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -a4dbe34f Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta -8611caff Fix: add log for ping clients -71af78d7 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta -7a1d4b82 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta -5540f89e Fix: the status of udp stream -e5307fac Fix: cc loss bytes in stream write -229dbc6a Add reset_sn_list() function in Stack's ineterface. -b469a288 Upload get-nearest SN Server in client call. The build-tunnel-params's remote-sn is priority over get-nearest sn-list. -a564d9ee Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta - -## [1.0.0.713] -- 2023/2/11 -ab8a2a6c Fix app-manager compile error -cd7eb6b4 Cyfs Monitor restore case interval time after success -7a03fdb3 Add noc test cases -bb596b85 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -20d14f19 Print warning when decapp missing status or stop scripts - -## [1.0.0.711] -- 2023/2/11 -2c798622 Fix: package enter write closed state correctly -be780df7 Stream shutdown success at closed state -21aef793 Create a directory if it does not exist when downloading to a local file -b6b7e7f8 Improve cyfs-stack's control strategy for task manager resume_task -c0f775cc Fix: fix reset key logic -c90f6ae9 Panic manager supports multiple bug reporters -07f2717d Add dingtalk_bug_report method to PanicBuilder for external use -db4acc4b Optimize some logs output -fb13f654 Add init-ood-daemon param to ood-installer -8f8e88c2 Remove cyfs-bdt's dependence on os-id lib -c05e88b7 Improve the ndn request logs output -7e0c03b0 Add req_path suport to front o protocol for acl -e3d042a0 Send start notify when cyfs-monitor started -2b3a433e Improve the problem that the front r protocol cannot correctly handle data req_path for acl -11e6ed60 Use search instead of get for device in context -06498f24 Add target device prompt info to access reject msg for better debug -7c753b20 Improve cyfs stack test cases -851f1a04 Improve some logs output about chunk cache -7cce9079 Fix: chunk list task download split chunks dumplicatedly - -## [1.0.0.709] -- 2023/2/7 -3005944e Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system -0a004af9 Fix: using channel got reserved correctly -1bfe7b55 Fix: cyfs-monitor report, use sn-online-test to test sn server status -8aa6a426 impl: log udp socket's recv loop thread os id -a1d30562 Improve some logs output -4bf5e29c Add seperate sn-online-test program -82e71892 Fix: cyfs stack resp interest with NotFound if chunk not exists on default -7af6ce69 Fix: Add some log for dectecting zero speed source -d593800f Fix: modify resend piece control send time -b5c41727 Fix: channel ignore estimate request for sequence lost -21a3cb11 Correct the use of sync mechanism on bdt download context -42b7029e Bdt acl callback can correctly handle empty referer now -52709bc8 Changed to auto cancel strategy for ndn task with context param -acde7c48 Remove complie warning -6834b67a Fix the bug that the device_list param of trans.create_task cannot correctly find the device object -4c3370f4 Remove useless ood_resolver field from ndn service relate codes - -## [1.0.0.708] -- 2023/2/6 -4e1122df Fix: the status of udp stream -58c545d7 Improve the handling of non.get_object when the target object cannot be found in (dir or objectmap) + inner_path mode -78904db7 Switch cyfs-ndc and cyfs-tracker-cache db to use SqliteConnectionHolder -932f1c61 Add SqliteConnectionHolder for general db connection management Switch cyfs-noc db to use SqliteConnectionHolder -5f1db008 impl: add a download context strategy to cancel source when zero speed -044bc59c Fix: ndn timer triggered correctly -d6bccc0f The read and write mode of Meta db is separated to support read-only in special cases such as disk is full etc - -## [1.0.0.707] -- 2023/2/3 -0ac77054 Fix the coding stability problem of Dir about HashMap -85cdd9cb Change some Mutex to cyfs-debug's checked Mutex in ood-daemon -5a448ccd Fix the deadlock bug that may be caused by service state detection -24177f29 Add test cases for config repo in ood-daemon project -8c7465ea Fix the coding stability problem of AppList and AppLocalStatus about HashMap -47d820ae Add sort by name strategy for device-config.toml -df39550f Fix the init error of trans store when the db dir is missing -bad1a48d Add inner path support for SingleOpEnvStub -cec8822c Add inner_path support for single_op_env.load method -26c68baa Fix some warning and add some comments -dc3b6e74 Update cyfs-bdt-ext deps -e977dcc9 Move LocalDeviceManager from cyfs-stack-loader to cyfs-util Remove the dependency on cyfs-stack-loader of ood-daemon and ood-installer -b09291cb Add stop_all support to stop all the services for ood-daemon -e031b4b5 Remove useless codes in cyfs-stack project -efb2431c Merge remote-tracking branch 'origin/92-more-convenient-and-suitable-to-use-cyfs-bdt' into main -170eedcf Move group and data relate codes to cyfs-bdt-ext project -259c46c4 Switched cyfs-stack to rely on cyfs-bdt-ext -965803d5 Move relate components to cyfs-bdt-ext project -00f5b35b Add cyfs-bdt-ext project -50036402 Add uptime and boot_time into get_system_info -a166c72d Fix: correctly wait dapp process -20ddf1d0 Add total trans bytes field in get_system_info Added network card deduplication in some environments -ec08c584 Publish new cargo packages -b6db6f9b Fix cyfs-util publish error -cd204231 Bump cargo packages version -cd120a75 Fix: retry sn list when offline -338c31b8 Improve ndn test case with get_data -9ee1a6d4 Improve the resp's return logic of get_data with error prompt -87b0693e Use of http requestor for get_data and put_data methods as default -6f4d47a0 Error of reading resp is returned correctly in ws mode -114c040a Merge remote-tracking branch 'origin/main' into main -a5c5da0e Sync projects for trans and stack object relate apis's changes -b51738f3 Fix a compile error with requestor config and some warnings -d7950257 Fix: trigger chunk downloader's on_drain method -95abf250 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main -fd22bdec Add some logs -4a459fd3 Add serialization support for storage base on global state -068cde9a Add log for named-data-client chunk reading -cd0f3c5f Fix a compile error -ab7cf9e1 Merge branch '74-integrate-bdt-task-context-and-group' -63a37de6 Improve ood-daemon's upgrade detection and restart logic -6850633e Add host mode support to browser sanbox -d4d2639d Improve the error status of build relate tasks -7aa93795 Fix the bug that search context will enter an infinite loop -3ff1412f Improve the result of router get_object with flash flags is true -1ff3ff2e Fix the bug for decode context path param without fix -6bd563c9 Integrate surf requestor into shared stack -dc6d5ebb Remove redundant service requestors constructor -066ebd0e Add surf based requestor -066fe787 Also check app exclude list when install or start app -32b62e13 Adjust the file directory structure of requestsors in cyfs-lib -4ed6ddd2 Merge pull request #88 from buckyos/fix-container-dns -7404ab2e Merge branch 'fix-container-dns' into beta -93c35af4 Add router support for group relate methods Add target check for publish_file method -647b53ba Fix query_tasks error and add some logs for task -37c9bd9c Sync context manager modifications with bdt -78dd780c Refactor the context state session manager with source and chunk as unique index -f05bcd8b Refactor the download task to better support state switching and task release -c028b5bc Fix the read logic error for SharedMemChunk -f50bf84b Refactory: change context update_at to async function -7a2582f6 Refactory: chunk downloader triggers context's on_drain when all existing sources tried -475de4ad Refactory: add update at property for download context -d0200673 Fix: reserve or recycle channels when all reference released -eda71af7 Ood-installer support only start ood-daemon -a491c000 Fix AppManager startup param -d2fa72e0 Fix AppManager config path, load config after log init -409c38f9 Router handler support empty string as filter and will treat as none -51d8dc8f Mixed the usage of different requestor config for zone simulator stacks -70e1e833 Add shared stack cache logic to zone simulator -37cae961 Remove shared stack support and cache from cyfs-stack-loader -eb77a092 Improve open shared stack relate logic and add requestor config params -00b8cf65 Improve the local file & chunk writers logs -e0f14387 Refactor the file task and chunk task and use a consistent impls at the lower layer -e138e06c Add chunk type support for verify_file_task -3fb583e0 Add state manager with context for ndn task to cancel task on source error -200c8922 Refactory: add method on_drain for download context -72e2bb30 Impl: cancel task with user defined error -a0413319 Sync test cases with interface modification -473334df Add access support for build_dir_from_object_map source object's access -973718a1 Add get_object_map_ex with access field return for object_map relate cache -4a547ca3 Add access param support for publish_file and build_file relate methods -78d8f93e Add access support to put_object_map relate methods -750e65d5 Add some logs for task manager -58d90843 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead -b398e932 Fix: download task finish directly when total length is zero -2b415e37 Fix: download task progress/speed -54965e6c Improve some logs output -f62cb4df Refactory: impl download task progress -bbec1935 Fix: finish download leaf task -fd230411 Refactory: upload task group cancel/close -4c2f95b4 Refactory: Add logic leaf download task -eab160ec Refactory: chunk downloader send interest with group_path field -50db1d5c Refactory: chunk downloader not mergable -062bf19e Add from_str support for access string -2243fa7b Add alias for trans output requests -ebb67790 Improve the log and error codes for local file relate codes -ff7dd4c1 Use insert_chunk instead of update_chunk_state for chunk state updater -0525944c Improve insert_chunk logic with update state when already exists for ndc module -fc2d8b18 Improve some logs output for ndn relate codes -128a7cc5 Fix: some warning with while let -f1890ba3 Add chunk exists check for ndn get_data cache mechanism -18c94cf2 Improve some error process in std::io poll relate methods -06f03a6a Improve the conversion between BuckyError and std::io::Error -e801b468 Improve put_chunk for local chunk cache -23a61570 Add cache mechanism to ndn get_data -9055ec35 Refactory: add group_path field to interest packet -1093046b Add range support for ndn get_data with chunk -e3797e31 Add group test case -5061b962 Refactory: poll split read -e700a047 Use {dec_id}/ as default group when no group param is specified -14339d1a Remove dec_id field of context object Add global context support for context -6922dfa0 Put_context is adjusted to depend on context manager Add access field for put_context request -968e5e6d Fix context path fix error & add test case -b70f7990 Fix error when context manager parse context string with object_id -de18c885 Add ndn context test cases Fix compile errors of trans relate methods -8687e171 Fix ndn referer param encode error -be8f06b3 Add debug output for changed of context -abcc02d8 Remove context_id field for query tasks request -21421faf Fix: build error for cyfs-stack -4f62dbad Fix: build error for cyfs-stack -6d6ccad3 Improve resp process for trans & sync api methods -3eb6ca28 Refactor put_context and get_context methods for trans -5ad7e7f1 Improve the clone_from_slice method for ObjectId -9ece347b Refactor context support for trans -7340db07 Refactor ndn api target related codes to support context -458ad1f6 Refactor context to support target mode -9ea97744 Add context field for ndn get_data request -4a0aa1b6 Adapt to bdt new context relate params and types -b51eed19 Add cache and path search category to context manager -f0427489 Add dec_id field for context object, and add strict limit to context_path field -3441fdb0 Refactory: rename ChunkEncodeDesc => ChunkCodecDesc; declare context.source_of as async function; -04db0d46 Add context holder generator for context manager -6081a426 Add context manager and holder core impls -23eb4af0 Refactor the TransContext core object -73d7dcb1 Add dec limit for trans task group relate methods -abda8cfc Improve the param of TransOutputProcessor methods -a3678c4e Improve the trans.query_tasks request path -0fb35dbb Add task group relate methods for trans api -c78b3568 Add a common impl of serde code for JsonCodec -70366e60 Refactor get_task_state method's response to add group support -2d335eff Add group field for DownloadTaskState -ba606857 Add task group for ndn get_data resp -bbb16276 Improve the url query parse for referer and group params -5fae309c Add task group support for NDN/Trans modules -71414249 Rename the task range reader -a5107424 Optimize the ChunkWriter write method -b5ba81fb DirLoader switch to reply on chunk_store_reader instead of local_data_manager -89df6fcc NDN local_data_manager's get relate impls switch to reply on target_data_manager instead -bdfabe75 Fix: split read test -12610350 Fix: cyfs stack ndn event apply to new bdt ndn interface -816e7f6b Refactor the param model of ndc/tracker/chunk_manager -a397bd52 Adapt to bdt's new download stream model -2d5eb444 Impl: split read for download task reader -6cd9410e Impl: Add Single source context -95c8554a Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group -5a1f23af Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group -6111f439 Fix: Release chunk cache and downloader with weak reference -ffc56abe Refactory:create seperate downloader when context is not mergable -1ff8388e Refactory: add loading state to chunk cache -8e3590a2 Refactory: split chunk downloader from chunk cache -f2a3672f Fix: call cc on_loss with error loss count value -1dd8bae3 Fix: Donwload task path logic -4f3a92c4 Fix: return download task speed -371792c0 Fix: use BuckyError instead of BuckyErrorCode in some state -167664c9 Fix: add chunk_list_writer method to TrackedChunkStore -b4a67578 Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta -2e42dae0 Fix: stream chunk encoder always read cache with sync reader -bb954d5f Impl: Unit test for upload from path -8b7aa861 Refactory: Add start_upload_from_cache method -81014478 Refactory: Move ndn default event handler to utils -def00192 Refactory: remove default ndc/tracker from bdt stack -67f29271 Refactory: Taskgroup makesure path -896b39ba Impl: File raw cache for chunk -bc043adc In SN statistic, add endpoint's statistic. -ecb58708 Call sn support MTU_LARGE -2cf4567b Add Mutlity SN。 -2321e02c Fix: tcp tunnel send piece buffer with mtu -2ac27f33 Refactory: add DownloadContext trait -6832e73e Refactory: add DownloadContext trait -330a8940 Support large mtu and question&answer -e03962a7 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -d1cc885e Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -06d89662 Fix: chunk list task reader -f4d20813 Fix: close/finish download task group -5bd2ec64 Fix: task.reader return unexpected not found error -7d2e6f6f Fix:panic on download reader -de837c47 Refactory: write chunk from task.reader -677e444b Refactory: Reader of download task -c0a479e3 Refactory: Upload session wait establish -22e9cc0f Refactory: download/upload differs in tcp/udp tunnel -638a8fc4 Refactory: download/upload differs in tcp/udp tunnel -23251581 Fix: bind tunnel with upload/download session -70292ce4 Fix: cache packages in tunnel.build_send, send them when tunnel actived -197e241a Merge branch 'ndn-cache' into bdt-beta -51d5b714 Merge branch 'ndn-cache' into bdt-beta -ea1dae46 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -16d25537 Merge branch 'ndn-cache' into bdt-beta -c6bf684a log decrypt aeskey error info -79bceeea Fix: chunk list task reader -bc380433 Fix: close/finish download task group -61714a7b Fix: task.reader return unexpected not found error -97c955d7 Fix:panic on download reader -1e95e4da Refactory: write chunk from task.reader -9ad964fb Refactory: Reader of download task -d8bf33a0 Refactory: Upload session wait establish -06f3affc Refactory: download/upload differs in tcp/udp tunnel -2ef44f99 Refactory: download/upload differs in tcp/udp tunnel -8519534c Fix: bind tunnel with upload/download session -b2925e95 Fix: cache packages in tunnel.build_send, send them when tunnel actived -7235f3dc Merge branch 'ndn-cache' into bdt-beta -04e2a5a0 Merge branch 'ndn-cache' into bdt-beta -eaa0b650 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -3d711110 Merge branch 'ndn-cache' into bdt-beta -8c8b6039 log decrypt aeskey error info -43ccf15c Impl: Cancel download chunk task -6efb6eca Test: download from uploader test ok -439635f5 Merge branch 'ndn-cache' into bdt-beta -0e08b03a Refactory: download/upload session support reverse step stream -96ffaef7 Refactory: impl download/upload session with new cache -292cf4ae Refactory: impl download/upload session with new cache -d38e31ba Refactory: impl download/upload session with new cache -07b40c65 Refactory: impl download/upload session with new cache -d525a649 Refactory: implement memory raw cache -e07a4b0e Refactory: chunk downloader with stream cache - -## [1.0.0.703] -- 2023/1/13 -cfd654ac Temporarily disable all ipv6 addresses for bdt stack - -## [1.0.0.702] -- 2023/1/12 -bb72348e App Manager AppSource logic -413edbad AppManager supports more detailed configuration -7b0704ec WIP: add new config for app manager -2eb6dce1 Modify the way to start file uploader -6076a69f Improve the update state relate logic for service in ood-daemon service -44fbe781 Fix: avoid duplicate hole punching process when retry sn call -ea48e120 Merge remote-tracking branch 'origin/fix-container-dns' -56f22e21 Add --startup-mode for ood-daemon startup script -cf1f363c Add startup-mode to ood-daemon service with network verify on system startup -56b755e6 Add active check in daemon update and state check loop -b7943988 Fix compile -2b355960 Fix container dns, when resolv contain 127.0.0.53 -d6b5bb06 Add timeout for repo in ood-daemon service -628649f0 Start the monitor service synchronously on startup -de1e9960 Add service_list cache mechanism for meta config repo -a84bfafe Remove the local status of meta config repo in ood-daemon service -a807f171 Fix: retry sn list when builder not establish in time -5639e004 App-tool and app-tool-ex return error correctly -26b234cb Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main -f136c262 Fix some compile errors and warnings -a4ece723 Remove the useless base project -2d216910 Add app-manager.toml config file support to ood-installer tool -e111f3b2 Remove the useless old configuration of acl.toml -eae9d604 Merge branch 'main' into beta -d5463188 Merge branch 'main' into beta -b34744c3 Merge branch 'main' into beta -180ae196 Remove handler and event manager's none mode -d10953b2 Improve ws session and manager stop-related timing logic -8b84ef3f Add delayed start mechanism for router handler and events -c13cc029 Add shared stack stop test case -faf04a09 Improve ws and event manager stop strategy -c5d02ab9 Improve ws session and ws client stop strategy -007247e2 Refactor ws session related logic and improve packet parser logic -b0463c83 Add stop method to shared stack with requestors -1b80f43a Enable none mode for handler and event system in shared stack -8ec0888b Optimize the use of requestor by the service component and adopt the shared mode -d9d69051 Remove http handler support for shared stack -bb0e005e Add stop method to handler and event manager -1a2ada09 Add stop method for ws client -77ea26c6 Fix: cyfs-client correct get sn list from local stack -e29cd15c Merge branch 'main' into beta -0bb5dcd7 Sync service list method use the lock for services in ood-daemon -19b338e6 Improve some logs output -7e8cb267 Improve cmd status check return value and compare mechanism -fc800657 Improve the agent check for the browser disable mode -67a2179e NamedDataClient use init config, use GetData instead of GetDataWithMeta -e160a62a Improve the get_data logic of chunk_manager -9f7263bc Add memory cache for chunk_manager get_data_with_meta Improve the get_chunk_data resp body mechanism and remove the chunk_id verify temporarily -270778a9 Fix: stream pool use sn list in device cache -b1abf319 Fix: ignore sn list in build param's remote desc -ff05f5ff Fix: beta use correct built-in sn list -02fe10ef Fix: Add logs for build params info -26989db3 Merge branch 'main' into beta -440b90f9 Merge branch 'main' into beta -c377c61f Merge branch 'main' into beta -b0fe871d Merge branch 'main' into beta -ef8a124a Merge branch 'main' into beta -71e9e52b Merge branch 'main' into beta -2fa6be68 Fix: disable cyfs_debug::mutex check in some fraquently called functions +## [1.0.0.718] -- 2023/2/21 +1b0cf118 Change sync services packages from parallel to serial +638848a2 Remove two spawn task using for cancel on timeout +70837da7 Fix error op_env type check in requestor +e3f55f6e Improve timeout and retry strategy for repo download in ood-daemon service +9c3c63ab Meta db initialization switch to transaction mode +1e4e4277 Modify: add some statistic logs for ndn +94d8f7a4 Merge branch '104-appmanager-suppport-local-app-repo-store' +34580770 Modify: add some statistic logs for ndn +7522c0fe Email Sender support starttls +10d27023 App Manager support install app from local repo +2a3c1dc1 ood-installer support sync app repo +51f0be28 WIP: App Manager Support Local Repo +e6392f5b WIP: App Manager reflator app install logic +e65fe061 WIP: AppManager add repo type, use zip_extract to extract app service package + +## [1.0.0.715] -- 2023/2/20 +e51af4f2 Set docker api timeout to 300s +b213c3fe Fix: tcp not update active time when recv packet +24553a9c Improve the object layer strategy detection of after pass the first layer rpath access verification +574cfddf OOD-daemon will now report an error and exit if it fails to load the repo +0ab51327 Add version output in process alive check log +14c004b6 Fix meta-stat email format +4daab080 App-manager report app status to ood-daemon +c09ddea9 Fix field names of ood status +f3449363 Fix: monitor create desc when desc not existed on chain +a4e0e755 Fix: stream break when loss fin ack packet +0d2393f3 Fix: monitor create desc error +ba302dd4 Merge remote-tracking branch 'origin/107-support-multiple-global-states-in-cyfs-stack' into main +3d70797d Add group state test case +63e3e712 Fix a assert error when global state is init +61a5eff1 Cyfs monitor use generated identify to test metachain read and write +3d4aefc9 Improve the use of u64::MAX in two places +ee5323ea Delete some useless logs +90d9b5c8 meta spv support storage anbd query objects by object id, body hash +1101829c Add isolate_id method for GlobalStateRawProcessor +e3765b61 Add global state raw processor for use by external components of cyfs-stack +ff03c824 Add the persistence mechanism of all the global state list +b4c4de04 Refactor GlobalStateManager to support multiple global-states +937c7dbe Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +b4284830 Add exists methods into collection for to check if exists +5bcc2984 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +da09ed21 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +412d03ff Merge branch '99-recycle-unused-bdt-tunnel-instances' +979773da Fix: implement stream reserving 2*msl state with lru cache +25c53b07 Refactory: export private methods with pub(crate) +114f1d1b Fix: bdt unit test sn with ipv6 endpoints +fdde1948 Merge branch '95-ipv6-support-refactory' +1b91764a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8d522ec7 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +1875de3d Add object and name for meta in cyfs-stack +3e12b1be Fix cyfs-perf deps Improve the format of some tomls +e83890fc Add noc meta cache to optimize update last access write operation +2ff85f4d Publish cyfs-core new version +d917d648 Bump cyfs-core version +0dd49104 Fix cyfs-core deps +220c7ab2 Fix compile error +dd2f2f17 Publish new cargo packages +fb63c476 Bump cargo package version and dependences +89917227 Merge branch 'main' into beta +75aea584 Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8f60a00b Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +2ebd1e20 Add object and name for meta in cyfs-stack +4d5a9e90 Fix cyfs-perf deps Improve the format of some tomls +2121a11e Add noc meta cache to optimize update last access write operation +078b27d3 Publish cyfs-core new version +019b09d9 Bump cyfs-core version +51e4365b Fix cyfs-core deps +a04d6e88 Fix compile error +038b75b4 Publish new cargo packages +279ce4bd Bump cargo package version and dependences +026c1383 Merge branch 'main' into beta +ccb044db Integrate ood-daemon services status +4af47a92 Improve ServiceState fields spelling +f9eaed01 Add service status related def +ec1ba569 ood-daemon adds independent status http server +5bc02595 Add service status support to ood-daemon +ff14b0d1 Add external http server support to ood control +287c9468 Fix app-manager compile error +08249fa5 Cyfs Monitor restore case interval time after success +c6c372dc Add noc test cases +b176d6a5 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +97bd7bb9 Print warning when decapp missing status or stop scripts +9f85c599 Stream shutdown success at closed state +71ffede0 Fix: fix reset key logic +ec2194ec Integrate ood-daemon services status +2b30769b Improve ServiceState fields spelling +eb881d46 Add service status related def +5dc9c661 ood-daemon adds independent status http server +b2882ff5 Add service status support to ood-daemon +cfc87989 Add external http server support to ood control +d54866c2 Fix app-manager compile error +f0822e79 Cyfs Monitor restore case interval time after success +ab37ea21 Add noc test cases +fa1cc5c0 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +13cdfe46 Print warning when decapp missing status or stop scripts +5ad5d183 Fix: bdt unit test sn with ipv6 endpoints +9607470d Merge branch '95-ipv6-support-refactory' +a8ba267a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +5c2a8d77 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +c88a5e76 Add object and name for meta in cyfs-stack +598df4a8 Fix cyfs-perf deps Improve the format of some tomls +1952c7ee Add noc meta cache to optimize update last access write operation +ba181cef Publish cyfs-core new version +139a9ab6 Bump cyfs-core version +11c7205a Fix cyfs-core deps +76f871ea Fix compile error +30f99d3d Publish new cargo packages +4228e263 Bump cargo package version and dependences +34cb38f4 Merge branch 'main' into beta +87956987 Integrate ood-daemon services status +086dcd8a Improve ServiceState fields spelling +51f135c6 Add service status related def +0bd37768 ood-daemon adds independent status http server +933ed8cd Add isolate_path_env stub test cases +1be055d0 Add service status support to ood-daemon +d3e16c4d Add native ioslate_path_env component test cases and fix some test warnings +25fa3e85 Add external http server support to ood control +60b04789 Add ioslate path env stub +4b32f2b0 Optimize objectmap path to support non-transactional mode +5a6aa9b7 Integrate isolate path env into global-state services +6ccd4ef9 Add isolate path env impl +c78ae028 Fix app-manager compile error +429bddd8 Cyfs Monitor restore case interval time after success +9dd5aac3 Add noc test cases +c7132f26 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +cbf80ee3 Print warning when decapp missing status or stop scripts +2451a583 Fix: package enter write closed state correctly +0d4443ff Panic manager supports multiple bug reporters +f6749bb1 Stream shutdown success at closed state +f1a4cc60 Create a directory if it does not exist when downloading to a local file +28a37154 Improve cyfs-stack's control strategy for task manager resume_task +a63d6854 Fix: fix reset key logic +b7a3e3c9 Add dingtalk_bug_report method to PanicBuilder for external use +445fc501 Optimize some logs output +cc70a84b Add init-ood-daemon param to ood-installer +28fbed65 Remove cyfs-bdt's dependence on os-id lib +18d1534d Improve the ndn request logs output +8538be10 Add req_path suport to front o protocol for acl +1a621713 Send start notify when cyfs-monitor started +e8752b2a Improve the problem that the front r protocol cannot correctly handle data req_path for acl +4abdcf6b Use search instead of get for device in context +c8ad90a8 Add target device prompt info to access reject msg for better debug +4cc08abb Improve cyfs stack test cases +9cf2aafe Improve some logs output about chunk cache +b30d8cd6 Fix: chunk list task download split chunks dumplicatedly +c2570da0 Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +b7ecdbc7 Fix: using channel got reserved correctly +a8a9a3b9 Fix: cyfs-monitor report, use sn-online-test to test sn server status +c3964a38 impl: log udp socket's recv loop thread os id +cb239140 Improve some logs output +67b2aed5 Add seperate sn-online-test program +b6e22b0f Fix: cyfs stack resp interest with NotFound if chunk not exists on default +e1bbe10d Fix: Add some log for dectecting zero speed source +d3535025 Fix: modify resend piece control send time +04629f0f Fix: channel ignore estimate request for sequence lost +11bfb5a5 Correct the use of sync mechanism on bdt download context +d2d9ff8f Bdt acl callback can correctly handle empty referer now +a2ebb0df Changed to auto cancel strategy for ndn task with context param +d653c967 Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +a2cb418a Remove useless ood_resolver field from ndn service relate codes +236abdbb Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +cb0cba8a Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +dce764a9 Add object and name for meta in cyfs-stack +e0dac397 Fix: tcp stream don't reset tunnel when break +5af0b5fb Fix: implement stream reserving 2*msl state with lru cache +3da42793 Fix cyfs-perf deps Improve the format of some tomls +9867ad29 Add noc meta cache to optimize update last access write operation +e11ff3ef Publish cyfs-core new version +95a5c99d Bump cyfs-core version +c168c17a Fix cyfs-core deps +427050c6 Fix compile error +2412d747 Integrate ood-daemon services status +aa5ff976 Publish new cargo packages +0249ba77 Bump cargo package version and dependences +96e3bb69 Merge branch 'main' into beta +0493c935 Improve ServiceState fields spelling +5a88c564 Add service status related def +00bf2764 ood-daemon adds independent status http server +c013612e Fix: bdt mem device cache limited size +39de9529 Refactory: export private methods with pub(crate) +7785029d Fix: package enter write closed state correctly +101db063 Stream shutdown success at closed state +3fca43d8 Create a directory if it does not exist when downloading to a local file +ac0e4f2a Improve cyfs-stack's control strategy for task manager resume_task +4d8bfacc Fix: fix reset key logic +96e1c1e6 Panic manager supports multiple bug reporters +8d9b7929 Add dingtalk_bug_report method to PanicBuilder for external use +7825a4ea Optimize some logs output +fa6867c6 Add init-ood-daemon param to ood-installer +9aa4489c Remove cyfs-bdt's dependence on os-id lib +66b856fc Improve the ndn request logs output +c0622388 Add req_path suport to front o protocol for acl +cc24f8e0 Send start notify when cyfs-monitor started +10ace371 Improve the problem that the front r protocol cannot correctly handle data req_path for acl +6c59337d Use search instead of get for device in context +ef0f880d Add target device prompt info to access reject msg for better debug +beb0e7be Add service status support to ood-daemon +edc1d1f6 Add external http server support to ood control +e5e9a3a5 Refactory: stream release tunnel guard when closed +009c3c8a Refactory: export private methods with pub(crate) +8e21764a Refactory: export private methods with pub(crate) +743c2fcf Impl: recycle unused tunnel +b4eb9f85 Add isolate_path_env stub test cases +b0c6fd63 Add native ioslate_path_env component test cases and fix some test warnings +3f14f978 Impl: add a test for sn ipv6 ping +ff916188 Add ioslate path env stub +dd437a1f Impl: sn support ipv6 ping +b69709df Optimize objectmap path to support non-transactional mode +0de3fc0c Integrate isolate path env into global-state services +edacc65a Add isolate path env impl +29fed496 Remove complie warning +f3f66501 Impl: Add transfered and recursion close method to ndn task +027e9ae4 Impl: Add transfered and recursion close method to ndn task +6a1f7ed1 Rebase: rebase to 74-integrate-bdt-task-context-and-group +aa682520 Refactory: impl trans api for close upload group +260cbdf8 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +c2bd5612 Refactory: impl trans api for close upload group +99bbebfc Refactory: impl trans api for upload group +c19064b5 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +2f47bcc0 Fix: reserve or recycle channels when all reference released +ae3f02eb Impl: cancel task with user defined error +82692c64 Fix: download task progress/speed +bc3ba88e Rebase: rebase to 74-integrate-bdt-task-context-and-group +58d6d195 Refactory: impl trans api for close upload group +5dad1539 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +30aa07ae Fix: reserve or recycle channels when all reference released +acaa42fb Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +09076f70 Add uptime and boot_time into get_system_info +2b81e62a Fix: correctly wait dapp process +3bbbcfc3 Add total trans bytes field in get_system_info Added network card deduplication in some environments +80fa0863 Publish new cargo packages +ae40d694 Fix cyfs-util publish error +ee957a29 Bump cargo packages version +89341b52 Fix: retry sn list when offline +1370e83c Improve ndn test case with get_data +3584395e Improve the resp's return logic of get_data with error prompt +a3a5172e Use of http requestor for get_data and put_data methods as default +0347e50e Error of reading resp is returned correctly in ws mode +87d26ad6 Merge remote-tracking branch 'origin/main' into main +0df70f89 Sync projects for trans and stack object relate apis's changes +2ef0d178 Fix a compile error with requestor config and some warnings +4b716f44 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +1a15a767 Fix: trigger chunk downloader's on_drain method +e9faea63 Add some logs +a8dedd60 Add serialization support for storage base on global state +6effd696 Add log for named-data-client chunk reading +9edf7c31 Merge branch '74-integrate-bdt-task-context-and-group' +3fcdbf0c Improve ood-daemon's upgrade detection and restart logic +e0323ea1 Add host mode support to browser sanbox +91e519ec Also check app exclude list when install or start app +66acc69e Merge pull request #88 from buckyos/fix-container-dns +f1a63712 Ood-installer support only start ood-daemon +6514acec Fix AppManager startup param +ee80ce8c Fix AppManager config path, load config after log init +cb2ac1ee Mixed the usage of different requestor config for zone simulator stacks +be10f64b Add shared stack cache logic to zone simulator +5da765af Remove shared stack support and cache from cyfs-stack-loader +c2708f59 Improve open shared stack relate logic and add requestor config params +6150617a Temporarily disable all ipv6 addresses for bdt stack +95654ae5 App Manager AppSource logic +e849439c AppManager supports more detailed configuration +715e851e WIP: add new config for app manager +2ded38db Modify the way to start file uploader +0a50ed5f Improve the update state relate logic for service in ood-daemon service +c7de6539 Fix: avoid duplicate hole punching process when retry sn call +e828e7b5 Merge remote-tracking branch 'origin/fix-container-dns' +f8f4381b Add --startup-mode for ood-daemon startup script +c7bf12f2 Add startup-mode to ood-daemon service with network verify on system startup +b9aca01d Add active check in daemon update and state check loop +dc6aa3d9 Add timeout for repo in ood-daemon service +20ec54d1 Start the monitor service synchronously on startup +2e66ff4a Add service_list cache mechanism for meta config repo +d758151b Remove the local status of meta config repo in ood-daemon service +f99caadc Fix: retry sn list when builder not establish in time +b143379f Integrate surf requestor into shared stack +7eed812f App-tool and app-tool-ex return error correctly +09f79e9a Remove redundant service requestors constructor +cd8588de Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f5873108 Add surf based requestor +889d7f81 Adjust the file directory structure of requestsors in cyfs-lib +e7e9781e Fix some compile errors and warnings +3aa50d32 Remove the useless base project +4de7e33d Add app-manager.toml config file support to ood-installer tool +9317c01d Remove the useless old configuration of acl.toml +5af28985 Improve the error status of build relate tasks +a762fecf Merge branch 'fix-container-dns' into beta +b3231559 Fix compile +832e7a20 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b2471088 Fix container dns, when resolv contain 127.0.0.53 +bde55b1a Merge branch 'main' into beta +4dd330fe Merge branch 'main' into beta +35cabb3f Merge branch 'main' into beta +bd9326c9 File upload tool only support windows & mac for now. +01a46434 Open upload tool with "open" cmd on Mac +b45d377f Fix:ping client doesn't update local device +b36e728e Fix:ping client doesn't update local device +d9bd6698 Remove handler and event manager's none mode +980b5392 Add some field compatibility with the old version's data on new db format +6541571a Fix: pannic on time escape of call session +c0ceda78 Improve ws session and manager stop-related timing logic +f30cc9c8 Fix: some warning with while let +473e56d6 Add delayed start mechanism for router handler and events +74e30500 Fix: downloading speed/progress for chunk_list/file task use percent +172c5c9e Add shared stack stop test case +d670b458 Improve ws and event manager stop strategy +5841a4fb Improve ws session and ws client stop strategy +b62c204a Refactor ws session related logic and improve packet parser logic +706f06e6 Add stop method to shared stack with requestors +b45ddcf1 Enable none mode for handler and event system in shared stack +a1d67489 Optimize the use of requestor by the service component and adopt the shared mode +6acc40fa Remove http handler support for shared stack +5c3abc42 Add stop method to handler and event manager +b24935d7 Add stop method for ws client +6f55517f Publish new cargo packages +8c933ffc Fix cyfs-util publish error +bf75d29e Bump cargo packages version +bce2a745 Merge branch 'main' into beta +acbd636a Refactory: Add track chunk method option to publish dir/file methods +a022c2cc Fix the bug that search context will enter an infinite loop +a8a57c27 Improve the result of router get_object with flash flags is true +9f3d4e8d Fix the bug for decode context path param without fix +4236102e Add router support for group relate methods Add target check for publish_file method +3d758fcd Merge branch 'main' into beta +0843bbba Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead (#87) +387362a2 Rebase: rebase to 74-integrate-bdt-task-context-and-group +8bdf227b Refactory: impl trans api for close upload group +18ed9311 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +3f52efd9 Impl: cancel task with user defined error +9627d57a Fix: download task progress/speed +e0292e40 Fix: download task progress/speed +addd1976 Refactory: impl trans api for close upload group +dcb4395e Refactory: impl trans api for upload group +db6750fd Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +9f10434a Fix: reserve or recycle channels when all reference released +3ffb8c7e Refactor the file task and chunk task and use a consistent impls at the lower layer +603b5377 Impl: cancel task with user defined error +e66ab510 Fix: download task progress/speed +538a7111 Rebase: rebase to 74-integrate-bdt-task-context-and-group +f720dac7 Refactory: impl trans api for close upload group +a3d86db0 Refactory: impl trans api for upload group +31a93c96 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +f2287d89 Fix query_tasks error and add some logs for task +8ed9f7f2 Sync context manager modifications with bdt +7d6ceaa8 Refactor the context state session manager with source and chunk as unique index +50fb0345 Refactor the download task to better support state switching and task release +a9fe0654 Fix the read logic error for SharedMemChunk +2f89e98d Refactory: change context update_at to async function +f9bbc140 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +4643e4d5 Refactory: add update at property for download context +da234ea1 Fix: reserve or recycle channels when all reference released +a63f74ea Router handler support empty string as filter and will treat as none +5475581f Improve the local file & chunk writers logs +3758c0a0 Refactor the file task and chunk task and use a consistent impls at the lower layer +680f18e2 Add chunk type support for verify_file_task +f237b25b Add state manager with context for ndn task to cancel task on source error +d46a8abb Refactory: add method on_drain for download context +b88929fd Impl: cancel task with user defined error +81c297f0 Sync test cases with interface modification +9ead4762 Add access support for build_dir_from_object_map source object's access +078811fa Add get_object_map_ex with access field return for object_map relate cache +2e1d1924 Add access param support for publish_file and build_file relate methods +eb62b863 Add access support to put_object_map relate methods +dd1caba5 Add some logs for task manager +2b843a47 Fix: download task progress/speed +db13d228 Improve some logs output +f00b77c2 Add from_str support for access string +7c92e607 Add alias for trans output requests +c08c3e36 Improve the log and error codes for local file relate codes +7821234f Use insert_chunk instead of update_chunk_state for chunk state updater +91f0177a Improve insert_chunk logic with update state when already exists for ndc module +ddd8f8e6 Improve some logs output for ndn relate codes +4f637a9d Refactory: interest reponse upload field tokens +1c12c499 Fix: download task finish directly when total length is zero +a43ef9db Fix: download task progress/speed +e94e9560 Fix: download task progress/speed +307c10b5 Refactory: impl trans api for close upload group +a9071c13 Refactory: impl trans api for upload group +763791ba Refactory: upload handler with group_path filter; upload handler response with upload from path +96603e3c Refactory: impl download task progress +191497e7 Fix: finish download leaf task +311aba18 Refactory: upload task group cancel/close +38d8d707 Refactory: Add logic leaf download task +f0141ccc Refactory: chunk downloader send interest with group_path field +6291029a Refactory: chunk downloader not mergable +1684b91f Fix: pannic on udp call +0cf29489 Merge branch 'main' into bdt-beta +5bd73033 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +7805227c Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +a4dbe34f Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +8611caff Fix: add log for ping clients +71af78d7 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +7a1d4b82 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +5540f89e Fix: the status of udp stream +e5307fac Fix: cc loss bytes in stream write +229dbc6a Add reset_sn_list() function in Stack's ineterface. +b469a288 Upload get-nearest SN Server in client call. The build-tunnel-params's remote-sn is priority over get-nearest sn-list. +a564d9ee Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta + +## [1.0.0.713] -- 2023/2/11 +ab8a2a6c Fix app-manager compile error +cd7eb6b4 Cyfs Monitor restore case interval time after success +7a03fdb3 Add noc test cases +bb596b85 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +20d14f19 Print warning when decapp missing status or stop scripts + +## [1.0.0.711] -- 2023/2/11 +2c798622 Fix: package enter write closed state correctly +be780df7 Stream shutdown success at closed state +21aef793 Create a directory if it does not exist when downloading to a local file +b6b7e7f8 Improve cyfs-stack's control strategy for task manager resume_task +c0f775cc Fix: fix reset key logic +c90f6ae9 Panic manager supports multiple bug reporters +07f2717d Add dingtalk_bug_report method to PanicBuilder for external use +db4acc4b Optimize some logs output +fb13f654 Add init-ood-daemon param to ood-installer +8f8e88c2 Remove cyfs-bdt's dependence on os-id lib +c05e88b7 Improve the ndn request logs output +7e0c03b0 Add req_path suport to front o protocol for acl +e3d042a0 Send start notify when cyfs-monitor started +2b3a433e Improve the problem that the front r protocol cannot correctly handle data req_path for acl +11e6ed60 Use search instead of get for device in context +06498f24 Add target device prompt info to access reject msg for better debug +7c753b20 Improve cyfs stack test cases +851f1a04 Improve some logs output about chunk cache +7cce9079 Fix: chunk list task download split chunks dumplicatedly + +## [1.0.0.709] -- 2023/2/7 +3005944e Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +0a004af9 Fix: using channel got reserved correctly +1bfe7b55 Fix: cyfs-monitor report, use sn-online-test to test sn server status +8aa6a426 impl: log udp socket's recv loop thread os id +a1d30562 Improve some logs output +4bf5e29c Add seperate sn-online-test program +82e71892 Fix: cyfs stack resp interest with NotFound if chunk not exists on default +7af6ce69 Fix: Add some log for dectecting zero speed source +d593800f Fix: modify resend piece control send time +b5c41727 Fix: channel ignore estimate request for sequence lost +21a3cb11 Correct the use of sync mechanism on bdt download context +42b7029e Bdt acl callback can correctly handle empty referer now +52709bc8 Changed to auto cancel strategy for ndn task with context param +acde7c48 Remove complie warning +6834b67a Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +4c3370f4 Remove useless ood_resolver field from ndn service relate codes + +## [1.0.0.708] -- 2023/2/6 +4e1122df Fix: the status of udp stream +58c545d7 Improve the handling of non.get_object when the target object cannot be found in (dir or objectmap) + inner_path mode +78904db7 Switch cyfs-ndc and cyfs-tracker-cache db to use SqliteConnectionHolder +932f1c61 Add SqliteConnectionHolder for general db connection management Switch cyfs-noc db to use SqliteConnectionHolder +5f1db008 impl: add a download context strategy to cancel source when zero speed +044bc59c Fix: ndn timer triggered correctly +d6bccc0f The read and write mode of Meta db is separated to support read-only in special cases such as disk is full etc + +## [1.0.0.707] -- 2023/2/3 +0ac77054 Fix the coding stability problem of Dir about HashMap +85cdd9cb Change some Mutex to cyfs-debug's checked Mutex in ood-daemon +5a448ccd Fix the deadlock bug that may be caused by service state detection +24177f29 Add test cases for config repo in ood-daemon project +8c7465ea Fix the coding stability problem of AppList and AppLocalStatus about HashMap +47d820ae Add sort by name strategy for device-config.toml +df39550f Fix the init error of trans store when the db dir is missing +bad1a48d Add inner path support for SingleOpEnvStub +cec8822c Add inner_path support for single_op_env.load method +26c68baa Fix some warning and add some comments +dc3b6e74 Update cyfs-bdt-ext deps +e977dcc9 Move LocalDeviceManager from cyfs-stack-loader to cyfs-util Remove the dependency on cyfs-stack-loader of ood-daemon and ood-installer +b09291cb Add stop_all support to stop all the services for ood-daemon +e031b4b5 Remove useless codes in cyfs-stack project +efb2431c Merge remote-tracking branch 'origin/92-more-convenient-and-suitable-to-use-cyfs-bdt' into main +170eedcf Move group and data relate codes to cyfs-bdt-ext project +259c46c4 Switched cyfs-stack to rely on cyfs-bdt-ext +965803d5 Move relate components to cyfs-bdt-ext project +00f5b35b Add cyfs-bdt-ext project +50036402 Add uptime and boot_time into get_system_info +a166c72d Fix: correctly wait dapp process +20ddf1d0 Add total trans bytes field in get_system_info Added network card deduplication in some environments +ec08c584 Publish new cargo packages +b6db6f9b Fix cyfs-util publish error +cd204231 Bump cargo packages version +cd120a75 Fix: retry sn list when offline +338c31b8 Improve ndn test case with get_data +9ee1a6d4 Improve the resp's return logic of get_data with error prompt +87b0693e Use of http requestor for get_data and put_data methods as default +6f4d47a0 Error of reading resp is returned correctly in ws mode +114c040a Merge remote-tracking branch 'origin/main' into main +a5c5da0e Sync projects for trans and stack object relate apis's changes +b51738f3 Fix a compile error with requestor config and some warnings +d7950257 Fix: trigger chunk downloader's on_drain method +95abf250 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +fd22bdec Add some logs +4a459fd3 Add serialization support for storage base on global state +068cde9a Add log for named-data-client chunk reading +cd0f3c5f Fix a compile error +ab7cf9e1 Merge branch '74-integrate-bdt-task-context-and-group' +63a37de6 Improve ood-daemon's upgrade detection and restart logic +6850633e Add host mode support to browser sanbox +d4d2639d Improve the error status of build relate tasks +7aa93795 Fix the bug that search context will enter an infinite loop +3ff1412f Improve the result of router get_object with flash flags is true +1ff3ff2e Fix the bug for decode context path param without fix +6bd563c9 Integrate surf requestor into shared stack +dc6d5ebb Remove redundant service requestors constructor +066ebd0e Add surf based requestor +066fe787 Also check app exclude list when install or start app +32b62e13 Adjust the file directory structure of requestsors in cyfs-lib +4ed6ddd2 Merge pull request #88 from buckyos/fix-container-dns +7404ab2e Merge branch 'fix-container-dns' into beta +93c35af4 Add router support for group relate methods Add target check for publish_file method +647b53ba Fix query_tasks error and add some logs for task +37c9bd9c Sync context manager modifications with bdt +78dd780c Refactor the context state session manager with source and chunk as unique index +f05bcd8b Refactor the download task to better support state switching and task release +c028b5bc Fix the read logic error for SharedMemChunk +f50bf84b Refactory: change context update_at to async function +7a2582f6 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +475de4ad Refactory: add update at property for download context +d0200673 Fix: reserve or recycle channels when all reference released +eda71af7 Ood-installer support only start ood-daemon +a491c000 Fix AppManager startup param +d2fa72e0 Fix AppManager config path, load config after log init +409c38f9 Router handler support empty string as filter and will treat as none +51d8dc8f Mixed the usage of different requestor config for zone simulator stacks +70e1e833 Add shared stack cache logic to zone simulator +37cae961 Remove shared stack support and cache from cyfs-stack-loader +eb77a092 Improve open shared stack relate logic and add requestor config params +00b8cf65 Improve the local file & chunk writers logs +e0f14387 Refactor the file task and chunk task and use a consistent impls at the lower layer +e138e06c Add chunk type support for verify_file_task +3fb583e0 Add state manager with context for ndn task to cancel task on source error +200c8922 Refactory: add method on_drain for download context +72e2bb30 Impl: cancel task with user defined error +a0413319 Sync test cases with interface modification +473334df Add access support for build_dir_from_object_map source object's access +973718a1 Add get_object_map_ex with access field return for object_map relate cache +4a547ca3 Add access param support for publish_file and build_file relate methods +78d8f93e Add access support to put_object_map relate methods +750e65d5 Add some logs for task manager +58d90843 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b398e932 Fix: download task finish directly when total length is zero +2b415e37 Fix: download task progress/speed +54965e6c Improve some logs output +f62cb4df Refactory: impl download task progress +bbec1935 Fix: finish download leaf task +fd230411 Refactory: upload task group cancel/close +4c2f95b4 Refactory: Add logic leaf download task +eab160ec Refactory: chunk downloader send interest with group_path field +50db1d5c Refactory: chunk downloader not mergable +062bf19e Add from_str support for access string +2243fa7b Add alias for trans output requests +ebb67790 Improve the log and error codes for local file relate codes +ff7dd4c1 Use insert_chunk instead of update_chunk_state for chunk state updater +0525944c Improve insert_chunk logic with update state when already exists for ndc module +fc2d8b18 Improve some logs output for ndn relate codes +128a7cc5 Fix: some warning with while let +f1890ba3 Add chunk exists check for ndn get_data cache mechanism +18c94cf2 Improve some error process in std::io poll relate methods +06f03a6a Improve the conversion between BuckyError and std::io::Error +e801b468 Improve put_chunk for local chunk cache +23a61570 Add cache mechanism to ndn get_data +9055ec35 Refactory: add group_path field to interest packet +1093046b Add range support for ndn get_data with chunk +e3797e31 Add group test case +5061b962 Refactory: poll split read +e700a047 Use {dec_id}/ as default group when no group param is specified +14339d1a Remove dec_id field of context object Add global context support for context +6922dfa0 Put_context is adjusted to depend on context manager Add access field for put_context request +968e5e6d Fix context path fix error & add test case +b70f7990 Fix error when context manager parse context string with object_id +de18c885 Add ndn context test cases Fix compile errors of trans relate methods +8687e171 Fix ndn referer param encode error +be8f06b3 Add debug output for changed of context +abcc02d8 Remove context_id field for query tasks request +21421faf Fix: build error for cyfs-stack +4f62dbad Fix: build error for cyfs-stack +6d6ccad3 Improve resp process for trans & sync api methods +3eb6ca28 Refactor put_context and get_context methods for trans +5ad7e7f1 Improve the clone_from_slice method for ObjectId +9ece347b Refactor context support for trans +7340db07 Refactor ndn api target related codes to support context +458ad1f6 Refactor context to support target mode +9ea97744 Add context field for ndn get_data request +4a0aa1b6 Adapt to bdt new context relate params and types +b51eed19 Add cache and path search category to context manager +f0427489 Add dec_id field for context object, and add strict limit to context_path field +3441fdb0 Refactory: rename ChunkEncodeDesc => ChunkCodecDesc; declare context.source_of as async function; +04db0d46 Add context holder generator for context manager +6081a426 Add context manager and holder core impls +23eb4af0 Refactor the TransContext core object +73d7dcb1 Add dec limit for trans task group relate methods +abda8cfc Improve the param of TransOutputProcessor methods +a3678c4e Improve the trans.query_tasks request path +0fb35dbb Add task group relate methods for trans api +c78b3568 Add a common impl of serde code for JsonCodec +70366e60 Refactor get_task_state method's response to add group support +2d335eff Add group field for DownloadTaskState +ba606857 Add task group for ndn get_data resp +bbb16276 Improve the url query parse for referer and group params +5fae309c Add task group support for NDN/Trans modules +71414249 Rename the task range reader +a5107424 Optimize the ChunkWriter write method +b5ba81fb DirLoader switch to reply on chunk_store_reader instead of local_data_manager +89df6fcc NDN local_data_manager's get relate impls switch to reply on target_data_manager instead +bdfabe75 Fix: split read test +12610350 Fix: cyfs stack ndn event apply to new bdt ndn interface +816e7f6b Refactor the param model of ndc/tracker/chunk_manager +a397bd52 Adapt to bdt's new download stream model +2d5eb444 Impl: split read for download task reader +6cd9410e Impl: Add Single source context +95c8554a Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +5a1f23af Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +6111f439 Fix: Release chunk cache and downloader with weak reference +ffc56abe Refactory:create seperate downloader when context is not mergable +1ff8388e Refactory: add loading state to chunk cache +8e3590a2 Refactory: split chunk downloader from chunk cache +f2a3672f Fix: call cc on_loss with error loss count value +1dd8bae3 Fix: Donwload task path logic +4f3a92c4 Fix: return download task speed +371792c0 Fix: use BuckyError instead of BuckyErrorCode in some state +167664c9 Fix: add chunk_list_writer method to TrackedChunkStore +b4a67578 Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta +2e42dae0 Fix: stream chunk encoder always read cache with sync reader +bb954d5f Impl: Unit test for upload from path +8b7aa861 Refactory: Add start_upload_from_cache method +81014478 Refactory: Move ndn default event handler to utils +def00192 Refactory: remove default ndc/tracker from bdt stack +67f29271 Refactory: Taskgroup makesure path +896b39ba Impl: File raw cache for chunk +bc043adc In SN statistic, add endpoint's statistic. +ecb58708 Call sn support MTU_LARGE +2cf4567b Add Mutlity SN。 +2321e02c Fix: tcp tunnel send piece buffer with mtu +2ac27f33 Refactory: add DownloadContext trait +6832e73e Refactory: add DownloadContext trait +330a8940 Support large mtu and question&answer +e03962a7 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +d1cc885e Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +06d89662 Fix: chunk list task reader +f4d20813 Fix: close/finish download task group +5bd2ec64 Fix: task.reader return unexpected not found error +7d2e6f6f Fix:panic on download reader +de837c47 Refactory: write chunk from task.reader +677e444b Refactory: Reader of download task +c0a479e3 Refactory: Upload session wait establish +22e9cc0f Refactory: download/upload differs in tcp/udp tunnel +638a8fc4 Refactory: download/upload differs in tcp/udp tunnel +23251581 Fix: bind tunnel with upload/download session +70292ce4 Fix: cache packages in tunnel.build_send, send them when tunnel actived +197e241a Merge branch 'ndn-cache' into bdt-beta +51d5b714 Merge branch 'ndn-cache' into bdt-beta +ea1dae46 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +16d25537 Merge branch 'ndn-cache' into bdt-beta +c6bf684a log decrypt aeskey error info +79bceeea Fix: chunk list task reader +bc380433 Fix: close/finish download task group +61714a7b Fix: task.reader return unexpected not found error +97c955d7 Fix:panic on download reader +1e95e4da Refactory: write chunk from task.reader +9ad964fb Refactory: Reader of download task +d8bf33a0 Refactory: Upload session wait establish +06f3affc Refactory: download/upload differs in tcp/udp tunnel +2ef44f99 Refactory: download/upload differs in tcp/udp tunnel +8519534c Fix: bind tunnel with upload/download session +b2925e95 Fix: cache packages in tunnel.build_send, send them when tunnel actived +7235f3dc Merge branch 'ndn-cache' into bdt-beta +04e2a5a0 Merge branch 'ndn-cache' into bdt-beta +eaa0b650 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +3d711110 Merge branch 'ndn-cache' into bdt-beta +8c8b6039 log decrypt aeskey error info +43ccf15c Impl: Cancel download chunk task +6efb6eca Test: download from uploader test ok +439635f5 Merge branch 'ndn-cache' into bdt-beta +0e08b03a Refactory: download/upload session support reverse step stream +96ffaef7 Refactory: impl download/upload session with new cache +292cf4ae Refactory: impl download/upload session with new cache +d38e31ba Refactory: impl download/upload session with new cache +07b40c65 Refactory: impl download/upload session with new cache +d525a649 Refactory: implement memory raw cache +e07a4b0e Refactory: chunk downloader with stream cache + +## [1.0.0.703] -- 2023/1/13 +cfd654ac Temporarily disable all ipv6 addresses for bdt stack + +## [1.0.0.702] -- 2023/1/12 +bb72348e App Manager AppSource logic +413edbad AppManager supports more detailed configuration +7b0704ec WIP: add new config for app manager +2eb6dce1 Modify the way to start file uploader +6076a69f Improve the update state relate logic for service in ood-daemon service +44fbe781 Fix: avoid duplicate hole punching process when retry sn call +ea48e120 Merge remote-tracking branch 'origin/fix-container-dns' +56f22e21 Add --startup-mode for ood-daemon startup script +cf1f363c Add startup-mode to ood-daemon service with network verify on system startup +56b755e6 Add active check in daemon update and state check loop +b7943988 Fix compile +2b355960 Fix container dns, when resolv contain 127.0.0.53 +d6b5bb06 Add timeout for repo in ood-daemon service +628649f0 Start the monitor service synchronously on startup +de1e9960 Add service_list cache mechanism for meta config repo +a84bfafe Remove the local status of meta config repo in ood-daemon service +a807f171 Fix: retry sn list when builder not establish in time +5639e004 App-tool and app-tool-ex return error correctly +26b234cb Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f136c262 Fix some compile errors and warnings +a4ece723 Remove the useless base project +2d216910 Add app-manager.toml config file support to ood-installer tool +e111f3b2 Remove the useless old configuration of acl.toml +eae9d604 Merge branch 'main' into beta +d5463188 Merge branch 'main' into beta +b34744c3 Merge branch 'main' into beta +180ae196 Remove handler and event manager's none mode +d10953b2 Improve ws session and manager stop-related timing logic +8b84ef3f Add delayed start mechanism for router handler and events +c13cc029 Add shared stack stop test case +faf04a09 Improve ws and event manager stop strategy +c5d02ab9 Improve ws session and ws client stop strategy +007247e2 Refactor ws session related logic and improve packet parser logic +b0463c83 Add stop method to shared stack with requestors +1b80f43a Enable none mode for handler and event system in shared stack +8ec0888b Optimize the use of requestor by the service component and adopt the shared mode +d9d69051 Remove http handler support for shared stack +bb0e005e Add stop method to handler and event manager +1a2ada09 Add stop method for ws client +77ea26c6 Fix: cyfs-client correct get sn list from local stack +e29cd15c Merge branch 'main' into beta +0bb5dcd7 Sync service list method use the lock for services in ood-daemon +19b338e6 Improve some logs output +7e8cb267 Improve cmd status check return value and compare mechanism +fc800657 Improve the agent check for the browser disable mode +67a2179e NamedDataClient use init config, use GetData instead of GetDataWithMeta +e160a62a Improve the get_data logic of chunk_manager +9f7263bc Add memory cache for chunk_manager get_data_with_meta Improve the get_chunk_data resp body mechanism and remove the chunk_id verify temporarily +270778a9 Fix: stream pool use sn list in device cache +b1abf319 Fix: ignore sn list in build param's remote desc +ff05f5ff Fix: beta use correct built-in sn list +02fe10ef Fix: Add logs for build params info +26989db3 Merge branch 'main' into beta +440b90f9 Merge branch 'main' into beta +c377c61f Merge branch 'main' into beta +b0fe871d Merge branch 'main' into beta +ef8a124a Merge branch 'main' into beta +71e9e52b Merge branch 'main' into beta +2fa6be68 Fix: disable cyfs_debug::mutex check in some fraquently called functions From bdc725fc5f724b80b0d97f8b15635a9f6763215f Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 19:33:18 +0800 Subject: [PATCH 142/553] Remove config repo cache after discovering system-config changed --- src/component/cyfs-meta-lib/src/helper.rs | 4 ++++ src/service/ood-daemon/src/config/monitor.rs | 2 ++ src/service/ood-daemon/src/config_repo/meta.rs | 6 +++++- src/service/ood-daemon/src/config_repo/mod.rs | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-meta-lib/src/helper.rs b/src/component/cyfs-meta-lib/src/helper.rs index 6185450d4..55288f375 100644 --- a/src/component/cyfs-meta-lib/src/helper.rs +++ b/src/component/cyfs-meta-lib/src/helper.rs @@ -84,6 +84,10 @@ impl MetaClientHelperWithObjectCache { } } + pub async fn clear_cache(&self) { + self.objects.lock().await.clear(); + } + pub async fn get_object( &self, meta_client: &MetaClient, diff --git a/src/service/ood-daemon/src/config/monitor.rs b/src/service/ood-daemon/src/config/monitor.rs index d7246003f..e49a102f1 100644 --- a/src/service/ood-daemon/src/config/monitor.rs +++ b/src/service/ood-daemon/src/config/monitor.rs @@ -37,6 +37,8 @@ impl SystemConfigMonitor { } let _ = DEVICE_CONFIG_MANAGER.init_repo(); + + DEVICE_CONFIG_MANAGER.get_repo().clear_cache().await; daemon.wakeup_check_update(); diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index d2e4ee67c..ebd5892cc 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -143,7 +143,7 @@ impl DeviceConfigMetaRepo { meta_client, cache: Mutex::new(None), service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), - service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24), 16), + service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24 * 7), 16), } } @@ -457,4 +457,8 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { Ok(device_config_str) } + + async fn clear_cache(&self) { + self.service_objects.clear_cache().await; + } } diff --git a/src/service/ood-daemon/src/config_repo/mod.rs b/src/service/ood-daemon/src/config_repo/mod.rs index 1ae5761b5..e3f33a815 100644 --- a/src/service/ood-daemon/src/config_repo/mod.rs +++ b/src/service/ood-daemon/src/config_repo/mod.rs @@ -17,6 +17,9 @@ use std::sync::Arc; #[async_trait] pub trait DeviceConfigRepo: Send + Sync { async fn fetch(&self) -> BuckyResult; + async fn clear_cache(&self) { + // do nothing on default! + } fn get_type(&self) -> &'static str; } From 1dc85dbfa486b4ac339f10d223db7d2b405838a3 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 20:15:20 +0800 Subject: [PATCH 143/553] Add retry strategy into meta config repo in case of network error --- .../src/config/device_config_manager.rs | 6 +- .../ood-daemon/src/config_repo/meta.rs | 87 ++++++++++++++----- .../ood-daemon/src/service/service_manager.rs | 1 + 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 7394a575f..d5c6298a9 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -148,7 +148,7 @@ impl DeviceConfigManager { let repo = self.get_repo(); // 从mete-chain拉取对应desc - let ret = async_std::future::timeout(Duration::from_secs(60), repo.fetch()).await; + let ret = async_std::future::timeout(Duration::from_secs(60 * 5), repo.fetch()).await; if ret.is_err() { let msg = format!("fetch device config timeout! repo={}", repo.get_type()); @@ -160,10 +160,10 @@ impl DeviceConfigManager { let device_config_str = match ret.unwrap() { Ok(v) => v, Err(e) => { - let msg = format!("load desc from repo failed! err={}", e); + let msg = format!("load device config from repo failed! err={}", e); error!("{}", msg); - return Err(BuckyError::from(msg)); + return Err(BuckyError::new(e.code(), msg)); } }; diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index ebd5892cc..e9d54d2c2 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -3,7 +3,9 @@ use crate::config::*; use cyfs_base::*; use cyfs_core::*; use cyfs_debug::Mutex; -use cyfs_meta_lib::{MetaClient, MetaClientHelper, MetaClientHelperWithObjectCache, MetaMinerTarget}; +use cyfs_meta_lib::{ + MetaClient, MetaClientHelper, MetaClientHelperWithObjectCache, MetaMinerTarget, +}; use cyfs_util::LOCAL_DEVICE_MANAGER; use async_trait::async_trait; @@ -108,7 +110,7 @@ impl DeviceConfigGenerator { false => ServiceState::Stop, }; - debug!("new service item: id={}, version={}", id, version); + debug!("new service item: id={}, origin version in service list={}", id, version); let mut service = ServiceConfig::new(); service.id = id; service.version = version.to_owned(); @@ -142,8 +144,14 @@ impl DeviceConfigMetaRepo { Self { meta_client, cache: Mutex::new(None), - service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), - service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24 * 7), 16), + service_objects: MetaClientHelperWithObjectCache::new( + std::time::Duration::from_secs(3600 * 4), + 16, + ), + service_dir_objects: MetaClientHelperWithObjectCache::new( + std::time::Duration::from_secs(3600 * 24 * 7), + 16, + ), } } @@ -166,7 +174,10 @@ impl DeviceConfigMetaRepo { info!( "device config repo: config_desc={}, device_id={}, service_list_id={}, version={}", - get_system_config().config_desc, device_id, service_list_id, service_list_version + get_system_config().config_desc, + device_id, + service_list_id, + service_list_version ); Ok(service_list_id) @@ -186,7 +197,6 @@ impl DeviceConfigMetaRepo { } async fn load_service_list(&self) -> BuckyResult { - let service_list_id = Self::gen_service_list_id()?; let ret = MetaClientHelper::get_object(&self.meta_client, &service_list_id).await?; if ret.is_none() { @@ -203,7 +213,10 @@ impl DeviceConfigMetaRepo { // 解码 let list = AppList::clone_from_slice(&object_raw).map_err(|e| { - let msg = format!("decode service list object failed! id={}, {}", service_list_id, e); + let msg = format!( + "decode service list object failed! id={}, {}", + service_list_id, e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -219,7 +232,10 @@ impl DeviceConfigMetaRepo { } async fn load_service(&self, service_id: &ObjectId) -> BuckyResult { - let ret = self.service_objects.get_object_raw(&self.meta_client, service_id).await?; + let ret = self + .service_objects + .get_object_raw(&self.meta_client, service_id) + .await?; if ret.is_none() { let msg = format!( "load service object from meta chain but not found! id={}", @@ -244,7 +260,10 @@ impl DeviceConfigMetaRepo { } async fn load_service_dir(&self, dir_id: &ObjectId) -> BuckyResult { - let ret = self.service_dir_objects.get_object_raw(&self.meta_client, dir_id).await?; + let ret = self + .service_dir_objects + .get_object_raw(&self.meta_client, dir_id) + .await?; if ret.is_none() { let msg = format!( "load service dir from meta chain but not found! id={}", @@ -413,15 +432,8 @@ impl DeviceConfigMetaRepo { true } -} -#[async_trait] -impl DeviceConfigRepo for DeviceConfigMetaRepo { - fn get_type(&self) -> &'static str { - "meta" - } - - async fn fetch(&self) -> BuckyResult { + async fn fetch_inner(&self) -> BuckyResult { // 从mete-chain拉取对应的service_list let service_list = self.load_service_list().await?; @@ -450,13 +462,46 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { }); } - debug!( - "load device_config from meta: config={}", - device_config_str - ); + debug!("load device_config from meta: config={}", device_config_str); Ok(device_config_str) } +} + +#[async_trait] +impl DeviceConfigRepo for DeviceConfigMetaRepo { + fn get_type(&self) -> &'static str { + "meta" + } + + async fn fetch(&self) -> BuckyResult { + use rand::Rng; + + // Use a random retry interval + let mut retry_interval_secs: u64 = rand::thread_rng().gen_range(10, 60); + let mut retry_count = 0; + loop { + match self.fetch_inner().await { + Ok(ret) => break Ok(ret), + Err(e) => match e.code() { + BuckyErrorCode::HttpError => { + async_std::task::sleep(std::time::Duration::from_secs(retry_interval_secs)) + .await; + retry_interval_secs *= 2; + retry_count += 1; + + if retry_count > 3 { + break Err(e); + } + } + + _ => { + break Err(e); + } + }, + } + } + } async fn clear_cache(&self) { self.service_objects.clear_cache().await; diff --git a/src/service/ood-daemon/src/service/service_manager.rs b/src/service/ood-daemon/src/service/service_manager.rs index 4f656c614..2c88f76db 100644 --- a/src/service/ood-daemon/src/service/service_manager.rs +++ b/src/service/ood-daemon/src/service/service_manager.rs @@ -484,6 +484,7 @@ impl ServiceManager { } } } + debug!("sync all service packages complete!"); } async fn sync_service_package(service_info: &ServiceItem) -> BuckyResult<()> { From 34a231b8dcaaf9967a7ba42b74a31356018e0d67 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 20:34:04 +0800 Subject: [PATCH 144/553] Adjust the interval for checking for upgrades to 30 minutes --- src/service/ood-daemon/src/daemon/daemon.rs | 2 +- src/service/ood-daemon/src/main.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index 4c59ca60e..fb05c73ca 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -187,7 +187,7 @@ impl Daemon { } // 检查绑定状态 - let timer = task::sleep(Duration::from_secs(60 * 10)); + let timer = task::sleep(Duration::from_secs(60 * 30)); let (abort_handle, abort_registration) = AbortHandle::new_pair(); diff --git a/src/service/ood-daemon/src/main.rs b/src/service/ood-daemon/src/main.rs index 5ad479cd4..94856767f 100644 --- a/src/service/ood-daemon/src/main.rs +++ b/src/service/ood-daemon/src/main.rs @@ -1,4 +1,4 @@ -// #![windows_subsystem = "windows"] +#![windows_subsystem = "windows"] mod config; mod config_repo; @@ -22,9 +22,9 @@ const SERVICE_NAME: &str = ::cyfs_base::OOD_DAEMON_NAME; fn start_log() { cyfs_debug::CyfsLoggerBuilder::new_service(SERVICE_NAME) - .level("debug") + .level("info") .console("info") - .enable_bdt(Some("debug"), Some("debug")) + .enable_bdt(Some("info"), Some("info")) .build() .unwrap() .start(); From 0196d036cd7a922a40cf7bfe3c2bad75c89b59c2 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 12:52:44 +0800 Subject: [PATCH 145/553] Update nightly changelog --- CHANGELOG-nightly.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md index 527382d38..ec558d1e2 100644 --- a/CHANGELOG-nightly.md +++ b/CHANGELOG-nightly.md @@ -1,3 +1,23 @@ +## [1.0.0.722] -- 2023/2/24 +0d1eecc5 Add mechanism that trigger immediate update after system config changes +64f019fe Fix two log param errors +1776889e Add dynamic monitoring mechanism for system-config.toml +afb5c68c Add repeated loading supports to system-config.toml in ood-daemon +e81821d7 Fix two warning after package updated +8a2bba37 Switch meta repo to dynamic dependency on system config +1cf5799f Fix: pack script error +16eaf64c Fix: Missing app-manager lib.rs +de517952 Add app repo downloader for ood-installer +4eda0873 Add semver epoch check into ood-daemon +06717ad2 Add cache for meta config repo in ood-daemon +69f88233 Add meta client helper with object cache +0d5e5a69 Add service_version and preview relate supports into ood-daemon for better control of services update +7622e76a Add semver support into dec_app core object and with test cases +a976a6bf App-tool support change preview service version, pack script add preview version to service +b0e496bb Fix the panic that may be caused by check db in cyfs-noc +06201fbe Add api edition relate header to requestors +12d526f9 Add check mechanism to noc meta db in case of main table missing + ## [1.0.0.718] -- 2023/2/21 1b0cf118 Change sync services packages from parallel to serial 638848a2 Remove two spawn task using for cancel on timeout From 8cf1449da6a8d10e0f1b4d2346076e7011c370b6 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 15:43:40 +0800 Subject: [PATCH 146/553] Improve config with some comments --- src/tools/ood-installer/res/default/debug.toml | 3 +++ src/tools/ood-installer/res/synology/debug.toml | 3 +++ src/tools/ood-installer/res/vood/debug.toml | 3 +++ src/tools/ood-installer/src/system_config_gen.rs | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/tools/ood-installer/res/default/debug.toml b/src/tools/ood-installer/res/default/debug.toml index 9b42967de..45dda1079 100644 --- a/src/tools/ood-installer/res/default/debug.toml +++ b/src/tools/ood-installer/res/default/debug.toml @@ -1,6 +1,9 @@ [log.global] level = "info" console = "info" +#file = "off" +#file_max_size = 10485760 +#file_max_count = count [log.cyfs_bdt] level = "info" diff --git a/src/tools/ood-installer/res/synology/debug.toml b/src/tools/ood-installer/res/synology/debug.toml index 9b42967de..45dda1079 100644 --- a/src/tools/ood-installer/res/synology/debug.toml +++ b/src/tools/ood-installer/res/synology/debug.toml @@ -1,6 +1,9 @@ [log.global] level = "info" console = "info" +#file = "off" +#file_max_size = 10485760 +#file_max_count = count [log.cyfs_bdt] level = "info" diff --git a/src/tools/ood-installer/res/vood/debug.toml b/src/tools/ood-installer/res/vood/debug.toml index 94bbe6fbf..83acb1a57 100644 --- a/src/tools/ood-installer/res/vood/debug.toml +++ b/src/tools/ood-installer/res/vood/debug.toml @@ -1,6 +1,9 @@ [log.global] level = "info" console = "off" +#file = "off" +#file_max_size = 10485760 +#file_max_count = count [log.cyfs_bdt] level = "info" diff --git a/src/tools/ood-installer/src/system_config_gen.rs b/src/tools/ood-installer/src/system_config_gen.rs index 0f7824487..d02c3afa5 100644 --- a/src/tools/ood-installer/src/system_config_gen.rs +++ b/src/tools/ood-installer/src/system_config_gen.rs @@ -4,6 +4,9 @@ use cyfs_base::{BuckyError, BuckyResult}; const SYSTEM_CONFIG_TEMPLATE: &str = r#"[device] target = "${target}" config_desc = "${config_repo}" +#service_list_version = "nightly" +#service_version = "default" +#preview = false [[repository]] type = "${repo_type}" From fcf495a409753634259d52a58d657ddc2d76d7ea Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 16:18:03 +0800 Subject: [PATCH 147/553] Add system-config field to ood status --- src/service/ood-daemon/src/config/system_config.rs | 7 +++---- src/service/ood-daemon/src/status/service_status.rs | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 1f5341cc0..7ec69d578 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -55,14 +55,13 @@ impl SystemConfig { debug!("will load system-config file: {}", config_file.display()); - let node = self.load_as_json(&config_file).await?; + let node = Self::load_as_toml(&config_file)?; self.parse_config(node).await } - async fn load_as_json(&self, file_path: &Path) -> BuckyResult { - let content = async_std::fs::read_to_string(&file_path) - .await + pub fn load_as_toml(file_path: &Path) -> BuckyResult { + let content = std::fs::read_to_string(&file_path) .map_err(|e| { let msg = format!( "load system config to string error! file={}, {}", diff --git a/src/service/ood-daemon/src/status/service_status.rs b/src/service/ood-daemon/src/status/service_status.rs index e19b25b7f..b6dd37055 100644 --- a/src/service/ood-daemon/src/status/service_status.rs +++ b/src/service/ood-daemon/src/status/service_status.rs @@ -1,5 +1,5 @@ use crate::{SERVICE_MANAGER}; -use crate::config::{ServiceState, ServiceConfig, DEVICE_CONFIG_MANAGER}; +use crate::config::{ServiceState, ServiceConfig, DEVICE_CONFIG_MANAGER, SystemConfig, PATHS}; use crate::service::ServicePackageLocalState; use cyfs_base::bucky_time_now; @@ -21,6 +21,7 @@ pub struct OODServiceStatusItem { #[derive(Serialize)] pub struct OODDaemonStatus { last_update_time: u64, + system_config: Option, device_config: Vec, services: Vec, } @@ -29,6 +30,7 @@ impl Default for OODDaemonStatus { fn default() -> Self { Self { last_update_time: bucky_time_now(), + system_config: None, device_config: vec![], services: vec![], } @@ -76,10 +78,13 @@ impl OODDaemonStatusGenerator { Err(_) => vec![], }; + let system_config = SystemConfig::load_as_toml(&PATHS.system_config).ok(); + let services = SERVICE_MANAGER.collect_status(); OODDaemonStatus { last_update_time: bucky_time_now(), + system_config, device_config, services, } From 587aa128ff3aeebde2d1da653f1b83e940d02bfe Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:01:42 +0800 Subject: [PATCH 148/553] Fix app-manager leave defunct process when force kill app, kill app process when DApp dropped --- src/service/app-manager/src/app_controller.rs | 4 +-- src/service/app-manager/src/dapp.rs | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/service/app-manager/src/app_controller.rs b/src/service/app-manager/src/app_controller.rs index 1c3834fa3..0baf92a32 100644 --- a/src/service/app-manager/src/app_controller.rs +++ b/src/service/app-manager/src/app_controller.rs @@ -337,8 +337,8 @@ impl AppController { } } } else { - let reader = self.dapp_instance.read().unwrap(); - if let Some(dapp) = reader.get(app_id) { + let mut app_list = self.dapp_instance.write().unwrap(); + if let Some(dapp) = app_list.remove(app_id) { let result = dapp.stop().map_err(|e| { warn!("stop app directly failed, app:{}, err:{}", app_id, e); SubErrorCode::CommondFailed diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index f3bcb235f..012b5d26a 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -43,6 +43,16 @@ fn get_str(value: &Value, key: &str) -> BuckyResult { .to_owned()) } +impl Drop for DApp { + fn drop(&mut self) { + if let Some(mut child) = self.process.lock().unwrap().as_ref() { + warn!("dapp {} dropped when child process start! pid {}", &self.dec_id, child.id()); + child.kill(); + child.wait(); + } + } +} + impl DApp { pub fn load_from_app_id(app_id: &str) -> BuckyResult { let dapp = DApp::load_from(&get_app_dir(&app_id.to_string()))?; @@ -181,7 +191,6 @@ impl DApp { let mut command = Command::new(program); command.args(&args[1..]).current_dir(dir); if let Some(out) = stdout { - command.stdout(out); } #[cfg(target_os = "windows")] @@ -235,25 +244,22 @@ impl DApp { pub fn start(&self) -> BuckyResult { if !self.status()? { let child = DApp::run(&self.info.start, &self.work_dir, true, None)?; - + *self.process.lock().unwrap() = Some(child); // mark pid let id = child.id(); let lock_file = self.get_pid_file_path()?; let buf = format!("{}", id).into_bytes(); std::fs::write(lock_file, &buf).map_err(|e| { - error!( - "app[{}]{} write lock file failed! err {}", - self.dec_id, self.info.id, e - ); - BuckyError::from(BuckyErrorCode::ExecuteError) + let msg = format!("app[{}]{} write lock file failed! err {}", + self.dec_id, self.info.id, e); + error!("{}", &msg); + BuckyError::new(BuckyErrorCode::ExecuteError, msg) })?; info!( "start app:{} {} success! and write pid {:?}", self.dec_id, self.info.id, id ); - *self.process.lock().unwrap() = Some(child); - return Ok(true); } Ok(false) @@ -451,11 +457,11 @@ impl DApp { let pid = pid.unwrap(); info!( "stop app[{}] by inner cmd failed, try to force kill by pid {}", - &self.info.id, pid + &self.dec_id, pid ); #[cfg(windows)] { - Command::new("taskkill") + let mut child = Command::new("taskkill") .arg("/F") .arg("/T") .arg("/PID") @@ -465,10 +471,11 @@ impl DApp { error!("kill app:{} failed! err {}", pid, e); BuckyError::from(BuckyErrorCode::ExecuteError) })?; + let _ = child.wait(); } #[cfg(not(windows))] { - Command::new("kill") + let mut child = Command::new("kill") .arg("-9") .arg(&pid) .spawn() @@ -476,6 +483,7 @@ impl DApp { error!("kill app:{} failed! err {}", pid, e); BuckyError::from(BuckyErrorCode::ExecuteError) })?; + let _ = child.wait(); } let lock_file = self.get_pid_file_path()?; From c4081f9b0871e1d252fdb56d4dba805baab9ad56 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:02:06 +0800 Subject: [PATCH 149/553] Bump minor version to 1.1 --- scripts/pack.js | 2 +- src/component/cyfs-base/src/base/channel.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index 34432d425..d59ef46d2 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -78,7 +78,7 @@ function meta_url(channel) { } } -let version = `1.0.${version_from_channel(channel)}.${buildnumber}`; +let version = `1.1.${version_from_channel(channel)}.${buildnumber}`; let repo_path = process.env.FFS_SERVICE_REPO_DESC; if (!repo_path) { diff --git a/src/component/cyfs-base/src/base/channel.rs b/src/component/cyfs-base/src/base/channel.rs index b1abb388a..537e0556b 100644 --- a/src/component/cyfs-base/src/base/channel.rs +++ b/src/component/cyfs-base/src/base/channel.rs @@ -61,7 +61,7 @@ pub fn get_target() -> &'static str { fn get_version_impl() -> String { let channel_ver = get_channel().get_ver(); - format!("1.0.{}.{}-{} ({})", channel_ver, env!("VERSION"), get_channel(), env!("BUILDDATE")) + format!("1.1.{}.{}-{} ({})", channel_ver, env!("VERSION"), get_channel(), env!("BUILDDATE")) } fn get_channel_impl() -> CyfsChannel { From 25efae34ad3d9cbabde93c1750aafb56a8a87005 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 150/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index b892d402f..60531e1b7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1766,6 +1766,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1779,6 +1780,7 @@ dependencies = [ "semver 1.0.16", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1828,6 +1830,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.0" @@ -2179,6 +2240,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -3237,6 +3300,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.15" From ccce27245b2511655881315e333275339419bf31 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 151/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 1 + .../cyfs-lib/src/storage/remote_storage.rs | 12 ++ .../cyfs-perf/cyfs-perf-base/src/items.rs | 7 + .../cyfs-perf/cyfs-perf-client/Cargo.toml | 6 +- .../cyfs-perf/cyfs-perf-client/src/client.rs | 84 +++++----- .../cyfs-perf/cyfs-perf-client/src/config.rs | 13 ++ .../cyfs-perf-client/src/reporter.rs | 145 +++++++++++------- .../cyfs-perf/cyfs-perf-client/src/store.rs | 4 +- src/tests/cyfs-stack-test/src/case/perf.rs | 2 +- 9 files changed, 162 insertions(+), 112 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 60531e1b7..f09b84bc2 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2150,6 +2150,7 @@ dependencies = [ "android_logger", "async-std", "async-trait", + "chrono", "cyfs-base", "cyfs-core", "cyfs-debug", diff --git a/src/component/cyfs-lib/src/storage/remote_storage.rs b/src/component/cyfs-lib/src/storage/remote_storage.rs index 46200f2ee..20e16f389 100644 --- a/src/component/cyfs-lib/src/storage/remote_storage.rs +++ b/src/component/cyfs-lib/src/storage/remote_storage.rs @@ -1,3 +1,4 @@ +use cyfs_base::DeviceId; use super::collection::*; use super::remote_noc::*; use crate::stack::*; @@ -27,6 +28,17 @@ impl RemoteNOCStorage { NOCCollectionSync::new(id, remote_noc.into_noc()) } + pub fn new_noc_collection_sync_uni(id: &str, stack: &UniCyfsStackRef, device_id: &DeviceId) -> NOCCollectionSync + where + T: Default + CollectionCodec + Send + 'static, + { + let remote_noc = RemoteNamedObjectCache::new( + stack.non_service().clone(), + device_id, + ); + NOCCollectionSync::new(id, remote_noc.into_noc()) + } + pub fn new_noc_collection_rw_sync( id: &str, stack: &SharedCyfsStack, diff --git a/src/component/cyfs-perf/cyfs-perf-base/src/items.rs b/src/component/cyfs-perf/cyfs-perf-base/src/items.rs index 4eb54255f..2babb61b3 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/src/items.rs +++ b/src/component/cyfs-perf/cyfs-perf-base/src/items.rs @@ -4,6 +4,7 @@ use cyfs_lib::*; use serde::{Deserialize, Serialize}; use std::collections::{hash_map::Entry, HashMap}; +use std::fmt::{Display, Formatter}; // 统计所在的时间间隔 #[derive(Debug, Clone, Serialize, Deserialize)] @@ -12,6 +13,12 @@ pub struct PerfTimeRange { pub end: u64, } +impl Display for PerfTimeRange { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}-{}", self.begin, self.end) + } +} + impl Default for PerfTimeRange { fn default() -> Self { Self { diff --git a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml index 45bde7a0e..f9c167319 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml @@ -8,10 +8,7 @@ license = 'BSD-2-Clause' description = 'Rust cyfs-perf-client package' [dependencies] -log = { version = '0.4', features = [ - 'max_level_trace', - 'release_max_level_trace', -] } +log = { version = '0.4'} serde_json = '1.0' int-enum = '0.4' cyfs-perf-base = { path = '../cyfs-perf-base', version = '0.6' } @@ -25,6 +22,7 @@ async-std = { version = '1.11', features = ['unstable', 'attributes'] } rand = '0.7' sha2 = '0.8' async-trait = '0.1.53' +chrono = "0.4" [target.'cfg(target_os = "android")'.dependencies] jni = '0.19' diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs index 418859bd0..5d029c415 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs @@ -3,13 +3,13 @@ use crate::isolate::PerfIsolate; use crate::reporter::*; use crate::store::PerfStore; use cyfs_base::*; -use cyfs_core::*; use cyfs_debug::Mutex; use cyfs_lib::*; -use std::collections::{hash_map, HashMap}; +use std::collections::{HashMap}; use std::ops::Deref; use std::sync::Arc; +use std::time::Duration; // pub const PERF_DEC_ID_STR: &str = "5aSixgP8EPf6HkP54Qgybddhhsd1fgrkg7Atf2icJiiS"; @@ -17,12 +17,21 @@ pub struct PerfClientInner { id: String, version: String, dec_id: Option, - perf_server_config: PerfServerConfig, + perf_config: PerfConfig, - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, isolates: Mutex>, + + local_device: DeviceId, + owner: ObjectId +} + +pub struct PerfConfig { + pub reporter: PerfServerConfig, + pub save_to_file: bool, + pub report_interval: Duration } impl PerfClientInner { @@ -30,11 +39,11 @@ impl PerfClientInner { id: String, version: String, dec_id: Option, - perf_server_config: PerfServerConfig, - stack: SharedCyfsStack, + perf_config: PerfConfig, + stack: UniCyfsStackRef, + local_device: DeviceId, + owner: ObjectId ) -> Self { - let device_id = stack.local_device_id(); - let dec_name = match &dec_id { Some(id) => id.to_string(), None => "system".to_owned(), @@ -42,42 +51,44 @@ impl PerfClientInner { // 这里需要使用一个足够区分度的id,避免多个dec和内核共享协议栈情况下,同时使用PerfClient导致的冲突 // TODO version区别对待和,不同版本的数据是否可以合并 - let store_object_id = format!("{}-{}-{}-cyfs-perf-store", device_id, dec_name, id); + let store_object_id = format!("{}-{}-{}-cyfs-perf-store", &local_device, dec_name, id); - let store = PerfStore::new(store_object_id, &stack); + let store = PerfStore::new(store_object_id, &stack, &local_device); Self { id, version, dec_id, - perf_server_config, + perf_config, cyfs_stack: stack, store, isolates: Mutex::new(HashMap::new()), + local_device, + owner } } pub(crate) async fn start(&self) -> BuckyResult<()> { - let req = UtilGetZoneOutputRequest::new(None, None); - let resp = self.cyfs_stack.util().get_zone(req).await?; - let people_id = resp.zone.owner().to_owned(); - if let Err(e) = self.store.start().await { // FIXME 启动失败如何处理?一般只有从noc加载失败才会出问题 error!("perf client start error! {}", e); } - let perf_server = PerfServerLoader::load_perf_server(self.perf_server_config.clone()).await; + let save_to_local = self.perf_config.reporter.is_none(); + let perf_server = PerfServerLoader::load_perf_server(self.perf_config.reporter.clone()).await; let reporter = PerfReporter::new( self.id.clone(), self.version.clone(), - resp.device_id, - people_id, + self.local_device.clone(), + self.owner.clone(), self.dec_id.clone(), perf_server, self.cyfs_stack.clone(), self.store.clone(), + save_to_local, + self.perf_config.save_to_file, + self.perf_config.report_interval, ); reporter.start(); @@ -128,32 +139,12 @@ impl PerfClientInner { Ok(()) } - pub fn is_isolates_exists(&self, id: &str) -> bool { - self.isolates.lock().unwrap().contains_key(id) - } - - pub fn new_isolate(&self, id: &str) -> PerfIsolate { + pub fn get_isolate(&self, id: &str) -> PerfIsolate { let mut isolates = self.isolates.lock().unwrap(); - match isolates.entry(id.to_owned()) { - hash_map::Entry::Vacant(v) => { - log::info!("new isolate module: id={}", id); - - let isolate = PerfIsolate::new(id); - let temp_isolate = isolate.clone(); - v.insert(isolate); - temp_isolate.clone() - } - hash_map::Entry::Occupied(o) => { - let msg = format!("isolate module already exists: id={}", id); - log::error!("{}", msg); - - o.get().clone() - } - } - } - - pub fn get_isolate(&self, id: &str) -> Option { - self.isolates.lock().unwrap().get(id).map(|v| v.clone()) + isolates.entry(id.to_owned()).or_insert_with(|| { + log::info!("create isolate module: id={}", id); + PerfIsolate::new(id) + }).clone() } } @@ -165,10 +156,11 @@ impl PerfClient { id: String, version: String, dec_id: Option, - perf_server_config: PerfServerConfig, - stack: SharedCyfsStack, + perf_config: PerfConfig, + stack: UniCyfsStackRef, + local_device: DeviceId, owner: ObjectId ) -> Self { - let ret = PerfClientInner::new(id, version, dec_id, perf_server_config, stack); + let ret = PerfClientInner::new(id, version, dec_id, perf_config, stack, local_device, owner); Self(Arc::new(ret)) } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/config.rs b/src/component/cyfs-perf/cyfs-perf-client/src/config.rs index fe6b82a6e..bd5b2376d 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/config.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/config.rs @@ -18,6 +18,18 @@ pub enum PerfServerConfig { // 系统默认值,优先使用本地配置,其次使用链上的值 Default, + + // 只存储到本地,不上报到任何Server + None +} + +impl PerfServerConfig { + pub fn is_none(&self) -> bool { + match self { + PerfServerConfig::None => true, + _ => false + } + } } impl Default for PerfServerConfig { @@ -33,6 +45,7 @@ impl PerfServerLoader { PerfServerConfig::OOD => None, PerfServerConfig::Specified(device_id) => Some(device_id), PerfServerConfig::Default => Self::load_default_perf_server().await, + PerfServerConfig::None => None } } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index aff5d3c23..8a7592b55 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -1,13 +1,17 @@ +use std::path::{PathBuf}; use super::store::PerfStore; use cyfs_base::*; use cyfs_lib::*; use cyfs_perf_base::*; use std::sync::Arc; +use std::time::Duration; +use chrono::Local; +use crate::CYFS_PERF_SERVICE_NAME; // 用以实现统计项的上报 struct PerfReporterInner { - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, // PerfObject的依赖信息 @@ -19,6 +23,11 @@ struct PerfReporterInner { // 上报的目标 perf_server: Option, + save_to_local: bool, + save_path: Option, + + // 上报间隔 + report_interval: Duration, } impl PerfReporterInner { @@ -29,9 +38,31 @@ impl PerfReporterInner { people_id: ObjectId, dec_id: Option, perf_server: Option, - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, + save_to_local: bool, + save_to_file: bool, + report_interval: Duration ) -> Self { + let save_path = if save_to_file { + let path = if let Some(dec_id) = dec_id { + cyfs_util::get_app_data_dir(&dec_id.to_string()).join("stat").join(&id) + } else { + cyfs_util::get_service_data_dir(CYFS_PERF_SERVICE_NAME).join(&id) + }; + if !path.exists() { + if let Err(e) = std::fs::create_dir_all(&path) { + error!("create dir {} err {}, disable stat to file", path.display(), e); + None + } else { + Some(path) + } + } else { + Some(path) + } + } else { + None + }; Self { id, version, @@ -41,12 +72,15 @@ impl PerfReporterInner { perf_server, cyfs_stack, store, + save_to_local, + save_path, + report_interval } } pub async fn run(&self) { loop { - async_std::task::sleep(std::time::Duration::from_secs(60 * 10)).await; + async_std::task::sleep(self.report_interval).await; // 这里先按照等间隔均匀上报,忽略上报的结果 let _ = self.report_once().await; @@ -75,6 +109,16 @@ impl PerfReporterInner { return Ok(()); } + if let Some(path) = &self.save_path { + let begin: chrono::DateTime = bucky_time_to_system_time(data.time_range.begin).into(); + let end: chrono::DateTime = bucky_time_to_system_time(data.time_range.end).into(); + let pretty_format = "%Y%m%d_%H%M%S"; + let file_name = format!("{}-{}.stat", begin.format(pretty_format), end.format(pretty_format)); + if let Ok(file) = std::fs::File::create(path.join(file_name)) { + serde_json::to_writer_pretty(&file, &data); + } + } + debug!( "will report perf data: id={}, version={}, data={:?}", self.id, self.version, data @@ -90,17 +134,12 @@ impl PerfReporterInner { ); let perf_id = perf_obj.perf_id(); - info!( - "will report perf: id={}, version={}, target={:?}, perf_object={}", - self.id, self.version, self.perf_server, perf_id, - ); + info!("will report perf: id={}, version={}, target={:?}, perf_object={}", + self.id, self.version, self.perf_server, perf_id); - let perf_server = self - .perf_server - .as_ref() - .map(|id| id.object_id().to_owned()); + let perf_server = self.perf_server.as_ref().map(|id| id.object_id().to_owned()); - match self.put_object(&perf_obj, perf_server, 0).await { + match self.put_object(&perf_obj, perf_server, 0, self.save_to_local).await { Ok(_) => { info!( "report perf success! id={}, target={:?}, perf_object={}", @@ -119,18 +158,13 @@ impl PerfReporterInner { } // NON_REQUEST_FLAG_SIGN_BY_DEVICE | NON_REQUEST_FLAG_SIGN_SET_DESC | NON_REQUEST_FLAG_SIGN_SET_BODY - pub async fn put_object( + pub async fn put_object( &self, - obj: &N, + obj: &Perf, target: Option, sign_flags: u32, + save_to_local: bool ) -> BuckyResult<()> - where - D: ObjectType, - T: RawEncode, - N: RawConvertTo, - N: NamedObject, - ::ContentType: BodyContent, { let raw; let object_id = obj.desc().calculate_id(); @@ -139,11 +173,7 @@ impl PerfReporterInner { let req = CryptoSignObjectRequest::new(object_id.clone(), object_raw, sign_flags); // 先给Obj签名, 用Client的Device - let resp = self - .cyfs_stack - .crypto() - .sign_object(req) - .await + let resp = self.cyfs_stack.crypto_service().sign_object(req).await .map_err(|e| { error!("{} sign failed, err {}", &object_id, e); e @@ -154,45 +184,36 @@ impl PerfReporterInner { } // 把obj再put出去 - match self - .cyfs_stack - .non_service() - .put_object(NONPutObjectOutputRequest { - common: NONOutputRequestCommon { - req_path: None, - source: None, - target, - dec_id: obj.desc().dec_id().clone(), - flags: 0, - level: NONAPILevel::Router, - }, - object: NONObjectInfo { - object_id: object_id.clone(), - object_raw: raw, - object: None, - }, - access: None, - }) - .await - { + let mut req = NONPutObjectOutputRequest::new( + if save_to_local { NONAPILevel::NOC } else { NONAPILevel::Router }, + object_id.clone(), raw); + req.common.target = if save_to_local { None } else { target }; + req.common.dec_id = obj.desc().dec_id().clone(); + let str_target = if save_to_local { "local".to_owned() } else {target.map_or("ood".to_owned(), |id| id.to_string())}; + match self.cyfs_stack.non_service().put_object(req).await { Ok(_) => { - info!( - "### put perf obj [{}] to {} success!", - object_id, - target.map_or("ood".to_owned(), |id| id.to_string()) - ); + info!("### put perf obj {} to {} success!", &object_id, str_target); Ok(()) } Err(e) => { - error!( - "### put perf obj [{}] to {} failed! {}", - object_id, - target.map_or("ood".to_owned(), |id| id.to_string()), - e - ); + error!("### put perf obj [{}] to {} failed! {}", &object_id, str_target, e); Err(e) } - } + }?; + + // 存到root_state + let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); + req.access = access; + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + let resp = self.cyfs_stack.root_state().create_op_env(req).await?; + let path_env = PathOpEnvStub::new(resp, self.target.clone(), self.target_dec_id.clone()); + let key = obj.get_time_range().to_string(); + path_env.set_with_key("/stat", key, &object_id, None, true).await?; + path_env.commit().await?; + + Ok(()) } } @@ -207,8 +228,11 @@ impl PerfReporter { people_id: ObjectId, dec_id: Option, perf_server: Option, - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, + save_to_local: bool, + save_to_file: bool, + report_interval: Duration, ) -> Self { let ret = PerfReporterInner::new( id, @@ -219,6 +243,9 @@ impl PerfReporter { perf_server, cyfs_stack, store, + save_to_local, + save_to_file, + report_interval ); Self(Arc::new(ret)) } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs index 965693649..3359ccd3d 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs @@ -19,8 +19,8 @@ pub(crate) struct PerfStore { } impl PerfStore { - pub fn new(id: String, stack: &SharedCyfsStack) -> Self { - let cache = RemoteNOCStorage::new_noc_collection_sync(&id, stack); + pub fn new(id: String, stack: &UniCyfsStackRef, device_id: &DeviceId) -> Self { + let cache = RemoteNOCStorage::new_noc_collection_sync_uni(&id, stack, device_id); let locked = Arc::new(AtomicBool::new(false)); Self { cache, locked } } diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index 978e205c4..f79043ee6 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -28,7 +28,7 @@ pub async fn test() { let ret = perf.start().await; assert!(ret.is_ok()); - let isolate = perf.new_isolate("main"); + let isolate = perf.get_isolate("main"); test_flush(perf.clone()).await; test_request(isolate.clone()).await; test_acc(isolate.clone()).await; From c2bf2a522a788b8cc232a5086bf7662d113db0fa Mon Sep 17 00:00:00 2001 From: liqirun Date: Fri, 24 Feb 2023 20:12:13 +0800 Subject: [PATCH 152/553] Fix stream & NDN send data bugs --- src/component/cyfs-bdt/examples/pacing.rs | 175 ++++++++++++++++++ src/component/cyfs-bdt/src/cc/bbr.rs | 46 ++--- src/component/cyfs-bdt/src/cc/cc.rs | 24 ++- src/component/cyfs-bdt/src/cc/cc_impl.rs | 6 +- src/component/cyfs-bdt/src/cc/ledbat.rs | 25 ++- src/component/cyfs-bdt/src/cc/mod.rs | 2 + src/component/cyfs-bdt/src/cc/pacing.rs | 93 ++++++++++ src/component/cyfs-bdt/src/datagram/tunnel.rs | 11 +- src/component/cyfs-bdt/src/debug/stub.rs | 1 - src/component/cyfs-bdt/src/lib.rs | 2 +- .../cyfs-bdt/src/ndn/channel/tunnel/udp.rs | 45 ++++- src/component/cyfs-bdt/src/protocol/v0.rs | 18 ++ src/component/cyfs-bdt/src/stack.rs | 8 +- .../cyfs-bdt/src/stream/package/stream.rs | 100 +++++++++- .../cyfs-bdt/src/stream/package/write.rs | 59 ++++-- .../cyfs-bdt/src/tunnel/container.rs | 3 +- src/component/cyfs-bdt/src/tunnel/tcp.rs | 5 +- src/component/cyfs-bdt/src/tunnel/tunnel.rs | 2 +- src/component/cyfs-bdt/src/tunnel/udp.rs | 6 +- 19 files changed, 554 insertions(+), 77 deletions(-) create mode 100644 src/component/cyfs-bdt/examples/pacing.rs create mode 100644 src/component/cyfs-bdt/src/cc/pacing.rs diff --git a/src/component/cyfs-bdt/examples/pacing.rs b/src/component/cyfs-bdt/examples/pacing.rs new file mode 100644 index 000000000..8b7af524d --- /dev/null +++ b/src/component/cyfs-bdt/examples/pacing.rs @@ -0,0 +1,175 @@ +use std::{ + sync::{atomic::{AtomicU64, Ordering, AtomicBool}, Mutex, Arc}, + time::{Instant, Duration}, + collections::LinkedList, + thread, +}; + +use cyfs_base::*; +use cyfs_bdt::{cc::pacing}; + +struct PacePackage { + send_time: Instant, + package_size: u64, +} +struct PackageStreamMockImpl { + pacer: Mutex, + package_queue: Arc>>, + sent_bytes: AtomicU64, + finish: AtomicBool, + end: Mutex>, + thread: Mutex>>, +} + +#[derive(Clone)] +pub struct PackageStreamMock(Arc); + +fn mss() -> usize { + 1472 +} + +impl PackageStreamMock { + pub fn new(rate: u64) -> BuckyResult { + let mut pacer = pacing::Pacer::new(true, mss()*4, mss()); + pacer.update(rate); + + let stream = Self(Arc::new(PackageStreamMockImpl { + pacer: Mutex::new(pacer), + package_queue: Arc::new(Mutex::new(Default::default())), + sent_bytes: AtomicU64::new(0), + finish: AtomicBool::new(false), + end: Mutex::new(None), + thread: Mutex::new(None), + })); + + Ok(stream) + } + + pub fn send_packages(&self, packages: Vec) -> Result<(), BuckyError> { + let mut pacer = self.0.pacer.lock().unwrap(); + let now = Instant::now(); + let mut sent_bytes = 0; + for package in packages { + if let Some(next_time) = pacer.send(package as usize, now) { + self.package_delay(package, next_time); + } else { + sent_bytes += package; + } + } + self.0.sent_bytes.fetch_add(sent_bytes, Ordering::SeqCst); + + Ok(()) + } + + pub fn package_delay(&self, package_size: u64, send_time: Instant) { + let mut package_queue = self.0.package_queue.lock().unwrap(); + package_queue.push_back(PacePackage { + send_time, + package_size, + }); + + if package_queue.len() == 1 { + let mut delay = Instant::now() - send_time; + let package_queue = self.0.package_queue.clone(); + let stream = self.clone(); + let t = thread::spawn(move || { + loop { + thread::sleep(delay); + + let now = Instant::now(); + { + let mut packages = package_queue.lock().unwrap(); + let mut n = 0; + + for (_, package) in packages.iter().enumerate() { + if package.send_time > now { + delay = package.send_time.checked_duration_since(now).unwrap(); + break ; + } + n += 1; + } + + let mut sent_bytes = 0; + while n > 0 { + if let Some(package) = packages.pop_front() { + sent_bytes += package.package_size; + } + n -= 1; + } + stream.0.sent_bytes.fetch_add(sent_bytes, Ordering::SeqCst); + + if packages.len() == 0 { + if stream.0.finish.load(Ordering::SeqCst) { + let mut end = stream.0.end.lock().unwrap(); + *end = Some(Instant::now()); + } + return true; + } + } + } + }); + + let mut thread = self.0.thread.lock().unwrap(); + *thread = Some(t); + } + } +} + +fn packages_gen(n: usize) -> Vec { + let mut packages = vec![0u64]; + + let mut n = n; + loop { + if n == 0 { + break; + } + n -= 1; + + packages.push(mss() as u64); + } + + packages +} + +fn pacing_test(data_size: usize, rate: u64) { + println!("data_size={} | {} MB, rate={} | {} KB/s", data_size, data_size/1024/1024, rate, rate/1024); + + let n = 1000; + + let stream = PackageStreamMock::new(rate).unwrap(); + + let mut num = (data_size / mss() + 1) / n + 1; + + let start = Instant::now(); + loop { + let _ = stream.send_packages(packages_gen(n)); + std::thread::sleep(Duration::from_millis(20)); + + num -= 1; + if num == 0 { + stream.0.finish.store(true, Ordering::SeqCst); + break ; + } + } + + { + let t = stream.0.thread.lock().unwrap().take(); + if let Some(thread) = t { + let _ = thread.join(); + } + } + + let end = (*stream.0.end.lock().unwrap()).unwrap(); + let cost = end.checked_duration_since(start).unwrap(); + let sent_bytes = stream.0.sent_bytes.load(Ordering::SeqCst); + + println!("cost={:?} sent_bytes={} rate={:.1} KB/s", + cost, sent_bytes, sent_bytes as f64 / 1024.0 / cost.as_secs_f64()); +} + +#[async_std::main] +async fn main() { + pacing_test(1024*1024*30, 1024*1024*3); + pacing_test(1024*1024*30, 1024*1024*7); + pacing_test(1024*1024*50, 1024*1024*9); +} \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/cc/bbr.rs b/src/component/cyfs-bdt/src/cc/bbr.rs index 9b560a170..761c85548 100644 --- a/src/component/cyfs-bdt/src/cc/bbr.rs +++ b/src/component/cyfs-bdt/src/cc/bbr.rs @@ -234,7 +234,7 @@ impl Default for Config { fn default() -> Self { Self { min_cwnd: 2, - init_cwnd: 200, + init_cwnd: 10, probe_rtt_time: Duration::from_millis(200), probe_rtt_based_on_bdp: true, drain_to_target: true, @@ -648,30 +648,32 @@ impl Bbr { impl CcImpl for Bbr { - fn cwnd(&self) -> u64 { - let cwnd_rate = (self.pacing_rate as f64) / 1000.0; + fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64) { + self.max_sent_packet_number = last_packet_number; + self.max_bandwidth.on_sent(now, bytes); + } - if self.is_at_full_bandwidth && cwnd_rate > 0.0 { - (cwnd_rate * (self.min_rtt.as_millis() as f64)) as u64 + fn cwnd(&self) -> u64 { + if self.mode == Mode::ProbeRtt { + self.get_probe_rtt_cwnd() + } else if self.recovery_state.in_recovery() + && self.mode != Mode::Startup { + self.cwnd.min(self.recovery_window) } else { - if self.mode == Mode::ProbeRtt { - self.get_probe_rtt_cwnd() - } else if self.recovery_state.in_recovery() - && self.mode != Mode::Startup { - self.cwnd.min(self.recovery_window) - } else { - self.cwnd - } + self.cwnd } } - fn on_estimate(&mut self, rtt: Duration, _rto: Duration, _delay: Duration) { - self.rtt = rtt; + fn on_estimate(&mut self, rtt: Duration, _rto: Duration, _delay: Duration, app_limited: bool) { + let now = bucky_time_now(); + + if self.is_min_rtt_expired(now, app_limited) || self.min_rtt > rtt { + self.min_rtt = rtt; + } } - fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp) { //ret cwnd + fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp, app_limited: bool) { //ret cwnd let now = bucky_time_now(); - let app_limited = false; self.max_bandwidth.on_ack( now, @@ -682,10 +684,6 @@ impl CcImpl for Bbr { ); self.acked_bytes += ack; - if self.is_min_rtt_expired(now, app_limited) || self.min_rtt > self.rtt { - self.min_rtt = self.rtt; - } - let ack_in_wnd = self.max_bandwidth.bytes_acked_this_window(); let excess_acked = self.ack_aggregation.update_ack_aggregation_bytes( ack_in_wnd, @@ -740,9 +738,13 @@ impl CcImpl for Bbr { fn on_no_resp(&mut self, rto: Duration, lost: u64) -> Duration { self.loss_state.lost_bytes += lost; - rto + rto * 2 } fn on_time_escape(&mut self, _: Timestamp) { } + + fn rate(&self) -> u64 { + self.max_bandwidth.get_estimate() + } } diff --git a/src/component/cyfs-bdt/src/cc/cc.rs b/src/component/cyfs-bdt/src/cc/cc.rs index 6cf1e22bd..b22c6a974 100644 --- a/src/component/cyfs-bdt/src/cc/cc.rs +++ b/src/component/cyfs-bdt/src/cc/cc.rs @@ -16,6 +16,7 @@ struct EstimateRtt { mdev_max: i64, //maximal m_dev for the last rtt period rttvar: i64, //smoothed m_dev_max // rtt_seq: i64, //sequence number to update rtt_var + min_rtt: i64, } impl EstimateRtt { @@ -26,6 +27,7 @@ impl EstimateRtt { mdev_max: 0, rttvar: 0, // rtt_seq: 0, + min_rtt: 0, } } @@ -35,6 +37,11 @@ impl EstimateRtt { rtt = 1; } + if self.min_rtt == 0 || + self.min_rtt > rtt { + self.min_rtt = rtt; + } + if self.srtt != 0 { rtt -= self.srtt / 8; self.srtt += rtt; @@ -111,6 +118,10 @@ impl CongestionControl { } } + pub fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64) { + self.cc.on_sent(now, bytes, last_packet_number); + } + pub fn cwnd(&self) -> u64 { self.cc.cwnd() } @@ -123,19 +134,20 @@ impl CongestionControl { self.rtt } - pub fn on_estimate(&mut self, est_rtt: Duration, est_delay: Duration) { + pub fn on_estimate(&mut self, est_rtt: Duration, est_delay: Duration, app_limited: bool) { let (rtt, rto) = self.est_rtt.update(&self.config, est_rtt); self.rto = rto; self.rtt = rtt; - self.cc.on_estimate(rtt, rto, est_delay); + self.cc.on_estimate(Duration::from_micros(self.est_rtt.min_rtt as u64), rto, est_delay, app_limited); } pub fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, - sent_time: Timestamp) { - self.cc.on_ack(flight, ack, largest_packet_num_acked, sent_time) + sent_time: Timestamp, + app_limited: bool) { + self.cc.on_ack(flight, ack, largest_packet_num_acked, sent_time, app_limited) } pub fn on_loss(&mut self, lost: u64) { @@ -150,4 +162,8 @@ impl CongestionControl { pub fn on_time_escape(&mut self, now: Timestamp) { self.cc.on_time_escape(now) } + + pub fn rate(&self) -> u64 { + self.cc.rate() + } } \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/cc/cc_impl.rs b/src/component/cyfs-bdt/src/cc/cc_impl.rs index f538c014d..fd6cc01e5 100644 --- a/src/component/cyfs-bdt/src/cc/cc_impl.rs +++ b/src/component/cyfs-bdt/src/cc/cc_impl.rs @@ -4,9 +4,11 @@ use crate::{ }; pub trait CcImpl: Send { + fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64); + fn rate(&self) -> u64; fn cwnd(&self) -> u64; - fn on_estimate(&mut self, rtt: Duration, rto: Duration, delay: Duration); - fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp); + fn on_estimate(&mut self, rtt: Duration, rto: Duration, delay: Duration, app_limited: bool); + fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp, app_limited: bool); fn on_loss(&mut self, lost: u64); fn on_no_resp(&mut self, rto: Duration, lost: u64) -> Duration; fn on_time_escape(&mut self, now: Timestamp); diff --git a/src/component/cyfs-bdt/src/cc/ledbat.rs b/src/component/cyfs-bdt/src/cc/ledbat.rs index 4a8b66e99..1b367e8ae 100644 --- a/src/component/cyfs-bdt/src/cc/ledbat.rs +++ b/src/component/cyfs-bdt/src/cc/ledbat.rs @@ -16,6 +16,19 @@ pub struct Config { pub history_roll_interval: Duration } +impl Default for Config { + fn default() -> Self { + Self { + target_delay: Duration::from_millis(100), + min_cwnd: 2, + max_cwnd_inc: 8, + cwnd_gain: 1, + history_count: 10, + history_roll_interval: Duration::from_secs(60), + } + } +} + struct EstimateDelay { last_roll: Timestamp, base_delay: LinkedList, @@ -111,11 +124,14 @@ impl Ledbat { impl CcImpl for Ledbat { + fn on_sent(&mut self, _: Timestamp, _: u64, _: u64) { + } + fn cwnd(&self) -> u64 { self.cwnd } - fn on_estimate(&mut self, _rtt: Duration, _rto: Duration, delay: Duration) { + fn on_estimate(&mut self, _rtt: Duration, _rto: Duration, delay: Duration, _app_limited: bool) { self.est_delay.update(delay.as_micros() as i64); } @@ -124,7 +140,8 @@ impl CcImpl for Ledbat { _flight: u64, ack: u64, _largest_packet_num_acked: Option, - _sent_time: Timestamp + _sent_time: Timestamp, + _app_limited: bool ) { let cwnd = self.cwnd(); let cur_delay = self.est_delay.current_delay(); @@ -153,5 +170,9 @@ impl CcImpl for Ledbat { fn on_time_escape(&mut self, now: Timestamp) { self.est_delay.check_roll(&self.config, now); } + + fn rate(&self) -> u64 { + 0 + } } diff --git a/src/component/cyfs-bdt/src/cc/mod.rs b/src/component/cyfs-bdt/src/cc/mod.rs index c6006a10b..33069bdc9 100644 --- a/src/component/cyfs-bdt/src/cc/mod.rs +++ b/src/component/cyfs-bdt/src/cc/mod.rs @@ -1,6 +1,8 @@ mod cc_impl; mod cc; + pub mod ledbat; pub mod bbr; +pub mod pacing; pub use cc::*; diff --git a/src/component/cyfs-bdt/src/cc/pacing.rs b/src/component/cyfs-bdt/src/cc/pacing.rs new file mode 100644 index 000000000..73d217bf6 --- /dev/null +++ b/src/component/cyfs-bdt/src/cc/pacing.rs @@ -0,0 +1,93 @@ +use std::time::{Instant, Duration}; + +#[derive(Debug)] +pub struct Pacer { + capacity: usize, + used: usize, + rate: u64, + last_update: Instant, + next_time: Instant, + mss: usize, + last_packet_size: Option, + tick: Duration, + enable: bool, +} + +impl Pacer { + pub fn new(enable: bool, capacity: usize, mss: usize) -> Self { + let capacity = capacity / mss * mss; + + Pacer { + capacity, + used: 0, + rate: 0, + last_update: Instant::now(), + next_time: Instant::now(), + mss, + last_packet_size: None, + tick: Duration::ZERO, + enable, + } + } + + pub fn update(&mut self, rate: u64) { + if self.rate != rate { + self.rate = rate; + } + } + + pub fn reset(&mut self, now: Instant) { + self.used = 0; + self.last_update = now; + self.next_time = self.next_time.max(now); + self.last_packet_size = None; + self.tick = Duration::ZERO; + } + + pub fn send(&mut self, packet_size: usize, now: Instant) -> Option { + if !self.enable { + return None; + } + if self.rate == 0 { + self.reset(now); + + return None; + } + + if !self.tick.is_zero() { + self.next_time = self.next_time.max(now) + self.tick; + self.tick = Duration::ZERO; + } + + let interval = Duration::from_secs_f64(self.capacity as f64 / self.rate as f64); + + let elapsed = now.saturating_duration_since(self.last_update); + + if elapsed > interval { + self.reset(now); + } + + self.used += packet_size; + + let same_size = if let Some(last_packet_size) = self.last_packet_size { + last_packet_size == packet_size + } else { + true + }; + + self.last_packet_size = Some(packet_size); + + if self.used >= self.capacity || !same_size { + self.tick = Duration::from_secs_f64(self.used as f64 / self.rate as f64); + self.used = 0; + self.last_update = now; + self.last_packet_size = None; + }; + + if self.next_time <= now { + None + } else { + Some(self.next_time) + } + } +} diff --git a/src/component/cyfs-bdt/src/datagram/tunnel.rs b/src/component/cyfs-bdt/src/datagram/tunnel.rs index d725dc783..52406a3a7 100644 --- a/src/component/cyfs-bdt/src/datagram/tunnel.rs +++ b/src/component/cyfs-bdt/src/datagram/tunnel.rs @@ -340,12 +340,19 @@ impl DatagramTunnel { vport: u16, ) -> Result<(), std::io::Error> { let mtu = MTU; - let datagram = self.build_datagram(buf, options, remote, vport, None); - let fragment_len = datagram.fragment_len(mtu, options.plaintext); + let mut datagram = self.build_datagram(buf, options, remote, vport, None); + let mut fragment_len = datagram.fragment_len(mtu, options.plaintext); if fragment_len == 0 { self.send_datagram(datagram, remote, options.plaintext) } else { + if options.sequence.is_none() { + let seq = self.0.sequence.generate(); + options.sequence = Some(seq); + datagram.sequence = Some(seq); + fragment_len = datagram.fragment_len(mtu, options.plaintext); + } + let count = (buf.len() as f64 / fragment_len as f64).ceil() as u8; let mut start = 0; let mut end = fragment_len; diff --git a/src/component/cyfs-bdt/src/debug/stub.rs b/src/component/cyfs-bdt/src/debug/stub.rs index b6315c236..8c7289566 100644 --- a/src/component/cyfs-bdt/src/debug/stub.rs +++ b/src/component/cyfs-bdt/src/debug/stub.rs @@ -533,7 +533,6 @@ async fn watchdog_download_finished(task: Box, timeout: u32) - NdnTaskState::Finished => { break Ok(()); }, - NdnTaskState::Running => { if task.cur_speed() > 0 { i = 0; diff --git a/src/component/cyfs-bdt/src/lib.rs b/src/component/cyfs-bdt/src/lib.rs index 86491ce43..273b0a139 100644 --- a/src/component/cyfs-bdt/src/lib.rs +++ b/src/component/cyfs-bdt/src/lib.rs @@ -9,7 +9,7 @@ mod finder; pub mod sn; pub mod tunnel; pub mod pn; -mod cc; +pub mod cc; mod stream; mod datagram; mod dht; diff --git a/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs b/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs index ffa3bee6e..3c98312da 100644 --- a/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs +++ b/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs @@ -1,8 +1,8 @@ use log::*; use std::{ collections::{LinkedList}, - time::{Duration}, - cell::RefCell, + time::{Duration, Instant}, + cell::RefCell, sync::Mutex }; use async_std::{ @@ -70,6 +70,11 @@ struct RespEstimateStub { recved: u64, } +struct PacePackage { + send_time: Instant, + data: Vec, +} + struct TunnelImpl { config: channel::Config, raw_tunnel: RawTunnel, @@ -77,7 +82,8 @@ struct TunnelImpl { active_timestamp: Timestamp, cc: Mutex, resp_estimate: Mutex, - uploaders: Uploaders + uploaders: Uploaders, + package_queue: Arc>>, } #[derive(Clone)] @@ -105,7 +111,8 @@ impl UdpTunnel { seq: TempSeq::default(), recved: 0 }), - uploaders: Uploaders::new() + uploaders: Uploaders::new(), + package_queue: Arc::new(Mutex::new(Default::default())), })) } @@ -131,6 +138,8 @@ impl UdpTunnel { let mut pre_buf_index: Option = None; let mut sent = 0; let tunnel = &self.0.raw_tunnel; + let mut send_bytes = 0; + let mut last_est_seq = TempSeq::default(); for _ in 0..piece_count { let mut buf_index = if let Some(bi) = &pre_buf_index { if bi.index == 0 { @@ -149,7 +158,9 @@ impl UdpTunnel { buf_index.len = piece_len; if pre_buf_index.is_some() { std::mem::swap(pre_buf_index.as_mut().unwrap(), &mut buf_index); - let _ = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]); + if let Ok(size) = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]) { + send_bytes += size; + } } else { pre_buf_index = Some(buf_index); } @@ -172,7 +183,16 @@ impl UdpTunnel { }; debug!("{} send estimate sequence:{:?} sent:{}", self, est_seq, sent); PieceData::reset_estimate(&mut buffers[buf_index.index][tunnel.raw_data_header_len()..], est_seq); - let _ = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]); + last_est_seq = est_seq; + + if let Ok(size) = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]) { + send_bytes += size; + } + } + + { + let mut cc = self.0.cc.lock().unwrap(); + cc.cc.on_sent(bucky_time_now(), send_bytes as u64, last_est_seq.value() as u64); } }) }); @@ -231,7 +251,8 @@ impl ChannelTunnel for UdpTunnel { self, est_seq ); - let _ = tunnel.send_raw_data(&mut buffer[..]); + if let Ok(_) = tunnel.send_raw_data(&mut buffer[..]) { + } } } else { let mut est_stub = self.0.resp_estimate.lock().unwrap(); @@ -252,7 +273,7 @@ impl ChannelTunnel for UdpTunnel { let rtt = Duration::from_micros(bucky_time_now() - stub.send_time); let delay = rtt / 2; - cc.cc.on_estimate(rtt, delay); + cc.cc.on_estimate(rtt, delay, false); debug!("{} estimate rtt:{:?} delay:{:?} rto:{:?}", self, rtt, delay, cc.cc.rto()); est_index = Some(cc.est_stubs.len() - 1 - index); @@ -265,8 +286,10 @@ impl ChannelTunnel for UdpTunnel { let mut resp_count = 0; let est_stubs = cc.est_stubs.split_off(est_index + 1); + let mut send_time = 0; for stub in &cc.est_stubs { resp_count += stub.sent; + send_time = stub.send_time; } cc.est_stubs = est_stubs; @@ -276,11 +299,13 @@ impl ChannelTunnel for UdpTunnel { debug!("{} cc on ack on_air:{}, ack:{}", self, on_air, resp_count); cc.no_resp_counter = 0; cc.break_counter = 0; + cc.cc.on_ack( (on_air * PieceData::max_payload()) as u64, (resp_count * PieceData::max_payload()) as u64, - None, - bucky_time_now()); + Some(est_index as u64), + send_time, + false); } Ok(()) diff --git a/src/component/cyfs-bdt/src/protocol/v0.rs b/src/component/cyfs-bdt/src/protocol/v0.rs index c38540a8b..69f3a88e0 100644 --- a/src/component/cyfs-bdt/src/protocol/v0.rs +++ b/src/component/cyfs-bdt/src/protocol/v0.rs @@ -970,6 +970,24 @@ impl SessionData { id_part: None, } } + + pub fn is_ctrl_package(&self) -> bool { + if self.is_syn() || + self.is_syn_ack() || + self.is_flags_contain(SESSIONDATA_FLAG_ACK_PACKAGEID) || + self.is_flags_contain(SESSIONDATA_FLAG_FIN) || + self.is_flags_contain(SESSIONDATA_FLAG_FINACK) || + self.is_flags_contain(SESSIONDATA_FLAG_RESET) { + true + } else { + false + } + } + + pub fn data_size(&self) -> usize { + self.payload.as_ref().len() + } + pub fn is_syn(&self) -> bool { self.syn_info.is_some() && (self.flags & SESSIONDATA_FLAG_ACK == 0) } diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index 1d038f7af..a20becf1a 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -122,10 +122,10 @@ impl StackConfig { listener: stream::listener::Config { backlog: 100 }, stream: stream::container::Config { nagle: Duration::from_millis(0), - recv_buffer: 1024 * 256, + recv_buffer: 1024 * 1024, recv_timeout: Duration::from_millis(200), drain: 0.5, - send_buffer: 1024 * 256, // 这个值不能小于下边的max_record + send_buffer: 1024 * 512, // 这个值不能小于下边的max_record retry_sn_timeout: Duration::from_secs(2), connect_timeout: Duration::from_secs(5), tcp: stream::tcp::Config { @@ -134,7 +134,7 @@ impl StackConfig { }, package: stream::package::Config { connect_resend_interval: Duration::from_millis(100), - atomic_interval: Duration::from_millis(1), + atomic_interval: Duration::from_millis(10), break_overtime: Duration::from_secs(60), msl: Duration::from_secs(60), cc: cc::Config { @@ -170,7 +170,7 @@ impl StackConfig { cc: cc::Config { init_rto: Duration::from_secs(1), min_rto: Duration::from_millis(200), - cc_impl: cc::ImplConfig::BBR(Default::default()), + cc_impl: cc::ImplConfig::Ledbat(Default::default()), } }, history_speed: HistorySpeedConfig { diff --git a/src/component/cyfs-bdt/src/stream/package/stream.rs b/src/component/cyfs-bdt/src/stream/package/stream.rs index 58e76fea8..6377f237b 100644 --- a/src/component/cyfs-bdt/src/stream/package/stream.rs +++ b/src/component/cyfs-bdt/src/stream/package/stream.rs @@ -1,12 +1,14 @@ use log::*; use std::{ - time::Duration, + time::{Duration, Instant}, task::{Context, Poll}, + sync::Mutex, + collections::LinkedList, }; use async_std::{ sync::Arc, task, - future + future, }; use async_trait::{async_trait}; use cyfs_base::*; @@ -22,7 +24,7 @@ use super::super::{ stream_provider::{Shutdown, StreamProvider}}; use super::{ write::WriteProvider, - read::ReadProvider + read::ReadProvider, }; #[derive(Clone)] @@ -34,14 +36,21 @@ pub struct Config { pub cc: cc::Config } +struct PacePackage { + send_time: Instant, + package: DynamicPackage, +} + struct PackageStreamImpl { config: super::super::container::Config, owner_disp: String, tunnel: UdpTunnel, - local_id: IncreaseId, + local_id: IncreaseId, remote_id: IncreaseId, write_provider: WriteProvider, - read_provider: ReadProvider + read_provider: ReadProvider, + pacer: Mutex, + package_queue: Arc>>, } #[derive(Clone)] @@ -66,6 +75,7 @@ impl PackageStream { ) -> BuckyResult { let owner_disp = format!("{}", owner); let config = tunnel.stack().config().stream.stream.clone(); + let pacer_enable = false; let write_provider = WriteProvider::new(&config); let read_provider = ReadProvider::new(&config); @@ -76,7 +86,9 @@ impl PackageStream { local_id, remote_id, write_provider, - read_provider + read_provider, + pacer: Mutex::new(cc::pacing::Pacer::new(pacer_enable, PackageStream::mss() * 10, PackageStream::mss())), + package_queue: Arc::new(Mutex::new(Default::default())), })); Ok(stream) @@ -94,6 +106,40 @@ impl PackageStream { &self.0.read_provider } + fn package_delay(&self, package: DynamicPackage, send_time: Instant) { + let mut package_queue = self.0.package_queue.lock().unwrap(); + package_queue.push_back(PacePackage { + send_time, + package, + }); + } + + fn drain_delay(&self) { + let now = Instant::now(); + let mut package_queue = self.0.package_queue.lock().unwrap(); + let mut n = 0; + for (_, package) in package_queue.iter().enumerate() { + if package.send_time > now { + break ; + } + n += 1; + } + + while n > 0 { + if let Some(package) = package_queue.pop_front() { + match self.0.tunnel.send_package(package.package) { + Ok(sent_len) => { + trace!("package_delay send_package {}", sent_len); + }, + Err(err) => { + error!("stream send_package err={}", err); + } + } + } + n -= 1; + } + } + pub fn send_packages(&self, packages: Vec) -> Result<(), BuckyError> { if packages.len() == 0 { return Ok(()); @@ -117,9 +163,39 @@ impl PackageStream { // trace!("{} will send session data package {}", self, session_data); } - for package in packages { - let _ = self.0.tunnel.send_package(package); + let mut sent_bytes = 0; + let mut last_packet_number = 0; + { + let mut pacer = self.0.pacer.lock().unwrap(); + let now = Instant::now(); + for package in packages { + let session_data: & SessionData = package.as_ref(); + if !session_data.is_ctrl_package() || !session_data.is_flags_contain(SESSIONDATA_FLAG_ACK) { + let package_size = session_data.data_size(); + if let Some(next_time) = pacer.send(package_size, now) { + sent_bytes += package_size; + + self.package_delay(package, next_time); + continue; + } + last_packet_number = session_data.send_time; + } + + match self.0.tunnel.send_package(package) { + Ok(sent_len) => { + sent_bytes += sent_len; + }, + Err(err) => { + error!("stream send_package err={}", err); + } + } + } + } + + if sent_bytes > 0 { + self.write_provider().on_sent(sent_bytes as u64, last_packet_number); } + Ok(()) } } @@ -158,6 +234,7 @@ impl StreamProvider for PackageStream { break; } let _ = stream.send_packages(packages); + stream.drain_delay(); let _ = future::timeout(stream.config().package.atomic_interval, future::pending::<()>()).await; } }); @@ -238,7 +315,14 @@ impl OnPackage for PackageStream { _ => unreachable!() } }; + + { + let mut pacer = self.0.pacer.lock().unwrap(); + pacer.update(self.write_provider().rate()); + } + let _ = self.send_packages(packages); + Ok(r) } } diff --git a/src/component/cyfs-bdt/src/stream/package/write.rs b/src/component/cyfs-bdt/src/stream/package/write.rs index 132acaef0..59ea4935e 100644 --- a/src/component/cyfs-bdt/src/stream/package/write.rs +++ b/src/component/cyfs-bdt/src/stream/package/write.rs @@ -32,13 +32,16 @@ struct WriteProviderImpl { est_stubs: LinkedList, est_id: IncreaseIdGenerator, last_recv: Timestamp, - cc: CongestionControl + cc: CongestionControl, + app_limited: bool, } impl WriteProviderImpl { fn check_wnd(&mut self, stream: &PackageStream, now: Timestamp, timeout: Duration, packages: &mut Vec, logging: bool) { self.queue.check_wnd(stream, now, timeout, self.cc.cwnd(), packages, logging); self.on_pre_send_package(stream, packages); + + self.app_limited = packages.len() == 0; } fn on_time_escape(&mut self, stream: &PackageStream, now: Timestamp, packages: &mut Vec) -> BuckyResult<()> { @@ -46,19 +49,23 @@ impl WriteProviderImpl { let nagle = self.queue.check_nagle(stream, now); let (lost, _break) = if self.queue.flight() > 0 { let lost = self.queue.check_timeout(now, self.cc.rto()); - if lost >= self.queue.flight() { - let d = Duration::from_micros(now - self.last_recv); - if d > stream.config().package.break_overtime { - (true, true) + if lost > 0 { + if lost >= self.queue.flight() { + let d = Duration::from_micros(now - self.last_recv); + if d > stream.config().package.break_overtime { + (true, true) + } else { + debug!("{} cc no ack in rto, lost={}", stream, lost); + self.cc.on_no_resp(lost as u64); + (true, false) + } } else { - debug!("{} cc no ack in rto", stream); - self.cc.on_no_resp(lost as u64); + debug!("{} cc lost some package's ack, lost={}", stream, lost); + self.cc.on_loss(lost as u64); (true, false) } } else { - debug!("{} cc lost some package's ack", stream); - self.cc.on_loss(lost as u64); - (true, false) + (false, false) } } else { (false, false) @@ -119,7 +126,8 @@ impl WriteProvider { est_id: IncreaseIdGenerator::new(), est_stubs: LinkedList::new(), last_recv: bucky_time_now(), - cc: CongestionControl::new(PackageStream::mss(), &config.package.cc) + cc: CongestionControl::new(PackageStream::mss(), &config.package.cc), + app_limited: false, }))) } @@ -234,6 +242,28 @@ impl WriteProvider { result } + pub fn on_sent(&self, sent_bytes: u64, last_packet_number: u64) { + let state = &mut *cyfs_debug::lock!(self.0).unwrap(); + match state { + WriteProviderState::Open(provider) => { + provider.cc.on_sent(bucky_time_now(), sent_bytes, last_packet_number); + } + _ => {} + } + } + + pub fn rate(&self) -> u64 { + let state = &mut *cyfs_debug::lock!(self.0).unwrap(); + match state { + WriteProviderState::Open(provider) => { + provider.cc.rate() + } + _ => { + 0 + } + } + } + pub fn reset(&self, stream: &PackageStream) { let waiters = { let mut waiters = LinkedList::new(); @@ -282,7 +312,7 @@ impl OnPackage)> for Writ if sample.id == package_id { let rtt = Duration::from_micros(bucky_time_now() - sample.send_time); let delay = rtt / 2; - provider.cc.on_estimate(rtt, delay); + provider.cc.on_estimate(rtt, delay, provider.app_limited); debug!("{} estimate rtt:{:?} delay:{:?} rto:{:?}", stream, rtt, delay, provider.cc.rto()); to_remove = Some(index); break; @@ -312,8 +342,9 @@ impl OnPackage)> for Writ trace!("{} newly ack {} to {}", stream, newly_acked, provider.queue.start()); provider.cc.on_ack(provider.queue.flight() as u64, newly_acked as u64, - Some(newly_acked as u64), - bucky_time_now()); + Some(session_data.send_time), + bucky_time_now(), + provider.app_limited); debug!("{} update cwnd: {}", stream, provider.cc.cwnd()); provider.check_wnd(stream, now, provider.cc.rto(), &mut packages, false); diff --git a/src/component/cyfs-bdt/src/tunnel/container.rs b/src/component/cyfs-bdt/src/tunnel/container.rs index 721b23d51..6c5edc03f 100644 --- a/src/component/cyfs-bdt/src/tunnel/container.rs +++ b/src/component/cyfs-bdt/src/tunnel/container.rs @@ -289,7 +289,8 @@ impl TunnelContainer { Ok(()) } else { let tunnel = self.default_tunnel()?; - tunnel.as_ref().send_package(package) + let _ = tunnel.as_ref().send_package(package)?; + Ok(()) } } diff --git a/src/component/cyfs-bdt/src/tunnel/tcp.rs b/src/component/cyfs-bdt/src/tunnel/tcp.rs index d747619f6..2b675e35b 100644 --- a/src/component/cyfs-bdt/src/tunnel/tcp.rs +++ b/src/component/cyfs-bdt/src/tunnel/tcp.rs @@ -1022,7 +1022,7 @@ impl tunnel::Tunnel for Tunnel { } } - fn send_package(&self, package: DynamicPackage) -> Result<(), BuckyError> { + fn send_package(&self, package: DynamicPackage) -> Result { if package.cmd_code() == PackageCmdCode::SessionData { return Err(BuckyError::new(BuckyErrorCode::UnSupport, "session data should not send from tcp tunnel")); } @@ -1043,7 +1043,8 @@ impl tunnel::Tunnel for Tunnel { if to_connect { let _ = self.connect(); } - Ok(()) + + Ok(0) } fn raw_data_header_len(&self) -> usize { diff --git a/src/component/cyfs-bdt/src/tunnel/tunnel.rs b/src/component/cyfs-bdt/src/tunnel/tunnel.rs index 213033205..474ed8444 100644 --- a/src/component/cyfs-bdt/src/tunnel/tunnel.rs +++ b/src/component/cyfs-bdt/src/tunnel/tunnel.rs @@ -34,7 +34,7 @@ pub trait Tunnel: Send + Sync + std::fmt::Display { fn remote(&self) -> &Endpoint; fn state(&self) -> TunnelState; fn proxy(&self) -> ProxyType; - fn send_package(&self, packages: protocol::DynamicPackage) -> Result<(), BuckyError>; + fn send_package(&self, packages: protocol::DynamicPackage) -> Result; fn raw_data_header_len(&self) -> usize; fn send_raw_data(&self, data: &mut [u8]) -> Result; fn ptr_eq(&self, other: &DynamicTunnel) -> bool; diff --git a/src/component/cyfs-bdt/src/tunnel/udp.rs b/src/component/cyfs-bdt/src/tunnel/udp.rs index f027e055f..8d5bc5c99 100644 --- a/src/component/cyfs-bdt/src/tunnel/udp.rs +++ b/src/component/cyfs-bdt/src/tunnel/udp.rs @@ -356,7 +356,7 @@ impl tunnel::Tunnel for Tunnel { interface.send_raw_data_to(&key, data, tunnel::Tunnel::remote(self)) } - fn send_package(&self, package: DynamicPackage) -> Result<(), BuckyError> { + fn send_package(&self, package: DynamicPackage) -> Result { let (tunnel_container, interface, key) = { if let TunnelState::Active(active_state) = &*self.0.state.read().unwrap() { Ok((active_state.container.clone(), active_state.interface.clone(), active_state.key.clone())) @@ -367,8 +367,8 @@ impl tunnel::Tunnel for Tunnel { let package_box = PackageBox::from_package(tunnel_container.remote().clone(), key, package); let mut context = PackageBoxEncodeContext::default(); context.set_ignore_exchange(ProxyType::None != self.0.proxy); - interface.send_box_to(&mut context, &package_box, tunnel::Tunnel::remote(self))?; - Ok(()) + let sent_len = interface.send_box_to(&mut context, &package_box, tunnel::Tunnel::remote(self))?; + Ok(sent_len) } fn retain_keeper(&self) { From be1b5f211bac60624ade8287250970c0c5ca2274 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 19:14:24 +0800 Subject: [PATCH 153/553] Fix usage of lru cache in meta relate cache --- src/component/cyfs-meta-lib/src/helper.rs | 3 +++ src/component/cyfs-stack/src/meta/cache.rs | 6 +++++- src/component/cyfs-stack/src/meta/fail_cache.rs | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-meta-lib/src/helper.rs b/src/component/cyfs-meta-lib/src/helper.rs index 55288f375..9db23db71 100644 --- a/src/component/cyfs-meta-lib/src/helper.rs +++ b/src/component/cyfs-meta-lib/src/helper.rs @@ -108,6 +108,9 @@ impl MetaClientHelperWithObjectCache { object_id: &ObjectId, ) -> BuckyResult>> { let mut list = self.objects.lock().await; + // force remove expired items + list.iter(); + if let Some(item) = list.peek(object_id) { return Ok(item.into_object_raw()); } diff --git a/src/component/cyfs-stack/src/meta/cache.rs b/src/component/cyfs-stack/src/meta/cache.rs index 74e36cf1a..48b311bcb 100644 --- a/src/component/cyfs-stack/src/meta/cache.rs +++ b/src/component/cyfs-stack/src/meta/cache.rs @@ -46,7 +46,11 @@ where Key: Borrow, Q: Ord, { - self.list.get(&key).map(|v| v.value.clone()) + // force remove expired items + self.list.iter(); + + // do not update the last used timestamp + self.list.peek(&key).map(|v| v.value.clone()) } } diff --git a/src/component/cyfs-stack/src/meta/fail_cache.rs b/src/component/cyfs-stack/src/meta/fail_cache.rs index b0b16c468..c6c9d6188 100644 --- a/src/component/cyfs-stack/src/meta/fail_cache.rs +++ b/src/component/cyfs-stack/src/meta/fail_cache.rs @@ -97,7 +97,11 @@ impl MetaFailCacheImpl { pub fn get(&mut self, key: &MetaCacheKey) -> Option { // 首先查询是不是存在缓存 - let ret = self.list.get(&key).map(|v| v.error.clone()); + // force remove expired items + self.list.iter(); + + // use peek instead of get, do not update the last use timestamp! + let ret = self.list.peek(&key).map(|v| v.error.clone()); if ret.is_some() { return ret; } From 4e012834f6d12fdf54d8a08363bfdf012f36894e Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 19:55:32 +0800 Subject: [PATCH 154/553] Fix usage of lru cache in failed relate cache --- .../cyfs-stack/src/ndn_api/bdt/cache.rs | 9 +++- src/component/cyfs-stack/src/resolver/mod.rs | 1 - .../cyfs-stack/src/resolver/ood_cache.rs | 51 ------------------- .../src/root_state_api/validate/cache.rs | 5 +- .../cyfs-stack/src/zone/failed_cache.rs | 21 ++++++-- 5 files changed, 27 insertions(+), 60 deletions(-) delete mode 100644 src/component/cyfs-stack/src/resolver/ood_cache.rs diff --git a/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs b/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs index eea8b7356..bf6af0af5 100644 --- a/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs +++ b/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs @@ -24,7 +24,8 @@ pub(super) struct BdtDataAclCache { impl BdtDataAclCache { pub fn new() -> Self { - let list = LruCache::with_expiry_duration(std::time::Duration::from_secs(60 * 5)); + let list = LruCache::with_expiry_duration_and_capacity( + std::time::Duration::from_secs(60 * 5), 256); Self { list: Arc::new(Mutex::new(list)), @@ -45,6 +46,10 @@ impl BdtDataAclCache { pub fn get(&self, key: &BdtDataAclCacheKey) -> Option> { let mut list = self.list.lock().unwrap(); - list.get(&key).map(|v| v.result.clone()) + + // force remove expired items + list.iter(); + + list.peek(&key).map(|v| v.result.clone()) } } diff --git a/src/component/cyfs-stack/src/resolver/mod.rs b/src/component/cyfs-stack/src/resolver/mod.rs index 95929bcdd..e7a24f064 100644 --- a/src/component/cyfs-stack/src/resolver/mod.rs +++ b/src/component/cyfs-stack/src/resolver/mod.rs @@ -1,7 +1,6 @@ mod device_manager; mod obj_searcher; mod ood_resolver; -mod ood_cache; pub(crate) use device_manager::*; pub(crate) use obj_searcher::*; diff --git a/src/component/cyfs-stack/src/resolver/ood_cache.rs b/src/component/cyfs-stack/src/resolver/ood_cache.rs deleted file mode 100644 index 87baf1d62..000000000 --- a/src/component/cyfs-stack/src/resolver/ood_cache.rs +++ /dev/null @@ -1,51 +0,0 @@ -use cyfs_base::*; - -use lru_time_cache::{Entry, LruCache}; -use std::sync::Arc; -use std::time::Duration; -use cyfs_debug::Mutex; - -#[derive(Clone)] -pub struct OodInfo { - pub ood_list: Vec, -} - -pub(super) struct OodCache { - list: Arc>>, -} - -impl OodCache { - pub fn new() -> Self { - let list = - LruCache::with_expiry_duration_and_capacity(Duration::from_secs(3600 * 24 * 7), 1024); - - Self { - list: Arc::new(Mutex::new(list)), - } - } - - pub fn add(&self, object_id: &ObjectId, ood_list: Vec) { - match self.list.lock().unwrap().entry(object_id.clone()) { - Entry::Occupied(v) => { - info!("will replace resolved ood list: {}", object_id); - (*v.into_mut()).ood_list = ood_list; - } - Entry::Vacant(v) => { - info!("will save resolved ood list: {}, {:?}", object_id, ood_list); - let item = OodInfo { ood_list }; - - v.insert(item); - } - } - } - - pub fn get(&mut self, object_id: &ObjectId) -> Option> { - let mut list = self.list.lock().unwrap(); - let info = list.get(object_id); - if info.is_none() { - return None; - } - - Some(info.unwrap().ood_list.clone()) - } -} diff --git a/src/component/cyfs-stack/src/root_state_api/validate/cache.rs b/src/component/cyfs-stack/src/root_state_api/validate/cache.rs index 826d2bbcb..35b7aaf65 100644 --- a/src/component/cyfs-stack/src/root_state_api/validate/cache.rs +++ b/src/component/cyfs-stack/src/root_state_api/validate/cache.rs @@ -37,7 +37,10 @@ impl GlobalStatePathCacheInner { return Ok(ret.cloned()); } - if let Some(item) = self.failed_cache.get(key) { + // force remove expired items + self.failed_cache.iter(); + + if let Some(item) = self.failed_cache.peek(key) { return Err(item.error.clone()); } diff --git a/src/component/cyfs-stack/src/zone/failed_cache.rs b/src/component/cyfs-stack/src/zone/failed_cache.rs index d7ed23c3f..27c3ea988 100644 --- a/src/component/cyfs-stack/src/zone/failed_cache.rs +++ b/src/component/cyfs-stack/src/zone/failed_cache.rs @@ -30,10 +30,13 @@ impl OrphanZoneCache { } pub fn get_by_device(&mut self, device_id: &DeviceId) -> Option { - let ret = self.device_list.get(device_id); + // force remove expired items + self.device_list.iter(); + self.zone_list.iter(); + + let ret = self.device_list.peek(device_id); match ret { Some(v) => { - self.zone_list.get(&v.zone_id); Some(v.zone.clone()) } None => None, @@ -41,9 +44,13 @@ impl OrphanZoneCache { } pub fn get(&mut self, zone_id: &ZoneId) -> Option { - let ret = self.zone_list.get(zone_id); + // force remove expired items + self.device_list.iter(); + self.zone_list.iter(); + + let ret = self.zone_list.peek(zone_id); match ret { - Some(device_id) => self.device_list.get(device_id).map(|v| v.zone.clone()), + Some(device_id) => self.device_list.peek(device_id).map(|v| v.zone.clone()), None => None, } } @@ -93,7 +100,11 @@ impl ZoneFailedCache { pub fn get_failed_owner(&self, object_id: &ObjectId) -> Option { let mut cache = self.owner_cache.lock().unwrap(); - cache.get(object_id).map(|v| v.clone()) + + // force remove expired items + cache.iter(); + + cache.peek(object_id).map(|v| v.clone()) } // device搜寻zone失败,创建孤儿zone并缓存 From 3e8fe5b845c4ee214460605b811c2cd9589d71a8 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 20:37:21 +0800 Subject: [PATCH 155/553] Perf-client can use in cyfs-stack --- src/component/cyfs-lib/src/root_state/stub.rs | 2 +- .../cyfs-perf/cyfs-perf-client/src/reporter.rs | 10 +++++----- src/tests/cyfs-stack-test/src/case/perf.rs | 17 ++++++++++++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-lib/src/root_state/stub.rs b/src/component/cyfs-lib/src/root_state/stub.rs index 3577f4ca2..bb56ca3b5 100644 --- a/src/component/cyfs-lib/src/root_state/stub.rs +++ b/src/component/cyfs-lib/src/root_state/stub.rs @@ -338,7 +338,7 @@ pub struct PathOpEnvStub { } impl PathOpEnvStub { - pub(crate) fn new( + pub fn new( processor: OpEnvOutputProcessorRef, target: Option, target_dec_id: Option, diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index 8a7592b55..9a83fe7af 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -184,10 +184,11 @@ impl PerfReporterInner { } // 把obj再put出去 + let target = if save_to_local { None } else { target }; let mut req = NONPutObjectOutputRequest::new( if save_to_local { NONAPILevel::NOC } else { NONAPILevel::Router }, object_id.clone(), raw); - req.common.target = if save_to_local { None } else { target }; + req.common.target = target.clone(); req.common.dec_id = obj.desc().dec_id().clone(); let str_target = if save_to_local { "local".to_owned() } else {target.map_or("ood".to_owned(), |id| id.to_string())}; match self.cyfs_stack.non_service().put_object(req).await { @@ -203,12 +204,11 @@ impl PerfReporterInner { // 存到root_state let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); - req.access = access; - req.common.target = self.target.clone(); - req.common.target_dec_id = self.target_dec_id.clone(); + req.common.target = target.clone(); + req.common.target_dec_id = self.dec_id.clone(); let resp = self.cyfs_stack.root_state().create_op_env(req).await?; - let path_env = PathOpEnvStub::new(resp, self.target.clone(), self.target_dec_id.clone()); + let path_env = PathOpEnvStub::new(resp, target.clone(), self.dec_id.clone()); let key = obj.get_time_range().to_string(); path_env.set_with_key("/stat", key, &object_id, None, true).await?; path_env.commit().await?; diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index f79043ee6..49ba595b8 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -1,6 +1,7 @@ +use std::time::Duration; use cyfs_base::*; use cyfs_core::*; -use cyfs_perf_client::{PerfClient, PerfIsolate, PerfServerConfig}; +use cyfs_perf_client::{PerfClient, PerfConfig, PerfIsolate, PerfServerConfig}; use zone_simulator::*; fn new_dec(name: &str) -> ObjectId { @@ -16,13 +17,23 @@ fn new_dec(name: &str) -> ObjectId { pub async fn test() { let dec_id = new_dec("test-perf"); let stack = TestLoader::get_shared_stack(DeviceIndex::User1Device2); + stack.online().await; + let device = stack.local_device(); + let owner = device.desc().owner().as_ref().unwrap().clone(); + let device_id = device.desc().device_id(); let perf = PerfClient::new( "test-perf".to_owned(), "1.0.0".to_owned(), Some(dec_id), - PerfServerConfig::Default, - stack, + PerfConfig { + reporter: PerfServerConfig::Default, + save_to_file: false, + report_interval: Duration::from_secs(60*10), + }, + stack.uni_stack().clone(), + device_id, + owner ); let ret = perf.start().await; From 5fa897fd28c546bdf648a7d2ee03f62f9d447594 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 21:41:54 +0800 Subject: [PATCH 156/553] Fix app-manager compile error --- src/service/app-manager/src/dapp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index 012b5d26a..628de11f7 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -45,7 +45,7 @@ fn get_str(value: &Value, key: &str) -> BuckyResult { impl Drop for DApp { fn drop(&mut self) { - if let Some(mut child) = self.process.lock().unwrap().as_ref() { + if let Some(child) = self.process.lock().unwrap().as_mut() { warn!("dapp {} dropped when child process start! pid {}", &self.dec_id, child.id()); child.kill(); child.wait(); @@ -244,9 +244,9 @@ impl DApp { pub fn start(&self) -> BuckyResult { if !self.status()? { let child = DApp::run(&self.info.start, &self.work_dir, true, None)?; + let id = child.id(); *self.process.lock().unwrap() = Some(child); // mark pid - let id = child.id(); let lock_file = self.get_pid_file_path()?; let buf = format!("{}", id).into_bytes(); std::fs::write(lock_file, &buf).map_err(|e| { From 917ea272fc68622d8cb0307158dfe9b4062d59e3 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Sat, 25 Feb 2023 15:47:24 +0800 Subject: [PATCH 157/553] Change old-chunk-client`s get header timeout to 30 secs, DecApp Install Command timeout to 15 mins, remove app-manager`s intermediate state`s timeout --- src/service/app-manager/src/app_manager_ex.rs | 51 ------------------- src/service/app-manager/src/dapp.rs | 2 +- .../cyfs-chunk-client/src/chunk_request.rs | 2 +- 3 files changed, 2 insertions(+), 53 deletions(-) diff --git a/src/service/app-manager/src/app_manager_ex.rs b/src/service/app-manager/src/app_manager_ex.rs index 0175f6501..7da7d0be5 100644 --- a/src/service/app-manager/src/app_manager_ex.rs +++ b/src/service/app-manager/src/app_manager_ex.rs @@ -431,8 +431,6 @@ impl AppManager { } /* 根据local_status检查app状态 - Starting,Stopping,Installing,Uninstalling为中间状态, - 处于此种状态超过一定时间(STATUS_LASTED_TIME_LIMIT_IN_MICROS 10分钟)会进入错误状态。 已经入错误状态的app不用管。等下一个命令纠正它。 已经入Running状态的app要确保它正在运行。 除Running状态的其他非中间状态,不用管。 @@ -452,55 +450,6 @@ impl AppManager { self.check_running_app(&app_id, status.clone()).await; continue; } - - let mut status_clone = None; - { - //要在锁里操作,因为执行器也可能改变App的状态 - let mut status = status.lock().unwrap(); - let status_code = status.status(); - let status_lasted_time = bucky_time_now() - status.last_status_update_time(); - let is_lasted_exceeds_limit = - status_lasted_time > STATUS_LASTED_TIME_LIMIT_IN_MICROS; - let mut target_status_code = None; - if is_lasted_exceeds_limit { - //中间状态超过持续时间,认为失败 - match status_code { - AppLocalStatusCode::Starting => { - target_status_code = Some(AppLocalStatusCode::StartFailed); - } - AppLocalStatusCode::Stopping => { - target_status_code = Some(AppLocalStatusCode::StopFailed); - } - AppLocalStatusCode::Installing => { - target_status_code = Some(AppLocalStatusCode::InstallFailed); - } - AppLocalStatusCode::Uninstalling => { - target_status_code = Some(AppLocalStatusCode::UninstallFailed); - } - _ => { - //info!("check status pass, app:{}, status: {}", app_id, v); - } - } - } - - match target_status_code { - Some(target_status) => { - info!( - "[STATUS CHECK] will change status by checker, app:{}, from [{}] to [{}], is lasted exceeds limit: {}", - app_id, status_code, target_status, is_lasted_exceeds_limit - ); - - status.set_status(target_status); - status_clone = Some(status.clone()); - } - None => { - info!("check status pass, app:{}, status: {}", app_id, status_code); - } - } - } - if let Some(new_status) = status_clone { - let _ = self.non_helper.put_local_status(&new_status).await; - } } } diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index 628de11f7..9f3e52df7 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -14,7 +14,7 @@ use wait_timeout::ChildExt; const STATUS_CMD_TIME_OUT_IN_SECS: u64 = 15; const STOP_CMD_TIME_OUT_IN_SECS: u64 = 60; const START_CMD_TIME_OUT_IN_SECS: u64 = 5 * 60; -const INSTALL_CMD_TIME_OUT_IN_SECS: u64 = 10 * 60; +const INSTALL_CMD_TIME_OUT_IN_SECS: u64 = 15 * 60; #[derive(Deserialize, Clone)] pub struct DAppInfo { diff --git a/src/tools/cyfs-chunk-client/src/chunk_request.rs b/src/tools/cyfs-chunk-client/src/chunk_request.rs index d00aca7b6..9769b29eb 100644 --- a/src/tools/cyfs-chunk-client/src/chunk_request.rs +++ b/src/tools/cyfs-chunk-client/src/chunk_request.rs @@ -7,7 +7,7 @@ pub async fn process_req(req: Request, stream: RW) -> BuckyResult where RW: Read + Write + Send + Sync + Unpin + 'static, { - let resp = cyfs_util::async_h1_helper::connect_timeout(stream, req,std::time::Duration::from_secs(60 * 5)).await.map_err(|e| { + let resp = cyfs_util::async_h1_helper::connect_timeout(stream, req,std::time::Duration::from_secs(30)).await.map_err(|e| { error!("read resp from stream error: {}", e); e })?; From 15d0e4c713a4b32a0ca75567fb01f7cf048acdf3 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 12:15:03 +0800 Subject: [PATCH 158/553] Add perf related definitions to cyfs-base --- src/component/cyfs-base/src/lib.rs | 2 + src/component/cyfs-base/src/perf/auxi.rs | 69 +++++++++++++++++++++++ src/component/cyfs-base/src/perf/dummy.rs | 29 ++++++++++ src/component/cyfs-base/src/perf/mod.rs | 15 +++++ src/component/cyfs-base/src/perf/perf.rs | 31 ++++++++++ 5 files changed, 146 insertions(+) create mode 100644 src/component/cyfs-base/src/perf/auxi.rs create mode 100644 src/component/cyfs-base/src/perf/dummy.rs create mode 100644 src/component/cyfs-base/src/perf/mod.rs create mode 100644 src/component/cyfs-base/src/perf/perf.rs diff --git a/src/component/cyfs-base/src/lib.rs b/src/component/cyfs-base/src/lib.rs index 627477b70..74e41d155 100644 --- a/src/component/cyfs-base/src/lib.rs +++ b/src/component/cyfs-base/src/lib.rs @@ -2,6 +2,7 @@ mod codec; mod crypto; mod base; mod objects; +mod perf; pub use base::endpoint; @@ -18,6 +19,7 @@ pub use base::*; pub use codec::*; pub use cyfs_base_derive::*; pub use objects::*; +pub use perf::*; #[macro_use] extern crate log; diff --git a/src/component/cyfs-base/src/perf/auxi.rs b/src/component/cyfs-base/src/perf/auxi.rs new file mode 100644 index 000000000..5a3da8418 --- /dev/null +++ b/src/component/cyfs-base/src/perf/auxi.rs @@ -0,0 +1,69 @@ +#[macro_export] +macro_rules! declare_module_perf_isolate { + ( $id:expr ) => { + pub const PERF_ISOLATE_ID: &str = $id; + pub fn get_current_perf_instance() -> Option<&'static cyfs_base::PerfIsolateRef> { + static CURRENT_PERF_INSTANCE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + match CURRENT_PERF_INSTANCE.get() { + Some(ins) => Some(ins), + None => { + match cyfs_base::PERF_MANGER.get() { + Some(manager) => { + let ins = manager.get_isolate(PERF_ISOLATE_ID); + let _ = CURRENT_PERF_INSTANCE.set(ins); + CURRENT_PERF_INSTANCE.get() + } + None => { + None + } + } + } + } + } + } +} + +#[macro_export] +macro_rules! perf_begin_request { + ( $id:expr, $key:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.begin_request($id, $key); + } + } +} + +#[macro_export] +macro_rules! perf_end_request { + ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request($id, $key, $err, $bytes); + } + } +} + +#[macro_export] +macro_rules! perf_acc { + ( $id:expr, $err:expr, $size:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.acc($id, $err, $size); + } + } +} + +#[macro_export] +macro_rules! perf_action { + ( $id:expr, $err:expr, $name:expr, $value:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.action($id, $err, $name, $value); + } + } +} + +#[macro_export] +macro_rules! perf_record { + ( $id:expr, $total:expr, $total_size:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.record($id, $total, $total_size); + } + } +} \ No newline at end of file diff --git a/src/component/cyfs-base/src/perf/dummy.rs b/src/component/cyfs-base/src/perf/dummy.rs new file mode 100644 index 000000000..3b918ec91 --- /dev/null +++ b/src/component/cyfs-base/src/perf/dummy.rs @@ -0,0 +1,29 @@ +#[macro_export] +macro_rules! declare_module_perf_isolate { + ( $id:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_begin_request { + ( $id:expr, $key:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_end_request { + ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_acc { + ( $id:expr, $err:expr, $size:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_action { + ( $id:expr, $err:expr, $name:expr, $value:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_record { + ( $id:expr, $total:expr, $total_size:expr ) => {}; +} diff --git a/src/component/cyfs-base/src/perf/mod.rs b/src/component/cyfs-base/src/perf/mod.rs new file mode 100644 index 000000000..bcba02ef0 --- /dev/null +++ b/src/component/cyfs-base/src/perf/mod.rs @@ -0,0 +1,15 @@ +mod perf; + +pub use perf::*; + +#[cfg(not(feature = "perf"))] +mod dummy; + +#[cfg(not(feature = "perf"))] +pub use dummy::*; + +#[cfg(feature = "perf")] +mod auxi; + +#[cfg(feature = "perf")] +pub use auxi::*; \ No newline at end of file diff --git a/src/component/cyfs-base/src/perf/perf.rs b/src/component/cyfs-base/src/perf/perf.rs new file mode 100644 index 000000000..2c81117b4 --- /dev/null +++ b/src/component/cyfs-base/src/perf/perf.rs @@ -0,0 +1,31 @@ +use crate::{BuckyErrorCode, BuckyResult}; + +use once_cell::sync::OnceCell; +use std::sync::Arc; + +pub trait PerfIsolate: Send + Sync { + fn begin_request(&self, id: &str, key: &str); + fn end_request(&self, id: &str, key: &str, err: BuckyErrorCode, bytes: Option); + + fn acc(&self, id: &str, err: BuckyErrorCode, size: Option); + + fn action( + &self, + id: &str, + err: BuckyErrorCode, + name: &str, + value: &str, + ); + + fn record(&self, id: &str, total: u64, total_size: Option); +} + +pub type PerfIsolateRef = Arc>; + +#[async_trait::async_trait] +pub trait PerfManager: Send + Sync { + async fn flush(&self) -> BuckyResult<()>; + fn get_isolate(&self, id: &str) -> PerfIsolateRef; +} + +pub static PERF_MANGER: OnceCell> = OnceCell::new(); From 7ec3d2a0bff1dea96d878ad2c2811176040b76b5 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 13:16:44 +0800 Subject: [PATCH 159/553] Adapts perf relate impls in cyfs-perf-client with the perf definition in cyfs-base --- .../cyfs-perf/cyfs-perf-client/src/client.rs | 24 ++++++++++--- .../cyfs-perf/cyfs-perf-client/src/isolate.rs | 35 +++++++++++++++++-- .../cyfs-perf-client/src/reporter.rs | 7 ++-- .../cyfs-perf/cyfs-perf-client/src/store.rs | 2 +- src/tests/cyfs-stack-test/src/case/perf.rs | 6 ++-- 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs index 5d029c415..15dddeb42 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs @@ -1,5 +1,5 @@ use crate::config::*; -use crate::isolate::PerfIsolate; +use crate::isolate::PerfIsolateInstance; use crate::reporter::*; use crate::store::PerfStore; use cyfs_base::*; @@ -22,7 +22,7 @@ pub struct PerfClientInner { cyfs_stack: UniCyfsStackRef, store: PerfStore, - isolates: Mutex>, + isolates: Mutex>, local_device: DeviceId, owner: ObjectId @@ -139,11 +139,11 @@ impl PerfClientInner { Ok(()) } - pub fn get_isolate(&self, id: &str) -> PerfIsolate { + pub fn get_isolate(&self, id: &str) -> PerfIsolateInstance { let mut isolates = self.isolates.lock().unwrap(); isolates.entry(id.to_owned()).or_insert_with(|| { log::info!("create isolate module: id={}", id); - PerfIsolate::new(id) + PerfIsolateInstance::new(id) }).clone() } } @@ -164,6 +164,10 @@ impl PerfClient { Self(Arc::new(ret)) } + pub fn get_isolate(&self, id: &str) -> PerfIsolateInstance { + self.0.get_isolate(id) + } + pub async fn start(&self) -> BuckyResult<()> { self.0.start().await?; @@ -184,3 +188,15 @@ impl Deref for PerfClient { &self.0 } } + + +#[async_trait::async_trait] +impl PerfManager for PerfClient { + async fn flush(&self) -> BuckyResult<()> { + self.0.flush().await + } + + fn get_isolate(&self, id: &str) -> PerfIsolateRef { + self.0.get_isolate(id).into_isolate() + } +} \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs b/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs index 15b884494..2743f3d9e 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs @@ -231,13 +231,17 @@ impl PerfItemMerge for PerfIsolateImpl { } #[derive(Clone)] -pub struct PerfIsolate(Arc>); +pub struct PerfIsolateInstance(Arc>); -impl PerfIsolate { +impl PerfIsolateInstance { pub fn new(id: &str) -> Self { Self(Arc::new(Mutex::new(PerfIsolateImpl::new(id)))) } + pub fn into_isolate(self) -> PerfIsolateRef { + Arc::new(Box::new(self)) + } + pub fn begin_request(&self, id: &str, key: &str) { self.0.lock().unwrap().begin_request(id, key) } @@ -273,3 +277,30 @@ impl PerfIsolate { self.0.lock().unwrap().id.clone() } } + +impl PerfIsolate for PerfIsolateInstance { + fn begin_request(&self, id: &str, key: &str) { + Self::begin_request(&self, id, key) + } + fn end_request(&self, id: &str, key: &str, err: BuckyErrorCode, bytes: Option) { + Self::end_request(&self, id, key, err, bytes) + } + + fn acc(&self, id: &str, err: BuckyErrorCode, size: Option) { + Self::acc(&self, id, err, size) + } + + fn action( + &self, + id: &str, + err: BuckyErrorCode, + name: &str, + value: &str, + ) { + Self::action(&self, id, err, name, value) + } + + fn record(&self, id: &str, total: u64, total_size: Option) { + Self::record(&self, id, total, total_size) + } +} \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index 9a83fe7af..5d386c0e0 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -114,8 +114,11 @@ impl PerfReporterInner { let end: chrono::DateTime = bucky_time_to_system_time(data.time_range.end).into(); let pretty_format = "%Y%m%d_%H%M%S"; let file_name = format!("{}-{}.stat", begin.format(pretty_format), end.format(pretty_format)); - if let Ok(file) = std::fs::File::create(path.join(file_name)) { - serde_json::to_writer_pretty(&file, &data); + let file_path = path.join(file_name); + if let Ok(file) = std::fs::File::create(&file_path) { + if let Err(e) = serde_json::to_writer_pretty(&file, &data) { + error!("save perf data to local file failed! file={}, {}", file_path.display(), e); + } } } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs index 3359ccd3d..c657ec90e 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs @@ -59,7 +59,7 @@ impl PerfStore { } // 尝试保存到noc,保存成功后会清空isolates内容 - pub fn save(&self, isolates: &HashMap) { + pub fn save(&self, isolates: &HashMap) { // 锁定状态下,不可修改数据 if self.is_locked() { warn!("perf store still in locked state!"); diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index 49ba595b8..66cde49c7 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -1,7 +1,7 @@ use std::time::Duration; use cyfs_base::*; use cyfs_core::*; -use cyfs_perf_client::{PerfClient, PerfConfig, PerfIsolate, PerfServerConfig}; +use cyfs_perf_client::{PerfClient, PerfConfig, PerfIsolateInstance, PerfServerConfig}; use zone_simulator::*; fn new_dec(name: &str) -> ObjectId { @@ -47,7 +47,7 @@ pub async fn test() { // async_std::task::sleep(std::time::Duration::from_secs(1000)).await; } -async fn test_request(perf: PerfIsolate) { +async fn test_request(perf: PerfIsolateInstance) { async_std::task::spawn(async move { loop { perf.begin_request("connect", "address"); @@ -59,7 +59,7 @@ async fn test_request(perf: PerfIsolate) { }); } -async fn test_acc(perf: PerfIsolate) { +async fn test_acc(perf: PerfIsolateInstance) { async_std::task::spawn(async move { loop { async_std::task::sleep(std::time::Duration::from_secs(1)).await; From b36cab7bb9bc243fa7aecf128e93c59f1144fd1d Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 13:26:58 +0800 Subject: [PATCH 160/553] Integrate perf module into cyfs-stack --- src/Cargo.lock | 1 + src/component/cyfs-base/Cargo.toml | 1 + src/component/cyfs-stack/Cargo.toml | 1 + .../cyfs-stack/src/stack/cyfs_stack.rs | 42 +++++++++++++++++++ src/component/cyfs-stack/src/stack/params.rs | 4 ++ 5 files changed, 49 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index f09b84bc2..7f1d76f21 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2247,6 +2247,7 @@ dependencies = [ "cyfs-meta-lib", "cyfs-ndc", "cyfs-noc", + "cyfs-perf-client", "cyfs-task-manager", "cyfs-tracker-cache", "cyfs-util", diff --git a/src/component/cyfs-base/Cargo.toml b/src/component/cyfs-base/Cargo.toml index 3d972b259..9ce32803e 100644 --- a/src/component/cyfs-base/Cargo.toml +++ b/src/component/cyfs-base/Cargo.toml @@ -16,6 +16,7 @@ protoc-bin-vendored = '3' [features] default = [] sqlx-error = ['dep:sqlx'] +perf = [] [dependencies] cyfs-base-derive = { path = '../cyfs-base-derive', version = '0.5' } diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index faaaf23ec..48f201a85 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -27,6 +27,7 @@ cyfs-task-manager = { path = "../../component/cyfs-task-manager" } cyfs-chunk-cache = { path = "../../component/cyfs-chunk-cache" } cyfs-util = { path = "../cyfs-util" } cyfs-meta-lib = { path = "../cyfs-meta-lib" } +cyfs-perf-client = { path = "../cyfs-perf/cyfs-perf-client" } #dsg-client = { path = "../dsg/dsg-client" } log = "0.4" serde = "1.0" diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 7f6f75ef7..d562319ca 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -593,6 +593,10 @@ impl CyfsStackImpl { } }); + if param.config.perf_service { + let _ = stack.init_perf().await; + } + Ok(stack) } @@ -1029,6 +1033,44 @@ impl CyfsStackImpl { processors } + + async fn init_perf(&self) -> BuckyResult<()> { + use cyfs_perf_client::*; + + // The same process can only be initialized once, there may be other cyfs-stacks in the same process + if !cyfs_base::PERF_MANGER.get().is_none() { + warn!("perf manager already initialized!"); + return Ok(()); + } + + let info = self.zone_manager.get_current_info().await?; + + let perf = PerfClient::new( + "cyfs-stack".to_owned(), + cyfs_base::get_version().to_owned(), + None, + PerfConfig { + reporter: PerfServerConfig::Default, + save_to_file: false, + report_interval: std::time::Duration::from_secs(60 * 10), + }, + self.open_uni_stack(&None).await, + info.device_id.clone(), + info.owner_id.clone(), + ); + + if let Err(e) = perf.start().await { + error!("init perf client failed! {}", e); + } + + if let Err(_) = cyfs_base::PERF_MANGER.set(Box::new(perf)) { + warn!("init perf manager but already initialized!"); + } + + info!("init perf manager success! current={}", info.device_id); + + Ok(()) + } } #[derive(Clone)] diff --git a/src/component/cyfs-stack/src/stack/params.rs b/src/component/cyfs-stack/src/stack/params.rs index 37af157e8..7ebcc448d 100644 --- a/src/component/cyfs-stack/src/stack/params.rs +++ b/src/component/cyfs-stack/src/stack/params.rs @@ -13,6 +13,9 @@ pub struct CyfsStackConfigParams { // 是否开启shared_object_stack服务,默认为true pub shared_stack: bool, + + // Whether to enable perf_service + pub perf_service: bool, } impl Default for CyfsStackConfigParams { @@ -21,6 +24,7 @@ impl Default for CyfsStackConfigParams { isolate: None, sync_service: true, shared_stack: true, + perf_service: true, } } } From 4419d34dfe60acb16c46e9b61b0d73ddde9aea52 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 16:18:14 +0800 Subject: [PATCH 161/553] Add scope relate perf helper macros --- src/component/cyfs-base/src/perf/auxi.rs | 90 ++++++++++++++++++++++- src/component/cyfs-base/src/perf/dummy.rs | 16 ++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-base/src/perf/auxi.rs b/src/component/cyfs-base/src/perf/auxi.rs index 5a3da8418..01bb4b4ce 100644 --- a/src/component/cyfs-base/src/perf/auxi.rs +++ b/src/component/cyfs-base/src/perf/auxi.rs @@ -20,6 +20,65 @@ macro_rules! declare_module_perf_isolate { } } } + + pub struct PerfScopeRequest<'a> { + id: &'a str, + key: String, + } + + impl<'a> PerfScopeRequest<'a> { + pub fn new( + id: &'a str, + ) -> Self { + let key = cyfs_base::perf_request_unique_id(); + if let Some(ins) = crate::get_current_perf_instance() { + ins.begin_request(id, &key); + } + + Self { + id, + key, + } + } + } + + impl<'a> Drop for PerfScopeRequest<'a> { + fn drop(&mut self) { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request(self.id, &self.key, cyfs_base::BuckyErrorCode::Ok, None); + } + } + } + } +} + +use std::sync::atomic::{AtomicU64, Ordering}; + +pub fn perf_request_unique_id() -> String { + static INDEX: AtomicU64 = AtomicU64::new(0); + let ret = INDEX.fetch_add(1, Ordering::SeqCst); + ret.to_string() +} + +#[macro_export] +macro_rules! perf_scope_request { + ( $id:expr, $block:block ) => { + if let Some(ins) = crate::get_current_perf_instance() { + let req_id = cyfs_base::perf_request_unique_id(); + ins.begin_request($id, &req_id); + match $block { + Ok(v) => { + ins.end_request($id, &req_id, cyfs_base::BuckyErrorCode::Ok, None); + Ok(v) + } + Err(e) => { + ins.end_request($id, &req_id, e.code(), None); + Err(e) + } + } + } else { + $block + } } } @@ -34,20 +93,49 @@ macro_rules! perf_begin_request { #[macro_export] macro_rules! perf_end_request { + ( $id:expr, $key:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request($id, $key, cyfs_base::BuckyErrorCode::Ok, None); + } + }; + ( $id:expr, $key:expr, $err:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request($id, $key, $err, None); + } + }; ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => { if let Some(ins) = crate::get_current_perf_instance() { ins.end_request($id, $key, $err, $bytes); } + }; +} + + +#[macro_export] +macro_rules! perf_simple_scope_request { + ( $id:expr ) => { + let __perf_simple_scope_request = crate::PerfScopeRequest::new($id); } } + #[macro_export] macro_rules! perf_acc { + ($id:expr) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.acc($id, cyfs_base::BuckyErrorCode::Ok, None); + } + }; + ($id:expr, $err:expr) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.acc($id, $err, None); + } + }; ( $id:expr, $err:expr, $size:expr ) => { if let Some(ins) = crate::get_current_perf_instance() { ins.acc($id, $err, $size); } - } + }; } #[macro_export] diff --git a/src/component/cyfs-base/src/perf/dummy.rs b/src/component/cyfs-base/src/perf/dummy.rs index 3b918ec91..913b908d0 100644 --- a/src/component/cyfs-base/src/perf/dummy.rs +++ b/src/component/cyfs-base/src/perf/dummy.rs @@ -3,6 +3,13 @@ macro_rules! declare_module_perf_isolate { ( $id:expr ) => {}; } +#[macro_export] +macro_rules! perf_scope_request { + ( $id:expr, $block:block ) => { + $block + }; +} + #[macro_export] macro_rules! perf_begin_request { ( $id:expr, $key:expr ) => {}; @@ -10,11 +17,20 @@ macro_rules! perf_begin_request { #[macro_export] macro_rules! perf_end_request { + ( $id:expr, $key:expr ) => {}; + ( $id:expr, $key:expr, $err:expr ) => {}; ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => {}; } +#[macro_export] +macro_rules! perf_simple_scope_request { + ( $id:expr ) => {}; +} + #[macro_export] macro_rules! perf_acc { + ($id:expr) => {}; + ($id:expr, $err:expr) => {}; ( $id:expr, $err:expr, $size:expr ) => {}; } From 984a3df3d0dd9366e83af2dee44bc42f72e831c4 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 16:23:02 +0800 Subject: [PATCH 162/553] Add some perf stub codec into cyfs-noc and cyfs-lib projects --- src/component/cyfs-lib/src/lib.rs | 5 +++- src/component/cyfs-noc/Cargo.toml | 2 +- src/component/cyfs-noc/src/lib.rs | 4 +++- src/component/cyfs-noc/src/meta/sqlite/db.rs | 24 ++++++++++--------- .../cyfs-stack/src/stack/cyfs_stack.rs | 4 ++-- src/tests/cyfs-stack-test/src/case/mod.rs | 7 +++--- src/tests/cyfs-stack-test/src/case/perf.rs | 2 +- 7 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index 80b572e2c..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -53,8 +53,11 @@ pub fn register_core_objects_format() { FORMAT_FACTORY.register(cyfs_core::CoreObjectType::Admin, format_json::); } +cyfs_base::declare_module_perf_isolate!("cyfs-lib"); + #[cfg(test)] mod tests { #[test] - fn main() {} + fn main() { + } } diff --git a/src/component/cyfs-noc/Cargo.toml b/src/component/cyfs-noc/Cargo.toml index 39fc1ff83..ce8b9608a 100644 --- a/src/component/cyfs-noc/Cargo.toml +++ b/src/component/cyfs-noc/Cargo.toml @@ -17,7 +17,7 @@ async-trait = "0.1.53" lazy_static = "1.4" cyfs-util = { path = "../../component/cyfs-util" } cyfs-lib = { path = "../../component/cyfs-lib" } -cyfs-base = { path = "../../component/cyfs-base" } +cyfs-base = { path = "../../component/cyfs-base", features = ["perf"]} cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-core = { path = "../../component/cyfs-core" } async-std = { version = "1.11", features = ["unstable", "attributes"] } diff --git a/src/component/cyfs-noc/src/lib.rs b/src/component/cyfs-noc/src/lib.rs index aa801b1ba..438e04a2e 100644 --- a/src/component/cyfs-noc/src/lib.rs +++ b/src/component/cyfs-noc/src/lib.rs @@ -9,4 +9,6 @@ mod noc; pub use noc::*; #[macro_use] -extern crate log; \ No newline at end of file +extern crate log; + +cyfs_base::declare_module_perf_isolate!("cyfs-noc"); \ No newline at end of file diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index bcd8aeb1e..645441d12 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -1306,53 +1306,55 @@ impl NamedObjectMeta for SqliteMetaStorage { &self, req: &NamedObjectMetaPutObjectRequest, ) -> BuckyResult { - self.update(req).await + perf_scope_request!("noc.meta.put_object", { self.update(req).await }) } async fn get_object( &self, req: &NamedObjectMetaGetObjectRequest, ) -> BuckyResult> { - self.get(req).await + perf_scope_request!("noc.meta.get_object", { self.get(req).await }) } async fn delete_object( &self, req: &NamedObjectMetaDeleteObjectRequest, ) -> BuckyResult { - self.delete(req).await + perf_scope_request!("noc.meta.delete_object", { self.delete(req).await }) } async fn exists_object(&self, req: &NamedObjectMetaExistsObjectRequest) -> BuckyResult { - self.exists(req) + perf_scope_request!("noc.meta.exists_object", { self.exists(req) }) } async fn update_last_access( &self, req: &NamedObjectMetaUpdateLastAccessRequest, ) -> BuckyResult { - match Self::update_last_access(&self, req)? { - n if n >= 1 => Ok(true), - _ => Ok(false), - } + perf_scope_request!("noc.meta.update_last_access", { + match Self::update_last_access(&self, req)? { + n if n >= 1 => Ok::(true), + _ => Ok(false), + } + }) } async fn update_object_meta( &self, req: &NamedObjectMetaUpdateObjectMetaRequest, ) -> BuckyResult<()> { - Self::update_object_meta(&self, req).await + perf_scope_request!("noc.meta.update_object_meta", { Self::update_object_meta(&self, req).await }) } async fn check_object_access( &self, req: &NamedObjectMetaCheckObjectAccessRequest, ) -> BuckyResult> { - Self::check_object_access(&self, req).await + perf_scope_request!("noc.meta.check_object_access", { Self::check_object_access(&self, req).await }) } async fn stat(&self) -> BuckyResult { - Self::stat(&self).await + perf_scope_request!("noc.meta.stat", { Self::stat(&self).await }) } fn bind_object_meta_access_provider( diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index d562319ca..f03d529e9 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -1051,7 +1051,7 @@ impl CyfsStackImpl { None, PerfConfig { reporter: PerfServerConfig::Default, - save_to_file: false, + save_to_file: true, report_interval: std::time::Duration::from_secs(60 * 10), }, self.open_uni_stack(&None).await, @@ -1068,7 +1068,7 @@ impl CyfsStackImpl { } info!("init perf manager success! current={}", info.device_id); - + Ok(()) } } diff --git a/src/tests/cyfs-stack-test/src/case/mod.rs b/src/tests/cyfs-stack-test/src/case/mod.rs index 25a71bee3..f1d5bde1b 100644 --- a/src/tests/cyfs-stack-test/src/case/mod.rs +++ b/src/tests/cyfs-stack-test/src/case/mod.rs @@ -45,8 +45,6 @@ pub async fn test() { // role::test().await; - // meta::test().await; - // crypto::test().await; noc::test().await; @@ -60,6 +58,9 @@ pub async fn test() { ndn::test().await; call::test().await; object_meta_access::test().await; + + async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; + return; test_restart().await; @@ -69,7 +70,7 @@ pub async fn test() { // test_drive::test().await; events::test().await; - // crypto::test().await; + zone::test().await; non_handlers::test().await; diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index 66cde49c7..7df91fe42 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -17,7 +17,7 @@ fn new_dec(name: &str) -> ObjectId { pub async fn test() { let dec_id = new_dec("test-perf"); let stack = TestLoader::get_shared_stack(DeviceIndex::User1Device2); - stack.online().await; + stack.online().await.unwrap(); let device = stack.local_device(); let owner = device.desc().owner().as_ref().unwrap().clone(); let device_id = device.desc().device_id(); From 5852523161ef8a6785cd226c37d2febf92ef24d8 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Sat, 25 Feb 2023 17:20:14 +0800 Subject: [PATCH 163/553] Perf-client use post_object when send perf to other device --- src/Cargo.lock | 3 +- .../cyfs-perf/cyfs-perf-base/Cargo.toml | 3 +- .../cyfs-perf/cyfs-perf-base/src/lib.rs | 14 ++- .../cyfs-perf-client/src/reporter.rs | 90 +++++++++---------- 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 7f1d76f21..1d9ae081b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2127,7 +2127,7 @@ dependencies = [ [[package]] name = "cyfs-perf-base" -version = "0.6.1" +version = "0.6.2" dependencies = [ "async-std", "cyfs-base", @@ -2135,6 +2135,7 @@ dependencies = [ "cyfs-lib", "cyfs-util", "int-enum", + "lazy_static", "log 0.4.17", "protobuf", "protoc-bin-vendored", diff --git a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml index 0320550cc..9ff1ed0a6 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-perf-base' -version = '0.6.1' +version = '0.6.2' authors = ['wangzhi '] edition = '2021' license = 'BSD-2-Clause' @@ -21,6 +21,7 @@ int-enum = '0.4' protobuf = { version = '2', features = ['with-bytes'] } serde = { version = '1.0', features = ['derive'] } serde_json = '1.0' +lazy_static = "1.4" [dev-dependencies] async-std = { version = '1.11', features = ['attributes'] } diff --git a/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs b/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs index 62fbd7928..728b5a584 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs +++ b/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs @@ -3,6 +3,18 @@ mod items; mod perf; mod merge; +#[macro_use] +extern crate lazy_static; + +use cyfs_base::ObjectId; +use std::str::FromStr; + pub use items::*; pub use perf::*; -pub use merge::*; \ No newline at end of file +pub use merge::*; + +lazy_static! { + pub static ref PERF_DEC_ID: ObjectId = ObjectId::from_str("9tGpLNnAAYE9Dd4ooNiSjtP5MeL9CNLf9Rxu6AFEc12M").unwrap(); +} + +pub static PERF_REPORT_PATH: &str = "/.perf/report"; \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index 5d386c0e0..a8bedb2ba 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -142,7 +142,7 @@ impl PerfReporterInner { let perf_server = self.perf_server.as_ref().map(|id| id.object_id().to_owned()); - match self.put_object(&perf_obj, perf_server, 0, self.save_to_local).await { + match self.send_perf(perf_obj, perf_server, self.save_to_local).await { Ok(_) => { info!( "report perf success! id={}, target={:?}, perf_object={}", @@ -161,61 +161,59 @@ impl PerfReporterInner { } // NON_REQUEST_FLAG_SIGN_BY_DEVICE | NON_REQUEST_FLAG_SIGN_SET_DESC | NON_REQUEST_FLAG_SIGN_SET_BODY - pub async fn put_object( + pub async fn send_perf( &self, - obj: &Perf, + obj: Perf, target: Option, - sign_flags: u32, save_to_local: bool ) -> BuckyResult<()> { - let raw; + let raw= obj.to_vec().unwrap(); let object_id = obj.desc().calculate_id(); - if sign_flags != 0 { - let object_raw = obj.to_vec().unwrap(); - let req = CryptoSignObjectRequest::new(object_id.clone(), object_raw, sign_flags); - // 先给Obj签名, 用Client的Device - let resp = self.cyfs_stack.crypto_service().sign_object(req).await - .map_err(|e| { - error!("{} sign failed, err {}", &object_id, e); - e - })?; - raw = resp.object.unwrap().object_raw; + // 如果存到本地,就直接用put + if save_to_local { + let mut req = NONPutObjectOutputRequest::new( + NONAPILevel::NOC, + object_id.clone(), raw); + req.common.dec_id = Some(PERF_DEC_ID.clone()); + match self.cyfs_stack.non_service().put_object(req).await { + Ok(_) => { + info!("### save perf obj {} to local success!", &object_id); + Ok(()) + } + Err(e) => { + error!("### save perf obj {} to local failed! {}", &object_id, e); + Err(e) + } + }?; + // 存到root_state + let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); + req.common.target = target.clone(); + req.common.target_dec_id = self.dec_id.clone(); + + let resp = self.cyfs_stack.root_state().create_op_env(req).await?; + let path_env = PathOpEnvStub::new(resp, target.clone(), self.dec_id.clone()); + let key = obj.get_time_range().to_string(); + path_env.set_with_key("/stat", key, &object_id, None, true).await?; + path_env.commit().await?; } else { - raw = obj.to_vec().unwrap(); + let mut req = NONPostObjectRequest::new_router(target, object_id.clone(), raw); + req.common.dec_id = Some(PERF_DEC_ID.clone()); + req.common.req_path = Some(PERF_REPORT_PATH.to_owned()); + let str_target = target.map_or("ood".to_owned(), |id| id.to_string()); + match self.cyfs_stack.non_service().post_object(req).await { + Ok(_) => { + info!("### send perf obj {} to {} success!", &object_id, str_target); + Ok(()) + } + Err(e) => { + error!("### send perf obj {} to {} failed! {}", &object_id, str_target, e); + Err(e) + } + }?; } - // 把obj再put出去 - let target = if save_to_local { None } else { target }; - let mut req = NONPutObjectOutputRequest::new( - if save_to_local { NONAPILevel::NOC } else { NONAPILevel::Router }, - object_id.clone(), raw); - req.common.target = target.clone(); - req.common.dec_id = obj.desc().dec_id().clone(); - let str_target = if save_to_local { "local".to_owned() } else {target.map_or("ood".to_owned(), |id| id.to_string())}; - match self.cyfs_stack.non_service().put_object(req).await { - Ok(_) => { - info!("### put perf obj {} to {} success!", &object_id, str_target); - Ok(()) - } - Err(e) => { - error!("### put perf obj [{}] to {} failed! {}", &object_id, str_target, e); - Err(e) - } - }?; - - // 存到root_state - let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); - req.common.target = target.clone(); - req.common.target_dec_id = self.dec_id.clone(); - - let resp = self.cyfs_stack.root_state().create_op_env(req).await?; - let path_env = PathOpEnvStub::new(resp, target.clone(), self.dec_id.clone()); - let key = obj.get_time_range().to_string(); - path_env.set_with_key("/stat", key, &object_id, None, true).await?; - path_env.commit().await?; - Ok(()) } } From e141b3e0e56410e692a698f5afc961603e1dfa1e Mon Sep 17 00:00:00 2001 From: tsukasa Date: Sat, 25 Feb 2023 18:50:35 +0800 Subject: [PATCH 164/553] Modify: add reset known sn method to bdt stack --- src/component/cyfs-bdt/examples/call_with_tcp.rs | 2 +- src/component/cyfs-bdt/examples/sn_with_ipv6.rs | 2 +- src/component/cyfs-bdt/examples/use_next_sn.rs | 2 +- src/component/cyfs-bdt/src/sn/client/cache.rs | 10 +++++++++- src/component/cyfs-bdt/src/stack.rs | 14 ++++++++------ src/component/cyfs-bdt/tests/sn.rs | 11 +++++------ 6 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/component/cyfs-bdt/examples/call_with_tcp.rs b/src/component/cyfs-bdt/examples/call_with_tcp.rs index c0693c515..e3ddab943 100644 --- a/src/component/cyfs-bdt/examples/call_with_tcp.rs +++ b/src/component/cyfs-bdt/examples/call_with_tcp.rs @@ -91,7 +91,7 @@ async fn main() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>>(1); diff --git a/src/component/cyfs-bdt/examples/sn_with_ipv6.rs b/src/component/cyfs-bdt/examples/sn_with_ipv6.rs index eb3fe568f..78a74ce7a 100644 --- a/src/component/cyfs-bdt/examples/sn_with_ipv6.rs +++ b/src/component/cyfs-bdt/examples/sn_with_ipv6.rs @@ -95,7 +95,7 @@ async fn main() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>>(1); diff --git a/src/component/cyfs-bdt/examples/use_next_sn.rs b/src/component/cyfs-bdt/examples/use_next_sn.rs index b83baa77e..0a7cb4990 100644 --- a/src/component/cyfs-bdt/examples/use_next_sn.rs +++ b/src/component/cyfs-bdt/examples/use_next_sn.rs @@ -111,7 +111,7 @@ async fn main() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn1.clone(), sn2.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); diff --git a/src/component/cyfs-bdt/src/sn/client/cache.rs b/src/component/cyfs-bdt/src/sn/client/cache.rs index 4d54b4f94..a469764c8 100644 --- a/src/component/cyfs-bdt/src/sn/client/cache.rs +++ b/src/component/cyfs-bdt/src/sn/client/cache.rs @@ -26,8 +26,16 @@ impl SnCache { for sn in sn_list { known_list.insert(sn.clone()); } - } + + pub fn reset_known_sn(&self, sn_list: &Vec) { + let mut known_list = self.known_list.write().unwrap(); + known_list.clear(); + for sn in sn_list { + known_list.insert(sn.clone()); + } + } + pub fn nearest_sn_of(remote: &DeviceId, sn_list: &[DeviceId]) -> Option { sn_list.iter().min_by(|l, r| l.object_id().distance(remote.object_id()).cmp(&r.object_id().distance(remote.object_id()))).cloned() } diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index a20becf1a..c7f556e85 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -378,8 +378,7 @@ impl Stack { if params.known_sn.is_some() { std::mem::swap(&mut known_sn, params.known_sn.as_mut().unwrap()); } - stack.reset_sn_list(known_sn); - + stack.reset_known_sn(known_sn.clone()); stack.ndn().start(); if let Some(debug_stub) = debug_stub { @@ -465,13 +464,16 @@ impl Stack { pub fn reset_sn_list(&self, sn_list: Vec) -> PingClients { let sn_id_list: Vec = sn_list.iter().map(|sn| sn.desc().device_id()).collect(); info!("{} reset_sn_list {:?}", self, sn_id_list); - + self.sn_client().reset_sn_list(sn_list) + } + + pub fn reset_known_sn(&self, sn_list: Vec) { + let sn_id_list: Vec = sn_list.iter().map(|sn| sn.desc().device_id()).collect(); + info!("{} reset_known_sn_list {:?}", self, sn_id_list); for (id, sn) in sn_id_list.iter().zip(sn_list.iter()) { self.device_cache().add_static(id, sn); } - self.sn_client().cache().add_known_sn(&sn_id_list); - - self.sn_client().reset_sn_list(sn_list) + self.sn_client().cache().reset_known_sn(&sn_id_list); } pub async fn reset_endpoints(&self, endpoints: &Vec) -> PingClients { diff --git a/src/component/cyfs-bdt/tests/sn.rs b/src/component/cyfs-bdt/tests/sn.rs index 816487a16..7d475babe 100644 --- a/src/component/cyfs-bdt/tests/sn.rs +++ b/src/component/cyfs-bdt/tests/sn.rs @@ -80,7 +80,7 @@ async fn call_sn_without_ping() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -168,8 +168,7 @@ async fn reset_sn_list() { rn_dev, rn_secret, rn_params).await.unwrap(); - - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn1.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -288,7 +287,7 @@ async fn use_next_sn() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn1.clone(), sn2.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -358,7 +357,7 @@ async fn call_with_tcp() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -428,7 +427,7 @@ async fn sn_with_ipv6() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); From 77ecc8cec4524e2ff0406dd59e03ada3023fcc03 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Sat, 25 Feb 2023 19:03:51 +0800 Subject: [PATCH 165/553] NamedDataClient use bdt no-sn mode, not listen on tcp port --- src/service/app-manager/src/app_controller.rs | 2 +- src/tools/cyfs-client/src/named_data_client.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/service/app-manager/src/app_controller.rs b/src/service/app-manager/src/app_controller.rs index 0baf92a32..ec07fb2bc 100644 --- a/src/service/app-manager/src/app_controller.rs +++ b/src/service/app-manager/src/app_controller.rs @@ -104,7 +104,7 @@ impl AppController { let old_hash = this.sn_hash.read().unwrap().clone(); if old_hash != sn_hash { info!("sn list from stack changed, {:?}", &sn_list); - match this.named_cache_client.get().unwrap().reset_sn_list(sn_list).await { + match this.named_cache_client.get().unwrap().reset_known_sn_list(sn_list) { Ok(_) => { *this.sn_hash.write().unwrap() = sn_hash; } diff --git a/src/tools/cyfs-client/src/named_data_client.rs b/src/tools/cyfs-client/src/named_data_client.rs index 87b4776fd..0f676297d 100644 --- a/src/tools/cyfs-client/src/named_data_client.rs +++ b/src/tools/cyfs-client/src/named_data_client.rs @@ -187,7 +187,6 @@ impl NamedCacheClient { let port = rand::thread_rng().gen_range(30000, 50000) as u16; for ip in cyfs_util::get_all_ips().unwrap() { if ip.is_ipv4() { - endpoints.push(Endpoint::from((Protocol::Tcp, ip, port))); endpoints.push(Endpoint::from((Protocol::Udp, ip, port))); } } @@ -242,12 +241,12 @@ impl NamedCacheClient { } } - pub async fn reset_sn_list(&self, sn_list: Vec) -> BuckyResult<()> { + pub fn reset_known_sn_list(&self, sn_list: Vec) -> BuckyResult<()> { if let Some(stack) = self.stack.get() { info!("named data client reset sn list {:?}", sn_list.iter().map(|device|{ device.desc().calculate_id() }).collect::>()); - stack.reset_sn_list(sn_list).wait_online().await?; + stack.reset_known_sn(sn_list); Ok(()) } else { Err(BuckyError::from(BuckyErrorCode::NotInit)) From 493dda7034724dcf00c9513bb5f2f721fb89ac46 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 17:21:12 +0800 Subject: [PATCH 166/553] Fix a panic that may be caused by an object field being empty in cyfs-noc --- src/component/cyfs-lib/src/non/def.rs | 21 +++++++++++++++++++++ src/component/cyfs-noc/src/storage/local.rs | 10 +++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-lib/src/non/def.rs b/src/component/cyfs-lib/src/non/def.rs index 82c97a02d..7845871bf 100644 --- a/src/component/cyfs-lib/src/non/def.rs +++ b/src/component/cyfs-lib/src/non/def.rs @@ -5,6 +5,7 @@ use serde_json::{Map, Value}; use std::fmt; use std::str::FromStr; use std::sync::Arc; +use std::borrow::Cow; // 请求的数据类型 #[derive(Clone)] @@ -251,6 +252,26 @@ impl NONObjectInfo { self.object.as_ref().unwrap() } + + pub fn object_if_none_then_decode(&self) -> BuckyResult> { + match &self.object { + Some(object) => { + Ok(Cow::Borrowed(object.as_ref())) + } + None => { + let (object, _) = AnyNamedObject::raw_decode(&self.object_raw).map_err(|e| { + error!( + "decode object from object_raw error: obj={} {}", + self.object_id, e, + ); + e + })?; + + Ok(Cow::Owned(object)) + } + } + } + pub fn take_object(&mut self) -> Arc { self.object.take().unwrap() } diff --git a/src/component/cyfs-noc/src/storage/local.rs b/src/component/cyfs-noc/src/storage/local.rs index 3d7345f34..93e27b6f4 100644 --- a/src/component/cyfs-noc/src/storage/local.rs +++ b/src/component/cyfs-noc/src/storage/local.rs @@ -71,7 +71,7 @@ impl NamedObjectLocalStorage { &self, request: &NamedObjectCachePutObjectRequest, ) -> BuckyResult { - let meta_req = self.gen_meta_put_request(request); + let meta_req = self.gen_meta_put_request(request)?; let meta_ret = self.meta.put_object(&meta_req).await?; info!( @@ -145,8 +145,8 @@ impl NamedObjectLocalStorage { fn gen_meta_put_request( &self, request: &NamedObjectCachePutObjectRequest, - ) -> NamedObjectMetaPutObjectRequest { - let obj = request.object.object.as_ref().unwrap(); + ) -> BuckyResult { + let obj = request.object.object_if_none_then_decode()?; let object_create_time = match obj.create_time() { 0 => None, @@ -169,7 +169,7 @@ impl NamedObjectLocalStorage { None => AccessString::default().value(), }; - NamedObjectMetaPutObjectRequest { + Ok(NamedObjectMetaPutObjectRequest { source: request.source.clone(), object_id: request.object.object_id.clone(), owner_id, @@ -190,7 +190,7 @@ impl NamedObjectLocalStorage { context: request.context.clone(), last_access_rpath: request.last_access_rpath.clone(), access_string, - } + }) } fn merge_body_and_signs( From 53ca55a02952efecbcea1707627f22feac21ca28 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 17:24:41 +0800 Subject: [PATCH 167/553] Ensure that the object field is not empty during the non output->input direct conversion --- src/component/cyfs-stack/src/non/transform.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-stack/src/non/transform.rs b/src/component/cyfs-stack/src/non/transform.rs index 486928cdb..f17e3565e 100644 --- a/src/component/cyfs-stack/src/non/transform.rs +++ b/src/component/cyfs-stack/src/non/transform.rs @@ -218,8 +218,11 @@ impl NONOutputTransformer { async fn put_object( &self, - req: NONPutObjectOutputRequest, + mut req: NONPutObjectOutputRequest, ) -> BuckyResult { + // Make sure the object field is not empty! + req.object.try_decode()?; + let in_req = NONPutObjectInputRequest { common: self.convert_common(req.common), @@ -263,8 +266,11 @@ impl NONOutputTransformer { async fn post_object( &self, - req: NONPostObjectOutputRequest, + mut req: NONPostObjectOutputRequest, ) -> BuckyResult { + // Make sure the object field is not empty! + req.object.try_decode()?; + let in_req = NONPostObjectInputRequest { common: self.convert_common(req.common), From 3435fd0c3c924eb57dd91b51be7dac44b8a1872c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 18:47:38 +0800 Subject: [PATCH 168/553] Add sn_mode to cyfs-stack and loaders --- .../cyfs-bdt-ext/src/sn/sn_config.rs | 91 +++++++++++++------ src/component/cyfs-bdt-ext/src/stack/param.rs | 48 +++++++++- src/component/cyfs-bdt-ext/src/stack/stack.rs | 73 ++++++--------- .../cyfs-stack-loader/src/bdt_loader.rs | 35 +++++++ .../src/cyfs_loader_config.rs | 3 +- .../cyfs-stack-loader/src/stack_info.rs | 1 + .../cyfs-stack/src/config/sn_config.rs | 5 +- .../src/root_state_api/core/test.rs | 1 + 8 files changed, 179 insertions(+), 78 deletions(-) diff --git a/src/component/cyfs-bdt-ext/src/sn/sn_config.rs b/src/component/cyfs-bdt-ext/src/sn/sn_config.rs index 91d32bf9f..70051612e 100644 --- a/src/component/cyfs-bdt-ext/src/sn/sn_config.rs +++ b/src/component/cyfs-bdt-ext/src/sn/sn_config.rs @@ -1,19 +1,21 @@ +use crate::stack::SNMode; use cyfs_base::*; -use cyfs_bdt::{retry_sn_list_when_offline, SnStatus, StackGuard}; +use cyfs_bdt::{retry_sn_list_when_offline, sn::client::PingClients, SnStatus, StackGuard}; use once_cell::sync::OnceCell; use std::sync::Arc; -use std::time::Duration; #[derive(Clone)] pub struct BdtStackSNHelper { bdt_stack: Arc>, + sn_mode: SNMode, } impl BdtStackSNHelper { - pub fn new() -> Self { + pub fn new(sn_mode: SNMode) -> Self { Self { bdt_stack: Arc::new(OnceCell::new()), + sn_mode, } } @@ -23,37 +25,72 @@ impl BdtStackSNHelper { } } - pub async fn on_sn_list_changed(&self, sn_list: Vec) { + pub async fn on_sn_list_changed(&self, config_sn_list: Vec) { // notify bdt stack if let Some(bdt_stack) = self.bdt_stack.get() { - let ping_clients = bdt_stack.reset_sn_list(sn_list); - match ping_clients.wait_online().await { - Err(err) => { - error!("reset bdt sn list error! {}", err); + let sn_list = match self.sn_mode { + SNMode::Normal => Some(config_sn_list.clone()), + SNMode::None => { + warn!("sn_mode is none, now will clear the sn_list!"); + None } - Ok(status) => match status { - SnStatus::Online => { - info!("reset bdt sn list success!"); - let bdt_stack = bdt_stack.clone(); - async_std::task::spawn(async move { - let _ = ping_clients.wait_offline().await; - retry_sn_list_when_offline( - bdt_stack.clone(), - ping_clients, - Duration::from_secs(30), - ); - }); - } - SnStatus::Offline => { - error!("reset bdt sn list error! offline"); + }; + + bdt_stack.reset_known_sn(config_sn_list); + + if let Some(sn_list) = sn_list { + let ping_clients = bdt_stack.reset_sn_list(sn_list); + Self::wait_sn_online(&bdt_stack, ping_clients).await; + } + } + } + + pub async fn wait_sn_online(bdt_stack: &StackGuard, ping_clients: PingClients) { + // Waiting for SN to go online + info!( + "now will wait for sn online {}......", + bdt_stack.local_device_id() + ); + let begin = std::time::Instant::now(); + match ping_clients.wait_online().await { + Err(e) => { + error!( + "bdt stack wait sn online failed! {}, during={}ms, {}", + bdt_stack.local_device_id(), + begin.elapsed().as_millis(), + e + ); + } + Ok(status) => match status { + SnStatus::Online => { + info!( + "bdt stack sn online success! {}, during={}ms", + bdt_stack.local_device_id(), + begin.elapsed().as_millis(), + ); + let bdt_stack = bdt_stack.clone(); + async_std::task::spawn(async move { + let _ = ping_clients.wait_offline().await; retry_sn_list_when_offline( bdt_stack.clone(), ping_clients, - Duration::from_secs(30), + std::time::Duration::from_secs(30), ); - } - }, - } + }); + } + SnStatus::Offline => { + error!( + "bdt stack wait sn online failed! {}, during={}ms, offline", + bdt_stack.local_device_id(), + begin.elapsed().as_millis(), + ); + retry_sn_list_when_offline( + bdt_stack.clone(), + ping_clients, + std::time::Duration::from_secs(30), + ); + } + }, } } } diff --git a/src/component/cyfs-bdt-ext/src/stack/param.rs b/src/component/cyfs-bdt-ext/src/stack/param.rs index 8934f311d..c287f2cba 100644 --- a/src/component/cyfs-bdt-ext/src/stack/param.rs +++ b/src/component/cyfs-bdt-ext/src/stack/param.rs @@ -1,5 +1,50 @@ use cyfs_base::*; +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum SNMode { + Normal, + None, +} + +impl SNMode { + pub fn as_str(&self) -> &str { + match *self { + Self::Normal => "normal", + Self::None => "none", + } + } +} + +impl Default for SNMode { + fn default() -> Self { + Self::Normal + } +} + +impl std::fmt::Display for SNMode { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl std::str::FromStr for SNMode { + type Err = BuckyError; + + fn from_str(str: &str) -> BuckyResult { + let ret = match str { + "normal" => Self::Normal, + "none" => Self::None, + _ => { + let msg = format!("unknown SNMode {}", str); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + } + }; + + Ok(ret) + } +} + #[derive(Clone)] pub struct BdtStackParams { pub device: Device, @@ -9,4 +54,5 @@ pub struct BdtStackParams { pub known_device: Vec, pub known_passive_pn: Vec, pub udp_sn_only: Option, -} \ No newline at end of file + pub sn_mode: SNMode, +} diff --git a/src/component/cyfs-bdt-ext/src/stack/stack.rs b/src/component/cyfs-bdt-ext/src/stack/stack.rs index 32050c4ea..c854f3c58 100644 --- a/src/component/cyfs-bdt-ext/src/stack/stack.rs +++ b/src/component/cyfs-bdt-ext/src/stack/stack.rs @@ -1,6 +1,8 @@ use super::com::*; use super::param::*; use crate::context::ContextManager; +use crate::sn::BdtStackSNHelper; + use cyfs_base::*; use cyfs_bdt::*; use cyfs_chunk_cache::{ChunkManager, ChunkManagerRef}; @@ -74,6 +76,20 @@ impl BdtStackHelper { bdt_params.config.interface.udp.sn_only = sn_only; } + // select sn_list via the sn_mode config + let wait_online; + let sn_list = match params.sn_mode { + SNMode::Normal => { + wait_online = true; + Some(params.known_sn.clone()) + } + SNMode::None => { + wait_online = false; + warn!("sn_mode is none, now will clear the sn_list!"); + None + } + }; + bdt_params.known_sn = Some(params.known_sn); if !params.known_device.is_empty() { @@ -84,7 +100,7 @@ impl BdtStackHelper { } bdt_params.outer_cache = Some(device_cache); bdt_params.chunk_store = Some(chunk_store); - + bdt_params.ndn_event = ndn_event; let ret = Stack::open(params.device, params.secret, bdt_params).await; @@ -96,52 +112,15 @@ impl BdtStackHelper { let bdt_stack = ret.unwrap(); - // 等待sn上线 - info!( - "now will wait for sn online {}......", - bdt_stack.local_device_id() - ); - let begin = std::time::Instant::now(); - let ping_clients = bdt_stack.sn_client().ping(); - match ping_clients.wait_online().await { - Err(e) => { - error!( - "bdt stack wait sn online failed! {}, during={}ms, {}", - bdt_stack.local_device_id(), - begin.elapsed().as_millis(), - e - ); - } - Ok(status) => match status { - SnStatus::Online => { - info!( - "bdt stack sn online success! {}, during={}ms", - bdt_stack.local_device_id(), - begin.elapsed().as_millis(), - ); - let bdt_stack = bdt_stack.clone(); - async_std::task::spawn(async move { - let _ = ping_clients.wait_offline().await; - retry_sn_list_when_offline( - bdt_stack.clone(), - ping_clients, - std::time::Duration::from_secs(30), - ); - }); - } - SnStatus::Offline => { - error!( - "bdt stack wait sn online failed! {}, during={}ms, offline", - bdt_stack.local_device_id(), - begin.elapsed().as_millis(), - ); - retry_sn_list_when_offline( - bdt_stack.clone(), - ping_clients, - std::time::Duration::from_secs(30), - ); - } - }, + // apply the sn list + let ping_clients = if let Some(sn_list) = sn_list { + bdt_stack.sn_client().reset_sn_list(sn_list) + } else { + bdt_stack.sn_client().ping() + }; + + if wait_online { + BdtStackSNHelper::wait_sn_online(&bdt_stack, ping_clients).await; } Ok(bdt_stack) diff --git a/src/component/cyfs-stack-loader/src/bdt_loader.rs b/src/component/cyfs-stack-loader/src/bdt_loader.rs index 670086932..bfe863d86 100644 --- a/src/component/cyfs-stack-loader/src/bdt_loader.rs +++ b/src/component/cyfs-stack-loader/src/bdt_loader.rs @@ -1,5 +1,6 @@ use crate::VAR_MANAGER; use cyfs_base::*; +use cyfs_bdt_ext::SNMode; use cyfs_util::TomlHelper; use std::str::FromStr; @@ -13,6 +14,9 @@ const BDT_PORT_KEY: &str = "CYFS_BDT_PORT"; // udp_sn_only const UDP_SN_ONLY_KEY: &str = "CYFS_UDP_SN_ONLY"; +// sn_mode +const SN_MODE_KEY: &str = "CYFS_SN_MODE"; + // bdt层的配置参数 pub(crate) struct BdtParams { pub device: String, @@ -24,6 +28,8 @@ pub(crate) struct BdtParams { // disable udp transport but sn online via udp pub udp_sn_only: Option, + + pub sn_mode: SNMode, } impl Default for BdtParams { @@ -34,6 +40,7 @@ impl Default for BdtParams { endpoint: vec![], tcp_port_mapping: None, udp_sn_only: None, + sn_mode: SNMode::default(), } } } @@ -123,6 +130,9 @@ impl BdtConfigLoader { "udp_sn_only" => { self.params.udp_sn_only = Some(TomlHelper::decode_from_boolean(v)?); } + "sn_mode" => { + self.params.sn_mode = TomlHelper::decode_from_string(v)?; + } _ => { warn!("unknown stack.bdt.config field: {}", k.as_str()); } @@ -133,6 +143,10 @@ impl BdtConfigLoader { self.params.udp_sn_only = Some(udp_sn_only); } + if let Some(sn_mode) = Self::load_sn_mode_from_env() { + self.params.sn_mode = sn_mode; + } + Ok(()) } @@ -349,4 +363,25 @@ impl BdtConfigLoader { Err(_) => None, } } + + fn load_sn_mode_from_env() -> Option { + match std::env::var(SN_MODE_KEY) { + Ok(val) => { + info!( + "got sn_mode from env var: env={}, val={}", + SN_MODE_KEY, val + ); + + let value = val.trim(); + match SNMode::from_str(&value) { + Ok(v) => Some(v), + Err(e) => { + error!("invalid sn_mode value got from env! val={}, {}", value, e); + None + } + } + } + Err(_) => None, + } + } } diff --git a/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs b/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs index 919bf0194..8c32bfe22 100644 --- a/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs +++ b/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs @@ -39,6 +39,7 @@ const BDT_CONFIG: &str = r#" #tcp_port_mapping = 0 device = "${device_file_name}" #udp_sn_only = false +#sn_mode = "normal" ${endpoints} "#; @@ -73,7 +74,7 @@ type = "ws" enable = ${ws_enable} listen = "${ws_listener}" -# bdt配置部分,可替换默认值 +# bdt configuration part, can replace the default value ${bdt_config} "#; diff --git a/src/component/cyfs-stack-loader/src/stack_info.rs b/src/component/cyfs-stack-loader/src/stack_info.rs index c7f048a86..13c49c032 100644 --- a/src/component/cyfs-stack-loader/src/stack_info.rs +++ b/src/component/cyfs-stack-loader/src/stack_info.rs @@ -153,6 +153,7 @@ impl StackInfo { known_passive_pn: init_pn_peers, known_device: init_known_peers, udp_sn_only: self.bdt_params.udp_sn_only, + sn_mode: self.bdt_params.sn_mode, }; bdt_param diff --git a/src/component/cyfs-stack/src/config/sn_config.rs b/src/component/cyfs-stack/src/config/sn_config.rs index 2d4eccd96..052a37ecb 100644 --- a/src/component/cyfs-stack/src/config/sn_config.rs +++ b/src/component/cyfs-stack/src/config/sn_config.rs @@ -82,11 +82,12 @@ impl SNConfigManager { meta_cache, root_state, noc, - config, sn_list: Arc::new(Mutex::new(vec![])), coll: Arc::new(OnceCell::new()), - bdt_stack: BdtStackSNHelper::new(), + bdt_stack: BdtStackSNHelper::new(config.get_bdt_params().sn_mode), + + config, } } diff --git a/src/component/cyfs-stack/src/root_state_api/core/test.rs b/src/component/cyfs-stack/src/root_state_api/core/test.rs index b32829707..c19d5617e 100644 --- a/src/component/cyfs-stack/src/root_state_api/core/test.rs +++ b/src/component/cyfs-stack/src/root_state_api/core/test.rs @@ -190,6 +190,7 @@ async fn create_global_state_manager() -> GlobalStateManager { known_device: vec![], known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Default, }; let config = StackGlobalConfig::new(params, bdt_params); From 3d42087d81ae477de7af0013091ff94892262e66 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 16:28:17 +0800 Subject: [PATCH 169/553] Fix task type mismatch error for chunk task in trans service --- .../src/trans_api/local/download_task_tracker.rs | 2 ++ .../src/trans_api/local/task/download_task.rs | 2 +- .../cyfs-task-manager/src/task_manager.rs | 14 +++++++++++++- src/component/cyfs-util/src/util/toml_helper.rs | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs b/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs index 0c134bcc9..d315fc92a 100644 --- a/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs +++ b/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs @@ -14,6 +14,8 @@ pub trait DownloadTaskTracker { #[async_trait::async_trait] impl DownloadTaskTracker for SqlConnection { async fn add_task_info(&mut self, task_id: &TaskId, context_id: &Option, task_status: TaskStatus, dec_list: Vec<(DeviceId, ObjectId)>) -> BuckyResult<()> { + info!("task tracker add task: id={}, context={:?}, dec_list={:?}", task_id, context_id, dec_list); + for (source, dec) in dec_list.iter() { let sql = r#"insert into download_task_tracker (source, dec_id, task_id, context_id, task_status) values (?1, ?2, ?3, ?4, ?5)"#; let context_id = if context_id.is_some() { diff --git a/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs b/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs index 33c1242d5..4b9d76842 100644 --- a/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs +++ b/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs @@ -410,7 +410,7 @@ impl Task for DownloadFileTask { } fn get_task_type(&self) -> TaskType { - DOWNLOAD_FILE_TASK + self.params.task_type } fn get_task_category(&self) -> TaskCategory { diff --git a/src/component/cyfs-task-manager/src/task_manager.rs b/src/component/cyfs-task-manager/src/task_manager.rs index ec3054da3..b623941ce 100644 --- a/src/component/cyfs-task-manager/src/task_manager.rs +++ b/src/component/cyfs-task-manager/src/task_manager.rs @@ -162,10 +162,22 @@ impl TaskManager { match self.get_task_factory(&task_type) { Some(factory) => { let param = task_param.to_vec()?; - let mut task = factory.create(param.as_slice()).await?; + let mut task = factory.create(param.as_slice()).await.map_err(|e| { + let msg = format!("create task failed! dec={}, source={}, task_type={}, {}", dec_id, source, task_type, e); + error!("{}", msg); + BuckyError::new(e.code(), msg) + })?; + + if task.get_task_type() != task_type { + let msg = format!("create task but task_type mismatch! dec={}, source={}, create task_type={}, got={}", dec_id, source, task_type, task.get_task_type()); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + if task.need_persist() { task.set_task_store(self.task_store.clone()).await; } + let task_id = task.get_task_id(); let _locker = Locker::get_locker(format!("task_manager_{}", task_id.to_string())).await; { diff --git a/src/component/cyfs-util/src/util/toml_helper.rs b/src/component/cyfs-util/src/util/toml_helper.rs index 67545c2c9..80b8ac116 100644 --- a/src/component/cyfs-util/src/util/toml_helper.rs +++ b/src/component/cyfs-util/src/util/toml_helper.rs @@ -19,7 +19,7 @@ impl TomlHelper { let v = T::from_str(v.as_str().unwrap()).map_err(|e| { let msg = format!( - "parse json string error: value={}, {}", + "parse toml string error: value={}, {}", v.as_str().unwrap(), e ); From 3fe72c3ee4ce285b1f6f8d22994ee0830e69f196 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 17:06:30 +0800 Subject: [PATCH 170/553] Improve test cases --- .../cyfs-stack-test/src/case/app_manager.rs | 15 +++++++++-- .../cyfs-stack-test/src/case/mnemonic.rs | 4 +++ src/tests/cyfs-stack-test/src/case/mod.rs | 26 ++++++++----------- src/tests/cyfs-stack-test/src/case/trans.rs | 5 ++++ src/tests/cyfs-stack-test/src/main.rs | 2 +- src/tools/pack-tools/Cargo.toml | 2 +- 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/tests/cyfs-stack-test/src/case/app_manager.rs b/src/tests/cyfs-stack-test/src/case/app_manager.rs index 3083d45c4..20ed9a93c 100644 --- a/src/tests/cyfs-stack-test/src/case/app_manager.rs +++ b/src/tests/cyfs-stack-test/src/case/app_manager.rs @@ -24,7 +24,15 @@ async fn register_app(stack: &SharedCyfsStack, dec_id: &ObjectId) { let action_id = action.desc().calculate_id(); let buf = action.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + let ret = stack.non_service().post_object(req.clone()).await; + assert!(ret.is_err()); + + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_APP_VIRTUAL_PATH.to_owned()); + let ret = stack.non_service().post_object(req.clone()).await; + assert!(ret.is_err()); + + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await.unwrap(); assert!(resp.object.is_none()); @@ -41,8 +49,11 @@ async fn unregister_app(stack: &SharedCyfsStack, dec_id: &ObjectId) { let action_id = action.desc().calculate_id(); let buf = action.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_APP_VIRTUAL_PATH.to_owned()); + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await.unwrap(); + assert!(resp.object.is_none()); info!("register dec success!"); diff --git a/src/tests/cyfs-stack-test/src/case/mnemonic.rs b/src/tests/cyfs-stack-test/src/case/mnemonic.rs index 595178eee..ba97751e7 100644 --- a/src/tests/cyfs-stack-test/src/case/mnemonic.rs +++ b/src/tests/cyfs-stack-test/src/case/mnemonic.rs @@ -26,6 +26,10 @@ async fn check_user() { user2.user_data().check_equal(&USER2_DATA); } +pub async fn test() { + check_user().await; +} + #[cfg(test)] mod test { #[test] diff --git a/src/tests/cyfs-stack-test/src/case/mod.rs b/src/tests/cyfs-stack-test/src/case/mod.rs index f1d5bde1b..2c4edf860 100644 --- a/src/tests/cyfs-stack-test/src/case/mod.rs +++ b/src/tests/cyfs-stack-test/src/case/mod.rs @@ -42,7 +42,8 @@ pub async fn test() { shared_stack::test().await; }); - + test_restart().await; + // role::test().await; // crypto::test().await; @@ -59,30 +60,25 @@ pub async fn test() { call::test().await; object_meta_access::test().await; - async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; - - return; - - test_restart().await; - test_obj_searcher::test().await; + events::test().await; + zone::test().await; + // mnemonic::test().await; + app_manager::test().await; + trans::test().await; - // test_drive::test().await; + async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; - events::test().await; + return; - zone::test().await; + + // test_drive::test().await; non_handlers::test().await; //non_file::test().await; - trans::test().await; - router_handlers::test().await; - //mnemonic::test().await; - app_manager::test().await; - admin::test().await; sync::test().await; diff --git a/src/tests/cyfs-stack-test/src/case/trans.rs b/src/tests/cyfs-stack-test/src/case/trans.rs index e61c9c394..a074770db 100644 --- a/src/tests/cyfs-stack-test/src/case/trans.rs +++ b/src/tests/cyfs-stack-test/src/case/trans.rs @@ -603,6 +603,8 @@ async fn test_shared_data() { unreachable!(); } + info!("pub chunk as shared data success!"); + { let req = NDNGetDataRequest::new_ndc(id.object_id().to_owned(), None); @@ -620,7 +622,10 @@ async fn test_shared_data() { let new_id = shared_chunk.calculate_id(); assert_eq!(new_id, id); } + + info!("test shared data success!"); } + async fn download_chunk(chunk_id: ChunkId, chunk: Vec, device_id: DeviceId) { let data_dir = cyfs_util::get_app_data_dir("cyfs-stack-test").join("trans"); let local_path = data_dir.join("test-chunk"); diff --git a/src/tests/cyfs-stack-test/src/main.rs b/src/tests/cyfs-stack-test/src/main.rs index eb8730f22..3edaa6874 100644 --- a/src/tests/cyfs-stack-test/src/main.rs +++ b/src/tests/cyfs-stack-test/src/main.rs @@ -12,7 +12,7 @@ async fn main_run() { CyfsLoggerBuilder::new_app("cyfs-stack-test") .level("debug") .console("debug") - .enable_bdt(Some("error"), Some("error")) + .enable_bdt(Some("debug"), Some("debug")) .disable_file_config(true) .file(true) .build() diff --git a/src/tools/pack-tools/Cargo.toml b/src/tools/pack-tools/Cargo.toml index 0511ad8e4..2a22c5de5 100644 --- a/src/tools/pack-tools/Cargo.toml +++ b/src/tools/pack-tools/Cargo.toml @@ -14,5 +14,5 @@ clap = "2.34.0" simple_logger = "2.1" log = "0.4" sha2 = "0.8" -zip = "0.6.2" +zip = "0.6" cyfs-base = { path = "../../component/cyfs-base" } From 39c9c4ff34b1a24febfde046250eab27d702053c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 17:19:58 +0800 Subject: [PATCH 171/553] Fix the bug that the full version cannot be parsed correctly when service_version = "default" --- .../ood-daemon/src/config_repo/meta.rs | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index e9d54d2c2..d260420a5 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -333,29 +333,35 @@ impl DeviceConfigMetaRepo { let service = self.load_service(service_id).await?; // first find the correct version - let config_version = match &get_system_config().service_version { - ServiceVersion::Default => version_in_service_list.to_owned(), - ServiceVersion::Specific(v) => v.clone(), - }; + let version = match &get_system_config().service_version { + ServiceVersion::Default => { + // direct use the full version configed in the service list + version_in_service_list + }, + ServiceVersion::Specific(config_version) => { + let preview = match get_system_config().preview { + true => Some("preview"), + false => None, + }; + + let (version, semver) = service.find_version(&config_version, preview).map_err(|e| { + let msg = format!( + "find version from service object failed! id={}, configed version={}, preview={:?}, {}", + service_id, config_version, preview, e, + ); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::NotFound, msg) + })?; + + // check if the target service version is valid + SemVerEpochCheck::check_version_with_semver_epoch(&semver)?; - let preview = match get_system_config().preview { - true => Some("preview"), - false => None, + version + } }; - let (version, semver) = service.find_version(&config_version, preview).map_err(|e| { - let msg = format!( - "find version from service object failed! id={}, configed version={}, preview={:?}, {}", - service_id, config_version, preview, e, - ); - error!("{}", msg); - - BuckyError::new(BuckyErrorCode::NotFound, msg) - })?; - - // check if the target service version is valid - SemVerEpochCheck::check_version_with_semver_epoch(&semver)?; - + let ret = service.find_source(&version); if ret.is_err() { let msg = format!( From ae1ab3999a9edeb6fd2edcb25b3790f3ea86c8dd Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 18:03:01 +0800 Subject: [PATCH 172/553] Fix the bug when system-config's service_version = "default" updated cannot trigger the device-config updating's bug in some cases --- .../ood-daemon/src/config/system_config.rs | 4 ++ .../ood-daemon/src/config_repo/meta.rs | 42 +++++++++++-------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 7ec69d578..9ae346c60 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -41,6 +41,10 @@ impl SystemConfig { } } + pub fn compare(&self, other: &SystemConfig) -> bool { + *self == *other + } + pub async fn load_config(&mut self) -> BuckyResult<()> { let config_file = PATHS.system_config.clone(); diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index d260420a5..90f3aa98e 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -11,6 +11,7 @@ use cyfs_util::LOCAL_DEVICE_MANAGER; use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::str::FromStr; +use std::sync::Arc; #[derive(Serialize, Deserialize)] struct DeviceConfigGenerator { @@ -123,6 +124,7 @@ impl DeviceConfigGenerator { } struct LocalCache { + system_config: Arc, service_list: AppList, device_config_str: String, } @@ -156,14 +158,15 @@ impl DeviceConfigMetaRepo { } pub fn init(&self) -> BuckyResult<()> { - Self::gen_service_list_id()?; + // just for verify system-config on init + Self::gen_service_list_id(&get_system_config())?; Ok(()) } - fn gen_service_list_id() -> BuckyResult { - let device_id = Self::load_device(&get_system_config().config_desc)?; - let service_list_version = get_system_config().service_list_version.to_string(); + fn gen_service_list_id(system_config: &Arc) -> BuckyResult { + let device_id = Self::load_device(&system_config.config_desc)?; + let service_list_version = system_config.service_list_version.to_string(); // 计算ServiceList对象id let service_list_id = AppList::generate_id( @@ -174,7 +177,7 @@ impl DeviceConfigMetaRepo { info!( "device config repo: config_desc={}, device_id={}, service_list_id={}, version={}", - get_system_config().config_desc, + system_config.config_desc, device_id, service_list_id, service_list_version @@ -196,8 +199,8 @@ impl DeviceConfigMetaRepo { Ok(ret) } - async fn load_service_list(&self) -> BuckyResult { - let service_list_id = Self::gen_service_list_id()?; + async fn load_service_list(&self, system_config: &Arc,) -> BuckyResult { + let service_list_id = Self::gen_service_list_id(system_config)?; let ret = MetaClientHelper::get_object(&self.meta_client, &service_list_id).await?; if ret.is_none() { let msg = format!( @@ -288,8 +291,8 @@ impl DeviceConfigMetaRepo { } // 从dir里面加载当前target对应的fid - fn load_fid(&self, dir_id: &str, dir: Dir) -> BuckyResult { - let mut target = get_system_config().target.clone(); + fn load_fid(&self, system_config: &Arc, dir_id: &str, dir: Dir) -> BuckyResult { + let mut target = system_config.target.clone(); match dir.desc().content().obj_list() { NDNObjectInfo::ObjList(entries) => { @@ -326,6 +329,7 @@ impl DeviceConfigMetaRepo { async fn load_service_fid( &self, + system_config: &Arc, device_config: &mut DeviceConfigGenerator, service_id: &ObjectId, version_in_service_list: &str, @@ -333,13 +337,13 @@ impl DeviceConfigMetaRepo { let service = self.load_service(service_id).await?; // first find the correct version - let version = match &get_system_config().service_version { + let version = match &system_config.service_version { ServiceVersion::Default => { // direct use the full version configed in the service list version_in_service_list }, ServiceVersion::Specific(config_version) => { - let preview = match get_system_config().preview { + let preview = match system_config.preview { true => Some("preview"), false => None, }; @@ -381,7 +385,7 @@ impl DeviceConfigMetaRepo { // 查找当前平台对应的fid let dir_id = dir_id.to_string(); - let fid = self.load_fid(&dir_id, dir)?; + let fid = self.load_fid(&system_config, &dir_id, dir)?; // 更新 device_config.update_service(&service, &fid, version); @@ -391,6 +395,7 @@ impl DeviceConfigMetaRepo { async fn gen_service_list_to_device_config( &self, + system_config: &Arc, service_list: &AppList, ) -> BuckyResult { let mut device_config = DeviceConfigGenerator::new(); @@ -399,7 +404,7 @@ impl DeviceConfigMetaRepo { let version = status.version(); - self.load_service_fid(&mut device_config, id.object_id(), version) + self.load_service_fid(&system_config, &mut device_config, id.object_id(), version) .await .map_err(|e| { error!( @@ -440,21 +445,23 @@ impl DeviceConfigMetaRepo { } async fn fetch_inner(&self) -> BuckyResult { + let current_system_config = get_system_config(); + // 从mete-chain拉取对应的service_list - let service_list = self.load_service_list().await?; + let service_list = self.load_service_list(¤t_system_config).await?; // Only in the default version case, it will use the cache of servicelist - if get_system_config().service_version.is_default() { + if current_system_config.service_version.is_default() { let cache = self.cache.lock().unwrap(); if let Some(cache) = &*cache { - if Self::compare_service_list(&cache.service_list, &service_list) { + if cache.system_config.compare(¤t_system_config) && Self::compare_service_list(&cache.service_list, &service_list) { return Ok(cache.device_config_str.clone()); } } } let mut device_config = self - .gen_service_list_to_device_config(&service_list) + .gen_service_list_to_device_config(¤t_system_config, &service_list) .await?; device_config.sort(); @@ -463,6 +470,7 @@ impl DeviceConfigMetaRepo { { let mut cache = self.cache.lock().unwrap(); *cache = Some(LocalCache { + system_config: current_system_config, service_list, device_config_str: device_config_str.clone(), }); From 6e1ffce2db5ed752606c8cffe9ecdfc3684e88f8 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 18:16:47 +0800 Subject: [PATCH 173/553] Fix the bug that the modification of system-config cannot take effect immediately during the check loop --- src/service/ood-daemon/src/daemon/daemon.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index fb05c73ca..9b967b499 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -9,7 +9,7 @@ use ood_control::OOD_CONTROLLER; use async_std::task; use futures::future::{AbortHandle, Abortable}; -use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::atomic::{AtomicU64, Ordering, AtomicBool}; use std::sync::{Arc, Mutex}; use std::time::Duration; @@ -49,6 +49,7 @@ pub struct Daemon { no_monitor: bool, last_active: Arc, check_update_waker: Arc>>, + wakedup_once: Arc, } impl Daemon { @@ -59,6 +60,7 @@ impl Daemon { no_monitor, last_active: Arc::new(ActionActive::default()), check_update_waker: Arc::new(Mutex::new(None)), + wakedup_once: Arc::new(AtomicBool::new(false)), } } @@ -92,6 +94,9 @@ impl Daemon { if let Some(abort_handle) = self.check_update_waker.lock().unwrap().take() { info!("will wakeup check update now!"); abort_handle.abort(); + } else { + info!("wakeup check udpate but still in checking loop! now will mark"); + self.wakedup_once.store(true, Ordering::SeqCst); } } @@ -186,11 +191,16 @@ impl Daemon { } } - // 检查绑定状态 + let ret = self.wakedup_once.swap(false, Ordering::SeqCst); + if ret { + continue; + } + let timer = task::sleep(Duration::from_secs(60 * 30)); let (abort_handle, abort_registration) = AbortHandle::new_pair(); + // check ood's binding status if !OOD_CONTROLLER.is_bind() { *notify.abort_handle.lock().unwrap() = Some(abort_handle.clone()); } @@ -198,6 +208,7 @@ impl Daemon { match Abortable::new(timer, abort_registration).await { Ok(_) => { + self.check_update_waker.lock().unwrap().take(); debug!("check update loop wait timeout, now will check once"); } Err(futures::future::Aborted { .. }) => { From 7c22da3363a93df2b49440d0b81c044c529512d5 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 21:11:48 +0800 Subject: [PATCH 174/553] Clear meta cache when service list changed --- src/component/cyfs-core/src/app/dec_app.rs | 12 ++++++------ .../ood-daemon/src/config/system_config.rs | 3 ++- .../ood-daemon/src/config_repo/meta.rs | 19 ++++++++++++++++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/component/cyfs-core/src/app/dec_app.rs b/src/component/cyfs-core/src/app/dec_app.rs index e5a0d9b8a..578ee27c9 100644 --- a/src/component/cyfs-core/src/app/dec_app.rs +++ b/src/component/cyfs-core/src/app/dec_app.rs @@ -219,8 +219,8 @@ impl DecAppObj for DecApp { let req_version = semver::VersionReq::parse(req_semver).map_err(|e| { let msg = format!( - "invalid semver request string! id={}, name={}, value={}, {}", - id, name, req_semver, e + "invalid semver request string! id={}, name={}, value={}, pre={:?}, {}", + id, name, req_semver, pre, e ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -241,8 +241,8 @@ impl DecAppObj for DecApp { for (version, new_version) in list { let mut semver = semver::Version::parse(&new_version).map_err(|e| { let msg = format!( - "invalid semver string! id={}, name={}, value={}, {}", - id, name, version, e, + "invalid semver string! id={}, name={}, value={}, pre={:?}, {}", + id, name, version, pre, e, ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -267,8 +267,8 @@ impl DecAppObj for DecApp { let ret = semver_list.iter().find(|(version, semver)| { if req_version.matches(semver) { info!( - "app version matched: id={}, name={}, req={}, got={}", - id, name, req_semver, version + "app version matched: id={}, name={}, req={}, got={}, prev={:?}", + id, name, req_semver, version, pre, ); true } else { diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 9ae346c60..ceb3344e9 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -41,10 +41,11 @@ impl SystemConfig { } } + // return true if the same pub fn compare(&self, other: &SystemConfig) -> bool { *self == *other } - + pub async fn load_config(&mut self) -> BuckyResult<()> { let config_file = PATHS.system_config.clone(); diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 90f3aa98e..e261c358a 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -450,16 +450,33 @@ impl DeviceConfigMetaRepo { // 从mete-chain拉取对应的service_list let service_list = self.load_service_list(¤t_system_config).await?; + let mut service_list_is_the_same = None; + // Only in the default version case, it will use the cache of servicelist if current_system_config.service_version.is_default() { let cache = self.cache.lock().unwrap(); if let Some(cache) = &*cache { - if cache.system_config.compare(¤t_system_config) && Self::compare_service_list(&cache.service_list, &service_list) { + service_list_is_the_same = Some(Self::compare_service_list(&cache.service_list, &service_list)); + if cache.system_config.compare(¤t_system_config) && service_list_is_the_same == Some(true) { return Ok(cache.device_config_str.clone()); } } } + { + if service_list_is_the_same.is_none() { + let cache = self.cache.lock().unwrap(); + if let Some(cache) = &*cache { + service_list_is_the_same = Some(Self::compare_service_list(&cache.service_list, &service_list)); + } + } + + if service_list_is_the_same == Some(false) { + warn!("service list changed! now will clear meta cache"); + self.clear_cache().await; + } + } + let mut device_config = self .gen_service_list_to_device_config(¤t_system_config, &service_list) .await?; From 2f0bb2890a08b0a3abbcd744443fd4df0f4e86b8 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 28 Feb 2023 09:33:39 +0800 Subject: [PATCH 175/553] Switch ndn get_data to normal http requestor instead of surf requestor --- src/component/cyfs-lib/src/stack/stack.rs | 55 +++++++++++++++-------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 5de037faa..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -76,7 +76,7 @@ impl Drop for ObjectServices { pub struct SharedCyfsStack { param: SharedCyfsStackParam, - // 所属的dec_id + // The dec_id it belongs to dec_id: SharedObjectStackDecID, services: Arc, @@ -88,7 +88,7 @@ pub struct SharedCyfsStack { // router events router_events: RouterEventManager, - // 当前协议栈的device + // Device of the current protocol stack device_info: Arc>>, // uni_stack @@ -161,10 +161,10 @@ impl CyfsStackRequestorConfig { pub struct SharedCyfsStackParam { pub dec_id: Option, - // 基于http协议的服务地址 + // Service address based on the HTTP protocol pub service_url: Url, - // 基于websocket协议的服务地址 + // Service address based on the WebSocket protocol pub ws_url: Url, pub event_type: CyfsStackEventType, @@ -186,7 +186,7 @@ impl SharedCyfsStackParam { Self::default(dec_id) } - // 默认切换到websocket模式 + // Switch to the websocket mode by default pub fn default(dec_id: Option) -> Self { let (service_url, ws_url) = Self::gen_url(cyfs_base::NON_STACK_HTTP_PORT, cyfs_base::NON_STACK_WS_PORT); @@ -200,7 +200,7 @@ impl SharedCyfsStackParam { } } - // 提供给cyfs-runtime使用的shareobjectstack + // SharedCyfsStack provided to Cyfs-Runtime pub fn default_runtime(dec_id: Option) -> Self { let (service_url, ws_url) = Self::gen_url( cyfs_base::CYFS_RUNTIME_NON_STACK_HTTP_PORT, @@ -216,7 +216,7 @@ impl SharedCyfsStackParam { } } - // 打开指定端口的shareobjectstack + // Open shared stack of the specified port pub fn gen(dec_id: Option, http_port: u16, ws_port: u16) -> Self { let (service_url, ws_url) = Self::gen_url(http_port, ws_port); @@ -263,6 +263,7 @@ struct RequestorHolder { requestor_config: CyfsStackRequestorConfig, http: Option, ws: Option, + data: Option, } impl RequestorHolder { @@ -271,6 +272,7 @@ impl RequestorHolder { requestor_config, http: None, ws: None, + data: None, } } @@ -283,7 +285,7 @@ impl RequestorHolder { CyfsStackRequestorType::Http => { self.http .get_or_insert_with(|| { - // 基于标准http的requestor + // Requestor based on standard http let addr = format!( "{}:{}", param.service_url.host_str().unwrap(), @@ -306,7 +308,7 @@ impl RequestorHolder { CyfsStackRequestorType::WebSocket => { self.ws .get_or_insert_with(|| { - // 基于websocket协议的requestor + // Requestor based on the WebSocket protocol Arc::new(Box::new(WSHttpRequestor::new(param.ws_url.clone()))) }) .clone() @@ -314,6 +316,21 @@ impl RequestorHolder { } } + fn data_requestor(&mut self, param: &SharedCyfsStackParam) -> HttpRequestorRef { + self.data + .get_or_insert_with(|| { + // Requestor based on standard HTTP + let addr = format!( + "{}:{}", + param.service_url.host_str().unwrap(), + param.service_url.port().unwrap() + ); + + Arc::new(Box::new(TcpHttpRequestor::new(&addr))) + }) + .clone() + } + async fn stop(&self) { if let Some(requestor) = &self.http { requestor.stop().await; @@ -383,7 +400,7 @@ impl SharedCyfsStack { let requestor = requestor_holder.select_requestor(¶m, ¶m.requestor_config.ndn_service); let data_requestor = - requestor_holder.select_requestor(¶m, &CyfsStackRequestorType::Http); + requestor_holder.data_requestor(¶m); let ndn_service = NDNRequestor::new(Some(dec_id.clone()), requestor, Some(data_requestor)); // sync @@ -433,7 +450,7 @@ impl SharedCyfsStack { local_cache_meta, }); - // 初始化对应的事件处理器,二选一 + // Initialize the corresponding event processor, choose one in the two choices let router_handlers = match ¶m.event_type { CyfsStackEventType::WebSocket(ws_url) => { RouterHandlerManager::new(Some(dec_id.clone()), ws_url.clone()) @@ -446,7 +463,7 @@ impl SharedCyfsStack { } }; - // 缓存所有processors,用以uni_stack直接返回使用 + // Caches all processors, use UNI_STACK to return to use directly let processors = Arc::new(CyfsStackProcessors { non_service: services.non_service.clone_processor(), ndn_service: services.ndn_service.clone_processor(), @@ -502,7 +519,7 @@ impl SharedCyfsStack { Self::open(param).await } - // 等待协议栈上线 + // Waiting for the protocol stack online pub async fn wait_online(&self, timeout: Option) -> BuckyResult<()> { let this = self.clone(); let ft = async move { @@ -512,7 +529,7 @@ impl SharedCyfsStack { Err(e) => { match e.code() { BuckyErrorCode::ConnectFailed | BuckyErrorCode::Timeout => { - // 需要重试 + // Need to retry } _ => { error!("stack online failed! {}", e); @@ -540,7 +557,7 @@ impl SharedCyfsStack { } pub async fn online(&self) -> BuckyResult<()> { - // 获取当前协议栈的device_id + // Get Device_id of the current protocol stack let req = UtilGetDeviceOutputRequest::new(); let resp = self.services.util_service.get_device(req).await?; @@ -551,7 +568,7 @@ impl SharedCyfsStack { Ok(()) } - // 如果初始化时候没有指定,那么可以延迟绑定一次 + // If it is not specified during initialization, it can be delayed init once pub fn bind_dec(&self, dec_id: ObjectId) { self.dec_id.set(dec_id).unwrap(); } @@ -560,7 +577,7 @@ impl SharedCyfsStack { self.dec_id.get() } - // 下面两个接口必须调用onlien成功一次之后才可以调用 + // The following two interfaces must be called online successfully before you can call them pub fn local_device_id(&self) -> DeviceId { self.device_info.read().unwrap().as_ref().unwrap().0.clone() } @@ -601,7 +618,7 @@ impl SharedCyfsStack { &self.router_events } - // root_state 根状态管理相关接口 + // root_state Root State Management Related Interface pub fn root_state(&self) -> &GlobalStateRequestor { &self.services.root_state } @@ -720,7 +737,7 @@ impl SharedCyfsStack { ) } - // uni_stack相关接口 + // uni_stack related interface fn create_uni_stack(&self) -> UniCyfsStackRef { Arc::new(self.clone()) } From d2c4824de0dc7947ebbda8d7549e8568609c5160 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 28 Feb 2023 09:46:18 +0800 Subject: [PATCH 176/553] Improve admin and sync test cases --- src/tests/cyfs-stack-test/src/case/admin.rs | 16 +++++- src/tests/cyfs-stack-test/src/case/crypto.rs | 2 +- src/tests/cyfs-stack-test/src/case/mod.rs | 16 +++--- src/tests/cyfs-stack-test/src/case/sync.rs | 56 +++++++++++++++----- 4 files changed, 63 insertions(+), 27 deletions(-) diff --git a/src/tests/cyfs-stack-test/src/case/admin.rs b/src/tests/cyfs-stack-test/src/case/admin.rs index 7daef8807..bd7aa1fb0 100644 --- a/src/tests/cyfs-stack-test/src/case/admin.rs +++ b/src/tests/cyfs-stack-test/src/case/admin.rs @@ -20,7 +20,17 @@ async fn change_access_mode(_dec_id: &ObjectId, access_mode: GlobalStateAccessMo let admin_id = admin_object.desc().calculate_id(); let buf = admin_object.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(Some(target.clone().into()), admin_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(Some(target.clone().into()), admin_id, buf); + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_ADMIN_VIRTUAL_PATH.to_owned()); + + let resp = stack.non_service().post_object(req.clone()).await; + if let Err(e) = resp { + assert_eq!(e.code(), BuckyErrorCode::NotHandled); + } else { + unreachable!(); + } + + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await; if let Err(e) = resp { assert_eq!(e.code(), BuckyErrorCode::InvalidSignature); @@ -41,7 +51,9 @@ async fn change_access_mode(_dec_id: &ObjectId, access_mode: GlobalStateAccessMo let admin_id = admin_object.desc().calculate_id(); let buf = admin_object.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(Some(target.into()), admin_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(Some(target.into()), admin_id, buf); + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_ADMIN_VIRTUAL_PATH.to_owned()); + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await.unwrap(); assert!(resp.object.is_none()); diff --git a/src/tests/cyfs-stack-test/src/case/crypto.rs b/src/tests/cyfs-stack-test/src/case/crypto.rs index 43ce9724f..f4ae23eb0 100644 --- a/src/tests/cyfs-stack-test/src/case/crypto.rs +++ b/src/tests/cyfs-stack-test/src/case/crypto.rs @@ -52,7 +52,7 @@ fn new_dec(name: &str) -> ObjectId { } pub async fn test() { - return test_codec().await; + test_codec().await; let dec_id = new_dec("crypto"); let stack1 = TestLoader::get_shared_stack(DeviceIndex::User1OOD); diff --git a/src/tests/cyfs-stack-test/src/case/mod.rs b/src/tests/cyfs-stack-test/src/case/mod.rs index 2c4edf860..95ec48a6b 100644 --- a/src/tests/cyfs-stack-test/src/case/mod.rs +++ b/src/tests/cyfs-stack-test/src/case/mod.rs @@ -45,7 +45,6 @@ pub async fn test() { test_restart().await; // role::test().await; - // crypto::test().await; noc::test().await; @@ -67,20 +66,17 @@ pub async fn test() { app_manager::test().await; trans::test().await; - async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; + admin::test().await; + sync::test().await; - return; + async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; - // test_drive::test().await; - non_handlers::test().await; - //non_file::test().await; - - router_handlers::test().await; + // non_handlers::test().await; + // non_file::test().await; - admin::test().await; - sync::test().await; + // router_handlers::test().await; info!("test all case success!"); } \ No newline at end of file diff --git a/src/tests/cyfs-stack-test/src/case/sync.rs b/src/tests/cyfs-stack-test/src/case/sync.rs index 4ff8105db..522610cf5 100644 --- a/src/tests/cyfs-stack-test/src/case/sync.rs +++ b/src/tests/cyfs-stack-test/src/case/sync.rs @@ -53,7 +53,31 @@ impl Indexer { } } +async fn test_http_version() { + use std::str::FromStr; + + let stack = TestLoader::get_shared_stack(DeviceIndex::User1StandbyOOD); + let chunk_id = ChunkId::from_str("7EwH3v5RwuzSfu6oGHJvEN69cw2YyfCu72Euo3wmauzy").unwrap(); + let req = NDNGetDataOutputRequest::new_ndc(chunk_id.object_id(), None); + let _resp = stack.ndn_service().get_data(req).await.unwrap(); + + let req = NDNGetDataOutputRequest::new_ndc(chunk_id.object_id(), None); + let _resp = stack.ndn_service().get_data(req).await.unwrap(); +} + pub async fn test() { + async_std::task::spawn(async move { + test_http_version().await; + }); + + async_std::task::spawn(async move { + test_http_version().await; + }); + + async_std::task::spawn(async move { + test_http_version().await; + }); + let index = Indexer::new(); let index1 = index.clone(); @@ -68,6 +92,8 @@ pub async fn test() { let stack = TestLoader::get_shared_stack(DeviceIndex::User1StandbyOOD); test_standby_ood_get(&stack, index).await; }); + + async_std::task::sleep(std::time::Duration::from_secs(60 * 5)).await; } async fn add_chunk(stack: &SharedCyfsStack) -> ChunkId { @@ -385,20 +411,6 @@ async fn test_standby_ood_get(stack: &SharedCyfsStack, indexer: Indexer) { let expect = indexer.get(&root_info.root).unwrap(); assert_eq!(expect, v); - let ret = op_env.get_by_path("/data/object_id1").await.unwrap(); - let v = ret.unwrap(); - assert!(v.is_data()); - - let req = RootStateAccessorGetObjectByPathOutputRequest::new("/data/object_id1"); - let ret = stack.root_state_accessor().get_object_by_path(req).await; - assert!(ret.is_ok()); - let ret = ret.unwrap(); - assert!(ret.object.object.is_empty()); - assert!(ret.object.object.object_id.is_data()); - - let object = stack.root_state_accessor_stub(None, None).get_object_by_path("/data/object_id1").await.unwrap(); - assert!(object.object.is_empty()); - assert!(object.object.object_id.is_data()); info!("device will get text_object: {}", v); let req = NONGetObjectRequest::new_noc(v, None); @@ -414,6 +426,22 @@ async fn test_standby_ood_get(stack: &SharedCyfsStack, indexer: Indexer) { info!("device got target chunk: {}", chunk_id); } + + let ret = op_env.get_by_path("/data/object_id1").await.unwrap(); + let ret = ret.unwrap(); + assert!(ret.is_data()); + + let req = RootStateAccessorGetObjectByPathOutputRequest::new("/data/object_id1"); + let ret = stack.root_state_accessor().get_object_by_path(req).await; + assert!(ret.is_ok()); + let ret = ret.unwrap(); + assert!(ret.object.object.is_empty()); + assert!(ret.object.object.object_id.is_data()); + + let object = stack.root_state_accessor_stub(None, None).get_object_by_path("/data/object_id1").await.unwrap(); + assert!(object.object.is_empty()); + assert!(object.object.object_id.is_data()); + async_std::task::sleep(std::time::Duration::from_secs(15)).await; } } From 1ad0bd74ae20ba0d941d10d2a3305ae3d18fe738 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 17:42:13 +0800 Subject: [PATCH 177/553] Set known sn list when sync built-in app repo --- src/tools/ood-installer/src/app_repo_downloader.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/ood-installer/src/app_repo_downloader.rs b/src/tools/ood-installer/src/app_repo_downloader.rs index b7fa7ca18..dd5c79c08 100644 --- a/src/tools/ood-installer/src/app_repo_downloader.rs +++ b/src/tools/ood-installer/src/app_repo_downloader.rs @@ -39,6 +39,11 @@ impl AppRepoDownloader { return Err(BuckyError::new(e.code(), msg)); } + let known_sn = cyfs_util::get_sn_desc().iter().map(|(_, device)| { + device.clone() + }).collect(); + let _ = self.client.reset_known_sn_list(known_sn); + Ok(()) } From e85ba6ec4d04fe3c833c79a24e1080074b986b71 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 20:55:05 +0800 Subject: [PATCH 178/553] Fix wrong app local repo path --- src/service/app-manager/src/package.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/service/app-manager/src/package.rs b/src/service/app-manager/src/package.rs index 274ed7d51..4b9d283be 100644 --- a/src/service/app-manager/src/package.rs +++ b/src/service/app-manager/src/package.rs @@ -34,7 +34,7 @@ impl AppPackage { Self::install_from_local(app_id, &tmp_path, true) } RepoMode::Local => { - let repo_path = get_cyfs_root_path().join("app_repo"); + let repo_path = get_cyfs_root_path().join("app_repo").join(dir.to_string()); Self::install_from_local(app_id, &repo_path, false) } } @@ -64,6 +64,7 @@ impl AppPackage { } pub fn install_from_local(app_id: &DecAppId, local_path: &Path, delete_source: bool) -> BuckyResult<()> { + info!("install app {} from local path {}", app_id, local_path.display()); let app_str = app_id.to_string(); let service_path = get_app_dir(&app_str); let acl_path = get_app_acl_dir(&app_str); From 84e57779027b2bdc90295015de7259d3cda5ce88 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 20:57:20 +0800 Subject: [PATCH 179/553] App-manager return error when repo path not exist --- src/service/app-manager/src/app_manager_ex.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/service/app-manager/src/app_manager_ex.rs b/src/service/app-manager/src/app_manager_ex.rs index 7da7d0be5..359bcb1fc 100644 --- a/src/service/app-manager/src/app_manager_ex.rs +++ b/src/service/app-manager/src/app_manager_ex.rs @@ -557,8 +557,12 @@ impl AppManager { .await { Ok(is_running) => { - info!("[RUNNING CHECK] running: [{}] app:{}", is_running, app_id); + let running_counter = self.start_couter.write().unwrap().entry(app_id.clone()).or_insert(0); + info!("[RUNNING CHECK] running: [{}] app:{}, start counter: {}", is_running, app_id, *running_counter); if is_running { + if *running_counter > 0 { + *running_counter = 0; + } return; } else { let mut try_start = false; @@ -575,17 +579,15 @@ impl AppManager { return; } //status is running, but not actually - let mut counters = self.start_couter.write().unwrap(); - let cur_count = *counters.get(app_id).unwrap_or(&0); - if cur_count > START_RETRY_LIMIT { + if *running_counter > START_RETRY_LIMIT { let target_status_code = AppLocalStatusCode::RunException; info!("[RUNNING CHECK] app failed count is out of limit! app:{}, change app status from [{}] to [{}]", app_id, cur_status_code, target_status_code); status.set_status(target_status_code); status_clone = Some(status.clone()); } else { - info!("[RUNNING CHECK] app status is running, but not actually. will restart it, app:{}, retry count:{}", app_id, cur_count + 1); - counters.insert(app_id.clone(), cur_count + 1); + *running_counter = *running_counter + 1; + info!("[RUNNING CHECK] app status is running, but not actually. will restart it, app:{}, retry count:{}", app_id, *running_counter); try_start = true; } } From 8ed501a391da568d79dca795b08645bec18a3e41 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 20:59:51 +0800 Subject: [PATCH 180/553] Commit right file --- src/service/app-manager/src/package.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service/app-manager/src/package.rs b/src/service/app-manager/src/package.rs index 4b9d283be..d6537a206 100644 --- a/src/service/app-manager/src/package.rs +++ b/src/service/app-manager/src/package.rs @@ -65,6 +65,9 @@ impl AppPackage { pub fn install_from_local(app_id: &DecAppId, local_path: &Path, delete_source: bool) -> BuckyResult<()> { info!("install app {} from local path {}", app_id, local_path.display()); + if !local_path.exists() { + return Err(BuckyError::new(BuckyErrorCode::NotFound, format!("local path {} not found", local_path.display()))); + } let app_str = app_id.to_string(); let service_path = get_app_dir(&app_str); let acl_path = get_app_acl_dir(&app_str); From 9109ae61922598895c928a9b52fd9ef5c086c847 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 1 Mar 2023 15:19:46 +0800 Subject: [PATCH 181/553] App-manager returns an error in the case that the command program does not exist. --- src/service/app-manager/src/app_manager_ex.rs | 8 ++++++-- src/service/app-manager/src/dapp.rs | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/service/app-manager/src/app_manager_ex.rs b/src/service/app-manager/src/app_manager_ex.rs index 359bcb1fc..14969b2a8 100644 --- a/src/service/app-manager/src/app_manager_ex.rs +++ b/src/service/app-manager/src/app_manager_ex.rs @@ -557,10 +557,12 @@ impl AppManager { .await { Ok(is_running) => { - let running_counter = self.start_couter.write().unwrap().entry(app_id.clone()).or_insert(0); - info!("[RUNNING CHECK] running: [{}] app:{}, start counter: {}", is_running, app_id, *running_counter); + info!("[RUNNING CHECK] running: [{}] app:{}", is_running, app_id); if is_running { + let mut writer = self.start_couter.write().unwrap(); + let running_counter = writer.entry(app_id.clone()).or_insert(0); if *running_counter > 0 { + info!("reset app {} restart counter {}", app_id, *running_counter); *running_counter = 0; } return; @@ -579,6 +581,8 @@ impl AppManager { return; } //status is running, but not actually + let mut writer = self.start_couter.write().unwrap(); + let running_counter = writer.entry(app_id.clone()).or_insert(0); if *running_counter > START_RETRY_LIMIT { let target_status_code = AppLocalStatusCode::RunException; info!("[RUNNING CHECK] app failed count is out of limit! app:{}, change app status from [{}] to [{}]", diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index 9f3e52df7..fff62587a 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -188,6 +188,11 @@ impl DApp { } info!("run cmd {} in {}", cmd, dir.display()); let program = which::which(args[0]).unwrap_or_else(|_| dir.join(args[0])); + if !program.exists() { + let err = format!("exec program path {} not exists!", program.display()); + error!("{}", &err); + return Err(BuckyError::new(BuckyErrorCode::NotFound, err)); + } let mut command = Command::new(program); command.args(&args[1..]).current_dir(dir); if let Some(out) = stdout { From 210a32507a8ff89706654b9171f7767a21f2798d Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 1 Mar 2023 17:43:39 +0800 Subject: [PATCH 182/553] Add perf-service in misc --- src/Cargo.lock | 508 +++++++++++++++++++-- src/Cargo.toml | 1 + src/misc/perf-service/Cargo.toml | 26 ++ src/misc/perf-service/src/config.rs | 174 +++++++ src/misc/perf-service/src/main.rs | 72 +++ src/misc/perf-service/src/service.rs | 124 +++++ src/misc/perf-service/src/storage/mod.rs | 77 ++++ src/misc/perf-service/src/storage/mongo.rs | 493 ++++++++++++++++++++ 8 files changed, 1449 insertions(+), 26 deletions(-) create mode 100644 src/misc/perf-service/Cargo.toml create mode 100644 src/misc/perf-service/src/config.rs create mode 100644 src/misc/perf-service/src/main.rs create mode 100644 src/misc/perf-service/src/service.rs create mode 100644 src/misc/perf-service/src/storage/mod.rs create mode 100644 src/misc/perf-service/src/storage/mongo.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 1d9ae081b..0649e040a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -174,7 +174,7 @@ dependencies = [ "serde_json", "surf", "tar", - "toml", + "toml 0.5.11", "version-compare", "wait-timeout", "walkdir", @@ -193,7 +193,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "toml", + "toml 0.5.11", ] [[package]] @@ -342,7 +342,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] @@ -472,6 +472,20 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "async-std-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "pin-utils", + "trust-dns-resolver", +] + [[package]] name = "async-task" version = "4.3.0" @@ -844,7 +858,27 @@ dependencies = [ "serde_json", "sqlx", "tide", - "toml", + "toml 0.5.11", +] + +[[package]] +name = "bson" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8746d07211bb12a7c34d995539b4a2acd4e0b0e757de98ce2ab99bcf17443fad" +dependencies = [ + "ahash", + "base64 0.13.1", + "chrono", + "hex", + "indexmap", + "lazy_static", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "time 0.3.19", + "uuid 1.3.0", ] [[package]] @@ -1387,6 +1421,16 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.6", + "subtle 2.4.1", +] + [[package]] name = "csv" version = "1.2.0" @@ -1571,7 +1615,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "socket2", + "socket2 0.4.7", "winapi", ] @@ -1705,7 +1749,7 @@ dependencies = [ "hmac 0.12.1", "log 0.4.17", "memzero", - "pbkdf2", + "pbkdf2 0.11.0", "rand 0.7.3", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -1813,7 +1857,7 @@ dependencies = [ "surf", "tide", "timer", - "toml", + "toml 0.5.11", "url 2.3.0", "winapi", ] @@ -2087,7 +2131,7 @@ dependencies = [ "serde", "serde_json", "surf", - "toml", + "toml 0.5.11", "url 2.3.0", ] @@ -2209,7 +2253,7 @@ dependencies = [ "serde", "serde_json", "tide", - "toml", + "toml 0.5.11", "url 2.3.0", ] @@ -2272,7 +2316,7 @@ dependencies = [ "sha2 0.8.2", "sqlx", "tide", - "toml", + "toml 0.5.11", "zip 0.6.4", ] @@ -2296,7 +2340,7 @@ dependencies = [ "log 0.4.17", "rand 0.8.5", "serde", - "toml", + "toml 0.5.11", ] [[package]] @@ -2318,7 +2362,7 @@ dependencies = [ "log 0.4.17", "regex", "serde", - "toml", + "toml 0.5.11", "toml_edit 0.15.0", ] @@ -2413,7 +2457,7 @@ dependencies = [ "simple_logger 2.3.0", "sysinfo 0.27.7", "thread_local", - "toml", + "toml 0.5.11", "url 2.3.0", "walkdir", "winapi", @@ -2468,6 +2512,12 @@ dependencies = [ "parking_lot_core 0.9.7", ] +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + [[package]] name = "deadpool" version = "0.7.0" @@ -2493,6 +2543,17 @@ dependencies = [ "pem-rfc7468", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -2700,6 +2761,18 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +[[package]] +name = "enum-as-inner" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -3197,7 +3270,7 @@ dependencies = [ "serde", "serde_json", "tide", - "toml", + "toml 0.5.11", "url 2.3.0", "wildmatch", "winapi", @@ -3519,6 +3592,16 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -3667,7 +3750,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite 0.2.9", - "socket2", + "socket2 0.4.7", "tokio", "tower-service", "tracing", @@ -3919,6 +4002,24 @@ dependencies = [ "libc", ] +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2 0.3.19", + "widestring 0.4.3", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + [[package]] name = "itertools" version = "0.10.5" @@ -4044,7 +4145,7 @@ dependencies = [ "nom 7.1.3", "once_cell", "quoted_printable", - "socket2", + "socket2 0.4.7", ] [[package]] @@ -4108,6 +4209,12 @@ dependencies = [ "cc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "local-ip-address" version = "0.5.1" @@ -4160,6 +4267,15 @@ dependencies = [ "log 0.4.17", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "lru_time_cache" version = "0.11.11" @@ -4194,6 +4310,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "md5" version = "0.7.0" @@ -4343,6 +4470,55 @@ dependencies = [ "serde", ] +[[package]] +name = "mongodb" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bacb6f8cee6bf010d7bc57550d859f6a4ffe255eb8c9a7014637fe988eaece64" +dependencies = [ + "async-std", + "async-std-resolver", + "async-trait", + "base64 0.13.1", + "bitflags", + "bson", + "chrono", + "derivative", + "futures-core", + "futures-executor", + "futures-io", + "futures-util", + "hex", + "hmac 0.11.0", + "lazy_static", + "md-5", + "os_info", + "pbkdf2 0.8.0", + "percent-encoding 2.2.0", + "rand 0.8.5", + "rustls 0.19.1", + "rustls-pemfile", + "serde", + "serde_with", + "sha-1 0.9.8", + "sha2 0.9.9", + "socket2 0.4.7", + "stringprep", + "strsim 0.10.0", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util 0.6.10", + "trust-dns-proto", + "trust-dns-resolver", + "typed-builder", + "uuid 0.8.2", + "version_check 0.9.4", + "webpki", + "webpki-roots 0.21.1", +] + [[package]] name = "multimap" version = "0.8.3" @@ -4359,7 +4535,7 @@ dependencies = [ "once_cell", "parking_lot 0.12.1", "thiserror", - "widestring", + "widestring 0.5.1", "winapi", ] @@ -4665,7 +4841,7 @@ dependencies = [ "serde", "serde_json", "tide", - "toml", + "toml 0.5.11", "zip 0.6.4", ] @@ -4759,6 +4935,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_info" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c424bc68d15e0778838ac013b5b3449544d8133633d8016319e7e05a820b8c0" +dependencies = [ + "log 0.4.17", + "winapi", +] + [[package]] name = "os_type" version = "2.6.0" @@ -4897,6 +5083,15 @@ dependencies = [ "proc-macro-hack 0.5.20+deprecated", ] +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -4941,6 +5136,27 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "perf-service" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-perf-base", + "cyfs-util", + "log 0.4.17", + "mongodb", + "serde", + "serde_json", + "toml 0.7.2", +] + [[package]] name = "petgraph" version = "0.6.3" @@ -5170,7 +5386,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] @@ -5770,6 +5986,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.16.20" @@ -5985,6 +6211,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "rustversion" version = "1.0.11" @@ -6129,6 +6364,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.2" @@ -6165,6 +6409,7 @@ version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ + "indexmap", "itoa", "ryu", "serde", @@ -6181,6 +6426,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -6215,6 +6469,19 @@ dependencies = [ "syn", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -6479,6 +6746,17 @@ dependencies = [ "simple_logger 4.0.0", ] +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -6574,7 +6852,7 @@ dependencies = [ "rand 0.8.5", "rsa 0.6.1", "rustls 0.19.1", - "sha-1", + "sha-1 0.10.1", "sha2 0.10.6", "smallvec 1.10.0", "sqlformat", @@ -6799,6 +7077,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tap" version = "1.0.1" @@ -7047,6 +7331,21 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.25.0" @@ -7060,10 +7359,33 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite 0.2.9", - "socket2", + "socket2 0.4.7", + "tokio-macros", "windows-sys 0.42.0", ] +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki", +] + [[package]] name = "tokio-util" version = "0.6.10" @@ -7072,6 +7394,7 @@ checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes 1.4.0", "futures-core", + "futures-io", "futures-sink", "log 0.4.17", "pin-project-lite 0.2.9", @@ -7102,12 +7425,33 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "toml_edit 0.19.4", +] + [[package]] name = "toml_datetime" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + [[package]] name = "toml_edit" version = "0.15.0" @@ -7117,7 +7461,7 @@ dependencies = [ "combine", "indexmap", "itertools", - "toml_datetime", + "toml_datetime 0.5.1", ] [[package]] @@ -7128,7 +7472,20 @@ checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ "indexmap", "nom8", - "toml_datetime", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "winnow", ] [[package]] @@ -7173,6 +7530,51 @@ dependencies = [ "rlp", ] +[[package]] +name = "trust-dns-proto" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.1", + "ipnet", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "smallvec 1.10.0", + "thiserror", + "tinyvec", + "tokio", + "url 2.3.0", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" +dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lazy_static", + "log 0.4.17", + "lru-cache", + "parking_lot 0.11.2", + "resolv-conf", + "smallvec 1.10.0", + "thiserror", + "tokio", + "trust-dns-proto", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -7192,7 +7594,7 @@ dependencies = [ "httparse", "log 0.4.17", "rand 0.8.5", - "sha-1", + "sha-1 0.10.1", "thiserror", "url 2.3.0", "utf-8", @@ -7204,6 +7606,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +[[package]] +name = "typed-builder" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46ee5bd706ff79131be9c94e7edcb82b703c487766a114434e5790361cf08c5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.16.0" @@ -7336,6 +7749,25 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "uuid" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +dependencies = [ + "getrandom 0.2.8", + "serde", +] + [[package]] name = "value-bag" version = "1.0.0-alpha.9" @@ -7560,6 +7992,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "widestring" version = "0.5.1" @@ -7736,6 +8174,24 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "winnow" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + [[package]] name = "wyz" version = "0.2.0" @@ -7800,7 +8256,7 @@ dependencies = [ "crossbeam-utils", "flate2", "hmac 0.12.1", - "pbkdf2", + "pbkdf2 0.11.0", "sha1 0.10.5", "time 0.3.19", "zstd", @@ -7863,7 +8319,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "toml", + "toml 0.5.11", "zone-simulator", ] diff --git a/src/Cargo.toml b/src/Cargo.toml index 3e7e6cdea..28684a8d6 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -65,6 +65,7 @@ members = [ "./misc/cyfs-monitor", "./misc/misc-util", "./misc/sn-online-test", + "./misc/perf-service", "./tests/cyfs-stack-test", "./tests/cyfs-bench-mark", diff --git a/src/misc/perf-service/Cargo.toml b/src/misc/perf-service/Cargo.toml new file mode 100644 index 000000000..24e526e3f --- /dev/null +++ b/src/misc/perf-service/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "perf-service" +version = "0.5.0" +authors = ["wangzhi "] +edition = "2018" +license = "BSD-2-Clause" +description = "Rust perf-service package" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cyfs-perf-base = {path="../../component/cyfs-perf/cyfs-perf-base"} +cyfs-base = {path="../../component/cyfs-base"} +cyfs-debug = {path="../../component/cyfs-debug"} +cyfs-core = {path="../../component/cyfs-core"} +cyfs-util = {path="../../component/cyfs-util"} +async-std = { version = "1.11", features = ["unstable", "attributes"] } +cyfs-lib = {path="../../component/cyfs-lib"} +log = "0.4" +async-trait = "0.1.53" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +mongodb = { version = "2", default-features = false, features = ["async-std-runtime", "bson-chrono-0_4"]} +toml = "0.7" +clap = "2" +chrono = "0.4" \ No newline at end of file diff --git a/src/misc/perf-service/src/config.rs b/src/misc/perf-service/src/config.rs new file mode 100644 index 000000000..4e4cac21e --- /dev/null +++ b/src/misc/perf-service/src/config.rs @@ -0,0 +1,174 @@ +use std::fmt::{Display, Formatter}; +use std::str::FromStr; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, TStringVisitor}; +use cyfs_lib::SharedCyfsStack; +use crate::storage::StorageConfig; +use cyfs_perf_base::PERF_DEC_ID; + +#[derive(PartialEq)] +pub enum StackType { + OOD, + Runtime, + Other(u16, u16) +} + +impl Default for StackType { + fn default() -> Self { + StackType::OOD + } +} + +impl Display for StackType { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + StackType::OOD => write!(f, "ood"), + StackType::Runtime => write!(f, "runtime"), + StackType::Other(http_port, ws_port) => write!(f, "{}:{}", http_port, ws_port) + } + } +} + +impl FromStr for StackType { + type Err = BuckyError; + + fn from_str(s: &str) -> BuckyResult { + match s { + "ood" => Ok(StackType::OOD), + "runtime" => Ok(StackType::Runtime), + v @ _ => { + let ports: Vec<&str> = v.split(":").collect(); + if ports.len() != 2 { + let msg = format!("stack type str {} invalid. Must have two port numbers separated by a colon", v); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + let http_port; + let ws_port; + match ports[0].parse::() { + Ok(port) => {http_port = port}, + Err(_) => { + let msg = format!("stack http port {} invalid. Must u16 port number", ports[0]); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + + match ports[1].parse::() { + Ok(port) => {ws_port = port}, + Err(_) => { + let msg = format!("stack ws port {} invalid. Must u16 port number", ports[1]); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + + Ok(StackType::Other(http_port, ws_port)) + } + } + } +} + +impl<'de> Deserialize<'de> for StackType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(TStringVisitor::::new()) + } +} + +impl Serialize for StackType { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_string()) + } +} + +#[derive(Serialize, Deserialize)] +pub(crate) struct PerfConfig { + pub stack_type: StackType, + pub storage: StorageConfig +} + +impl Default for PerfConfig { + fn default() -> Self { + Self { + stack_type: StackType::default(), + storage: StorageConfig::default(), + } + } +} + +pub(crate) async fn get_stack(config: StackType) -> BuckyResult { + let dec_id = Some(PERF_DEC_ID.clone()); + let stack = match config { + StackType::OOD => { + SharedCyfsStack::open_default(dec_id).await + }, + StackType::Runtime => { + SharedCyfsStack::open_runtime(dec_id).await + }, + StackType::Other(http_port, ws_port) => { + SharedCyfsStack::open_with_port(dec_id, http_port, ws_port).await + } + }?; + + stack.online().await?; + + Ok(stack) +} + +#[cfg(test)] +mod test { + use std::str::FromStr; + use crate::config::{PerfConfig, StackType}; + use crate::storage::mongo::MongoConfig; + use crate::storage::{DatabaseConfig, StorageConfig}; + + #[test] + fn print_config() { + let stack_type = StackType::from_str("2547:9885").unwrap(); + if let StackType::Other(http_port, ws_port) = stack_type { + assert_eq!(http_port, 2547); + assert_eq!(ws_port, 9885); + } else { + assert!(false); + } + + println!("normal config: \n{}", toml::to_string(&PerfConfig { + stack_type: StackType::OOD, + storage: StorageConfig { + isolate: Some("isolate".to_owned()), + database: DatabaseConfig::MongoDB(MongoConfig { mongo_url: "mongodb://localhost:21731".to_string() }) + } + }).unwrap()); + + println!("runtime config: \n{}", toml::to_string(&PerfConfig { + stack_type: StackType::Runtime, + storage: StorageConfig { + isolate: Some("isolate2".to_owned()), + database: DatabaseConfig::MongoDB(MongoConfig { mongo_url: "mongodb://localhost:21731".to_string() }) + } + }).unwrap()); + + println!("normal config: \n{}", toml::to_string(&PerfConfig { + stack_type: StackType::Other(21001, 21002), + storage: StorageConfig { + isolate: None, + database: DatabaseConfig::MongoDB(MongoConfig { mongo_url: "mongodb://localhost:21731".to_string() }) + } + }).unwrap()); + + let config_str = r#" +stack_type = "2132:8876" + +[storage.database.mongodb] +mongo_url = "mongodb://localhost:21731" +"#; + let config: PerfConfig = toml::from_str(config_str).unwrap(); + assert!(config.stack_type == StackType::Other(2132, 8876)); + assert!(config.storage.isolate.is_none()); + if let DatabaseConfig::MongoDB(config) = config.storage.database { + assert_eq!(config.mongo_url.as_str(), "mongodb://localhost:21731"); + } else { + assert!(false); + } + } +} diff --git a/src/misc/perf-service/src/main.rs b/src/misc/perf-service/src/main.rs new file mode 100644 index 000000000..7778c8093 --- /dev/null +++ b/src/misc/perf-service/src/main.rs @@ -0,0 +1,72 @@ + +mod service; +mod storage; +mod config; + +use std::path::Path; +use std::str::FromStr; +use service::*; +use async_std::sync::Arc; +use clap::{App, Arg}; +use log::{error, info, warn}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult}; +use crate::config::{PerfConfig, StackType}; + +fn parse_config(config_path: &Path) -> BuckyResult { + if !config_path.exists() { + warn!("config path {} not exists.", config_path.display()); + return Err(BuckyError::from(BuckyErrorCode::NotFound)); + } + + toml::from_str(std::fs::read_to_string(config_path)?.as_str()).map_err(|e| { + BuckyError::new(BuckyErrorCode::InvalidFormat, e.to_string()) + })? +} + +#[async_std::main] +async fn main() { + let matches = App::new("perf-service").version(cyfs_base::get_version()) + .arg(Arg::with_name("stack").short("s").long("stack").help("set stack mode, replace the config file one")) + .arg(Arg::with_name("config").short("c").long("config").takes_value(true).default_value("perf-service.toml")) + .get_matches(); + + cyfs_debug::CyfsLoggerBuilder::new_service("perf-service") + .level("info") + .console("info") + .enable_bdt(Some("info"), Some("info")) + .build() + .unwrap() + .start(); + + cyfs_debug::PanicBuilder::new("ood-service", "perf-service").build().start(); + + let config_path = Path::new(matches.value_of("config").unwrap()); + let mut config = match parse_config(config_path) { + Ok(config) => config, + Err(e) => { + warn!("parse config path {} err {}, use default", config_path.display(), e); + PerfConfig::default() + } + }; + + if let Some(stack_str) = matches.value_of("stack") { + info!("get stack param {}", stack_str); + match StackType::from_str(stack_str) { + Ok(stack) => { + config.stack_type = stack; + } + Err(e) => { + error!("parse stack param {} err {}", stack_str, e); + std::process::exit(1); + } + } + } + + info!("use final config: \n{}", toml::to_string_pretty(&config).unwrap()); + + let service = PerfService::create(config).await.unwrap(); + + PerfService::start(Arc::new(service)); + + async_std::task::block_on(async_std::future::pending::<()>()); +} \ No newline at end of file diff --git a/src/misc/perf-service/src/service.rs b/src/misc/perf-service/src/service.rs new file mode 100644 index 000000000..e53ee1314 --- /dev/null +++ b/src/misc/perf-service/src/service.rs @@ -0,0 +1,124 @@ +use cyfs_base::*; +use cyfs_perf_base::*; +use log::*; +use cyfs_lib::*; +use async_trait::async_trait; +use std::sync::{Arc}; +use cyfs_util::EventListenerAsyncRoutine; +use crate::config::{get_stack, PerfConfig}; + +use crate::storage::{create_storage, StorageRef}; + +struct OnPerfReport { + owner: Arc, +} + +#[async_trait] +impl EventListenerAsyncRoutine for OnPerfReport { + async fn call(&self, param: &RouterHandlerPostObjectRequest) -> BuckyResult { + let mut result = RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: None, + }; + + let owner = self.owner.clone(); + let from = param.request.common.source.zone.device.as_ref() + .map(|o|o.to_string()) + .unwrap_or_else(|| { + "self".to_owned() + }); + + // 验证对象签名,决定是否保存 + // 解出Perf对象 + match Perf::clone_from_slice(¶m.request.object.object_raw) { + Ok(perf) => { + let id= perf.desc().calculate_id(); + if self.owner.verify_object(&perf).await { + // 这里是实际处理流程,不占用路由时间 + async_std::task::spawn(async move { + info!("process perf object {} from {}", &id, from); + let _ = owner.on_perf(&perf).await; + }); + result.response = Some(Ok(NONPostObjectInputResponse { object: None })) + } else { + let msg = format!("perf object {} verify failed", &id); + warn!("{}", &msg); + result.response = Some(Err(BuckyError::new(BuckyErrorCode::Reject, msg))); + }; + } + Err(e) => { + let msg = format!("decode perf object {} err {}", ¶m.request.object.object_id, e); + result.response = Some(Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg))); + } + } + + Ok(result) + } +} + +pub(crate) struct PerfService { + cyfs_stack: SharedCyfsStack, + perf_storage: StorageRef +} + +impl PerfService { + pub async fn create(config: PerfConfig) -> BuckyResult { + let storage = create_storage(&config.storage).await?; + Ok(Self { + cyfs_stack: get_stack(config.stack_type).await?, + perf_storage: storage + }) + } + + pub fn start(service: Arc) { + // 注册on_post_put_router事件 + let listener = OnPerfReport { + owner: service.clone(), + }; + + // 只监听应用自己的DecObject + service.cyfs_stack + .router_handlers() + .add_handler( + RouterHandlerChain::Handler, + "cyfs_perf_on_perf_report", + 0, + None, + Some(PERF_REPORT_PATH.to_owned()), + RouterHandlerAction::Default, + Some(Box::new(listener))) + .unwrap(); + } + + // 这里验证对象签名是否正确,验证正确的对象才会被保存 + pub async fn verify_object(&self, _pref: &Perf) -> bool { + // 这里用业务逻辑检查 + true + } + + async fn on_perf(&self, perf: &Perf) -> BuckyResult<()> { + let id = perf.desc().calculate_id(); + + info!( + "###### recv msg {}, people:{}, device:{}, dec_id: {}, id: {}", + &id, + perf.people(), + perf.device(), + perf.dec_id(), + perf.get_id() + ); + + let all = perf.get_entity_list(); + info!("perf entity list len: {}", all.len()); + + let _ = self.perf_storage.insert_entity_list(perf.people(), + perf.device(), + perf.dec_id().to_string(), + perf.get_id().to_string(), + perf.get_version().to_owned(), + &all).await; + + Ok(()) + } +} diff --git a/src/misc/perf-service/src/storage/mod.rs b/src/misc/perf-service/src/storage/mod.rs new file mode 100644 index 000000000..9120ee1bd --- /dev/null +++ b/src/misc/perf-service/src/storage/mod.rs @@ -0,0 +1,77 @@ +pub mod mongo; + +use async_trait::async_trait; + +use cyfs_base::{BuckyResult}; + +use cyfs_perf_base::*; +use std::collections::HashMap; +use std::sync::Arc; +use serde::{Deserialize, Serialize, Serializer}; +use serde::ser::SerializeStruct; +use crate::storage::mongo::{MangodbStorage, MongoConfig}; + +#[derive(Serialize, Deserialize)] +pub(crate) struct StorageConfig { + pub(crate) isolate: Option, + pub(crate) database: DatabaseConfig +} + +impl Default for StorageConfig { + fn default() -> Self { + Self { + isolate: Some("perf-service".to_owned()), + database: DatabaseConfig::default(), + } + } +} + +#[derive(Deserialize)] +#[serde(rename_all="lowercase")] +pub(crate) enum DatabaseConfig { + MongoDB(MongoConfig) +} + +impl Default for DatabaseConfig { + fn default() -> Self { + DatabaseConfig::MongoDB(MongoConfig::default()) + } +} + +impl Serialize for DatabaseConfig { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + let mut state = serializer.serialize_struct("database", 1)?; + match self { + DatabaseConfig::MongoDB(config) => { + state.serialize_field("mongodb", config)?; + } + } + state.end() + } +} + +#[async_trait] +pub(crate) trait Storage: Sync + Send { + async fn insert_entity_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()>; +} + +pub(crate) type StorageRef = Arc; + +pub(crate) async fn create_storage(config: &StorageConfig) -> BuckyResult { + match &config.database { + DatabaseConfig::MongoDB(mongo_config) => { + let storage = MangodbStorage::new(config.isolate.as_deref(), mongo_config).await?; + Ok(Arc::new(storage)) + } + } +} + + + + + + + + + + diff --git a/src/misc/perf-service/src/storage/mongo.rs b/src/misc/perf-service/src/storage/mongo.rs new file mode 100644 index 000000000..4d5db067e --- /dev/null +++ b/src/misc/perf-service/src/storage/mongo.rs @@ -0,0 +1,493 @@ +use cyfs_base::{BuckyResult, BuckyError, BuckyErrorCode, bucky_time_to_system_time}; +use async_std::task; +use mongodb::{options::ClientOptions, Client, Collection, Database}; +use mongodb::error::{Error, ErrorKind, WriteFailure}; +use log::*; + +use async_trait::async_trait; +use crate::storage::*; +use cyfs_perf_base::*; +use std::collections::HashMap; +use chrono::Utc; +use mongodb::bson::{doc, Document}; +use serde::{Deserialize, Serialize}; + +const MONGO_DB_DEFAULT_NAME: &str = "perf-db"; + +const MONGO_COLL_NAME_REQUEST: &str = "request"; +const MONGO_COLL_NAME_ACTION: &str = "action"; +const MONGO_COLL_NAME_ACC: &str = "accumulation"; +const MONGO_COLL_NAME_RECORD: &str = "record"; + +pub const OBJECT_SELECT_MAX_PAGE_SIZE: u16 = 256; + +#[derive(Serialize, Deserialize)] +pub(crate) struct MongoConfig { + pub mongo_url: String +} + +impl Default for MongoConfig { + fn default() -> Self { + Self { + mongo_url: "mongodb://localhost".to_owned(), + } + } +} + +pub(crate) struct MangodbStorage{ + client: Client, + db: Database, + request_coll: Collection, + action_coll: Collection, + acc_coll: Collection, + record_coll: Collection, +} + +fn bucky_time_to_chrono_time(bucky_time: u64) -> chrono::DateTime { + let sys_time = bucky_time_to_system_time(bucky_time); + sys_time.into() +} + +impl MangodbStorage { + pub async fn new(isolate: Option<&str>, config: &MongoConfig) ->BuckyResult { + let mut client_options = ClientOptions::parse(&config.mongo_url).await.unwrap(); + client_options.direct_connection = Some(true); + client_options.app_name = Some("perf-service".to_string()); + + let client = Client::with_options(client_options).map_err(|e| { + let msg = format!("init mangodb client error: {}", e); + error!("{}", msg); + + BuckyError::from(msg) + })?; + + let db_name = if let Some(isolate) = isolate { + format!("{}-{}", isolate, MONGO_DB_DEFAULT_NAME) + } else { + MONGO_DB_DEFAULT_NAME.to_owned() + }; + + info!("use mongo db: {}", db_name); + + let db = client.database(&db_name); + let _ = Self::ping(&db).await; + + Self::dump_db(&db); + + // init request coll + let request_coll = db.collection(MONGO_COLL_NAME_REQUEST); + Self::dump_coll(&request_coll, MONGO_COLL_NAME_REQUEST.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_REQUEST.to_string()).await?; + + // init action coll + let action_coll = db.collection(MONGO_COLL_NAME_ACTION); + Self::dump_coll(&action_coll, MONGO_COLL_NAME_ACTION.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_ACTION.to_string()).await?; + + // init record coll + let record_coll = db.collection(MONGO_COLL_NAME_RECORD); + Self::dump_coll(&record_coll, MONGO_COLL_NAME_RECORD.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_RECORD.to_string()).await?; + + + // init acc coll + let acc_coll = db.collection(MONGO_COLL_NAME_ACC); + Self::dump_coll(&acc_coll, MONGO_COLL_NAME_ACC.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_ACC.to_string()).await?; + + + let ret = Self { client, db, request_coll, action_coll, acc_coll, record_coll}; + Ok(ret) + } + + + pub async fn query_index(db: &Database, coll_name: String) -> BuckyResult<()>{ + // 查询索引 + let doc = doc! { + "listIndexes": coll_name, + }; + + let _ret = db.run_command(doc, None).await.map_err(|e| { + let msg = format!("list index on coll error: {}", e); + error!("{}", msg); + + BuckyError::from(msg) + })?; + + Ok(()) + } + + pub async fn init_coll(db: &Database, coll_name: String) -> BuckyResult<()> { + const INDEX_NAME: &str = "people_id"; + + // 建立索引 + // https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/ + let doc = doc! { + "createIndexes": coll_name, + "indexes": [ + { + "key": { + "people_id": 1, + }, + "name": INDEX_NAME, + "unique": false, + }, + ], + }; + + let ret = db.run_command(doc, None).await.map_err(|e| { + let msg = format!("create index on coll error: {}", e); + error!("{}", msg); + BuckyError::from(msg) + + })?; + + trace!("{}", ret); + + let ok = ret.get_f64("ok").unwrap(); + + if ok == 1.0 { + if let Ok(note) = ret.get_str("note") { + info!("index already exists: {} {}", INDEX_NAME, note); + } else { + info!("create index success: {}", INDEX_NAME); + } + } else { + if let Ok(note) = ret.get_str("note") { + info!("index already exists: {} {}", INDEX_NAME, note); + } else { + let err = ret.get("errmsg"); + let code = ret.get("code"); + + let msg = format!("create index error: {} {:?} {:?}", INDEX_NAME, err, code); + error!("{}", msg); + + } + } + + Ok(()) + + } + + fn dump_db(db: &Database) { + let db = db.clone(); + task::spawn(async move { + match db.list_collection_names(None).await { + Ok(list) => { + info!("collections in {} as follows: {:?}", db.name(), list); + } + Err(e) => { + error!("list_collection_names error: {}", e); + } + } + }); + } + + fn dump_coll(coll: &Collection, coll_name: String) { + let coll = coll.clone(); + let coll_name = coll_name.clone(); + task::spawn(async move { + match coll.count_documents(None, None).await { + Ok(list) => { + info!("collection {} has doc count: {}", coll_name, list); + } + Err(e) => { + error!("count_documents error: {}", e); + } + } + }); + } + + pub async fn ping(db: &Database) -> BuckyResult<()>{ + let doc = doc! { + "ping": 1, + }; + + let _doc = db.run_command(doc, None).await.map_err(|e| { + let _msg = format!("ping error: {}", e); + error!("{}", e); + }).map_err(|_e|{ + error!{"async fn ping db_run_command() failed!"}; + }); + + Ok(()) + } + + + // 判断是不是相同object_id的项目已经存在 + fn is_exists_error(e: &Error) -> bool { + if let ErrorKind::Write(WriteFailure::WriteError(e)) = e.kind.as_ref() { + if e.code == 11000 { + return true; + } + } + + false + } + + + async fn insert_reqs_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.to_owned(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let reqs = v.reqs.clone(); + + let mut reqs_vec = Vec::new(); + for (_k1, v1) in reqs { + doc.insert("item_id", v1.id); + doc.insert("time", bucky_time_to_chrono_time(v1.time_range.begin)); + doc.insert("time_begin", bucky_time_to_chrono_time(v1.time_range.begin)); + doc.insert("time_end", bucky_time_to_chrono_time(v1.time_range.end)); + doc.insert("total", v1.total); + doc.insert("success", v1.success); + doc.insert("total_time", v1.total_time as i64); + if let Some(total_size) = v1.total_size { + doc.insert("total_size", total_size as i64); + } else { + doc.insert("total_size", 0); + } + + reqs_vec.push(doc.clone()); + } + + if !reqs_vec.is_empty() { + let _ = self.request_coll.insert_many(reqs_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to req coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to req coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_request success: obj={:?}", all); + + reqs_vec.clear(); + } + } + + Ok(()) + } + + async fn insert_action_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.clone(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let actions = v.actions.clone(); + + let mut actions_vec = Vec::new(); + for action in actions { + doc.insert("item_id", action.id); + doc.insert("time", bucky_time_to_chrono_time(action.time)); + doc.insert("err", action.err); + doc.insert("name", action.name); + doc.insert("value", action.value); + + actions_vec.push(doc.clone()); + } + + if !actions_vec.is_empty() { + let _ = self.action_coll.insert_many(actions_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to action coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to action coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_action success: obj={:?}", all); + + actions_vec.clear(); + } + + } + + Ok(()) + } + + + async fn insert_acc_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.to_owned(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let accs = v.accumulations.clone(); + + let mut acc_vec = Vec::new(); + for (_k1, v1) in accs { + doc.insert("item_id", v1.id); + doc.insert("time", bucky_time_to_chrono_time(v1.time_range.begin.clone())); + doc.insert("time_begin", bucky_time_to_chrono_time(v1.time_range.begin)); + doc.insert("time_end", bucky_time_to_chrono_time(v1.time_range.end)); + doc.insert("total", v1.total); + doc.insert("success", v1.success); + if let Some(total_size) = v1.total_size { + doc.insert("total_size", total_size as i64); + } else { + doc.insert("total_size", 0); + } + + acc_vec.push(doc.clone()); + } + + if !acc_vec.is_empty() { + let _ = self.acc_coll.insert_many(acc_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to acc coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to acc coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_accumulation success: obj={:?}", all); + acc_vec.clear(); + } + } + + Ok(()) + } + + + async fn insert_record_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.to_owned(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let records = v.records.clone(); + + let mut record_vec = Vec::new(); + for (_k1, v1) in records { + doc.insert("item_id", v1.id); + doc.insert("time", bucky_time_to_chrono_time(v1.time)); + doc.insert("total", v1.total as i64); + if let Some(total_size) = v1.total_size { + doc.insert("total_size", total_size as i64); + } else { + doc.insert("total_size", 0); + } + + record_vec.push(doc.clone()); + } + + if !record_vec.is_empty() { + let _ = self.record_coll.insert_many(record_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to record coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to record coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_record success: obj={:?}", all); + + record_vec.clear(); + } + } + + Ok(()) + } + + + pub async fn insert_entity_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + + let _ = self.insert_reqs_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + let _ = self.insert_action_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + let _ = self.insert_acc_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + let _ = self.insert_record_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + + Ok(()) + } + +} + +#[async_trait] +impl Storage for MangodbStorage { + async fn insert_entity_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + self.insert_entity_list(people_id, device_id, dec_id, dec_name, version, all).await + } +} \ No newline at end of file From aa04526646c6f1a6774c2d1945b3fd18f9040384 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 13:51:50 +0800 Subject: [PATCH 183/553] Do not cache chunk if already exists in data request --- src/component/cyfs-bdt-ext/src/cache/reader/cache.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs index 07991125d..6ca443db5 100644 --- a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs +++ b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs @@ -62,6 +62,7 @@ impl ChunkListCacheReader { let ret = chunk_manager.exist(cache.chunk()).await; if ret { debug!("cache chunk to chunk manager but already exists! chunk={}", cache.chunk()); + return; } let cache_wrapper = ChunkCacheWrapper::new(cache.clone()); From ca341c36a0f5d09584d755e02c8ef04f967b2d7f Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 13:56:49 +0800 Subject: [PATCH 184/553] Fix body length error when mime sniffing in cyfs-runtime --- src/service/cyfs-runtime/src/mime.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/service/cyfs-runtime/src/mime.rs b/src/service/cyfs-runtime/src/mime.rs index 405b385af..d6e7a5653 100644 --- a/src/service/cyfs-runtime/src/mime.rs +++ b/src/service/cyfs-runtime/src/mime.rs @@ -78,8 +78,12 @@ impl MimeHelper { // 根据内容猜测 // read some content and try sniff the mime use async_std::io::ReadExt; - let mut body = resp.take_body().into_reader(); let body_len = resp.len(); + if body_len == Some(0) { + return; + } + + let mut body = resp.take_body().into_reader(); let mut content: Vec = vec![0; 512]; let read_content_len; match body.read(&mut content).await { From 3a20012af2f838a401f4442efe2bc980e4497a07 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 16:15:21 +0800 Subject: [PATCH 185/553] Optimize some logs level --- .../cyfs-chunk-cache/src/local_chunk_cache.rs | 2 +- .../cyfs-stack/src/interface/browser_server.rs | 2 +- .../src/non_api/inner_path/objectmap_loader.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs index 5fb4bed09..9bd4887c3 100644 --- a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs +++ b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs @@ -630,7 +630,7 @@ impl TSingleDiskChunkCache for SingleDiskChunkCache { #[async_trait::async_trait] impl ChunkCache for SingleDiskChunkCache { async fn get_chunk(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult> { - log::info!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); + log::debug!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); let file_path = self.get_file_path(chunk_id, false); if !file_path.exists() { #[cfg(target_os = "windows")] diff --git a/src/component/cyfs-stack/src/interface/browser_server.rs b/src/component/cyfs-stack/src/interface/browser_server.rs index ae27a7433..c7e63153d 100644 --- a/src/component/cyfs-stack/src/interface/browser_server.rs +++ b/src/component/cyfs-stack/src/interface/browser_server.rs @@ -376,7 +376,7 @@ impl BrowserSanboxHttpServer { } } None => { - warn!("browser dec request but dec_id header or query pairs missing! req={}, origin={:?}", req.url(), origin); + debug!("browser dec request but dec_id header or query pairs missing! req={}, origin={:?}", req.url(), origin); drop(origin); // insert the origin dec_id diff --git a/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs b/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs index 5964b236e..e2e20b01b 100644 --- a/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs +++ b/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs @@ -27,11 +27,6 @@ impl NONObjectMapLoader { pub async fn load(&self, req: NONGetObjectInputRequest) -> BuckyResult { let inner_path = req.inner_path.unwrap(); - info!( - "will get objectmap with inner path: {}, {}", - req.object_id, inner_path - ); - assert_eq!(req.object_id.obj_type_code(), ObjectTypeCode::ObjectMap); // first check access at object level @@ -97,6 +92,11 @@ impl NONObjectMapLoader { let (object, object_raw) = ret.unwrap(); + info!( + "get object from objectmap with inner path: {}, {}, got={}", + req.object_id, inner_path, object_id, + ); + let info = NONObjectInfo { object_id: object_id.to_owned(), object_raw, From a7c1bfc921144a11aeeccd1b0f579043df2e00c3 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 19:33:18 +0800 Subject: [PATCH 186/553] Fix the bug that build file object access cannot take effect --- src/component/cyfs-stack/src/util_api/local/build_dir_task.rs | 4 ++-- .../cyfs-stack/src/util_api/local/build_file_task.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs b/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs index 119789132..3379abf79 100644 --- a/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs +++ b/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs @@ -512,7 +512,7 @@ impl BuildDirTask { start_pos: usize, ) -> BuckyResult { let path_str = path.to_string_lossy().to_string(); - log::info!("build_dir {}", path_str.as_str()); + log::info!("build_dir {}, start_pos={}", path_str, start_pos); { let mut task_state = self.task_state.lock().unwrap(); if !task_state @@ -583,7 +583,7 @@ impl BuildDirTask { let file_id = file.desc().calculate_id(); Ok((task_id, file_name, file_id)) } else { - let msg = format!("build_file_object unexpect status"); + let msg = format!("build_file_object unexpect status, task={}", task_id); log::error!("{}", msg.as_str()); Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)) } diff --git a/src/component/cyfs-stack/src/util_api/local/build_file_task.rs b/src/component/cyfs-stack/src/util_api/local/build_file_task.rs index bdc387b58..c4f226056 100644 --- a/src/component/cyfs-stack/src/util_api/local/build_file_task.rs +++ b/src/component/cyfs-stack/src/util_api/local/build_file_task.rs @@ -347,7 +347,7 @@ impl BuildFileTask { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: self.access, }; match self.noc.put_object(&req).await { @@ -633,6 +633,7 @@ mod build_file_task_test { chunk_size: 4 * 1024 * 1024, dec_id: dec_id.to_owned(), access: None, + chunk_method: TransPublishChunkMethod::default(), }; let task = task_manager .create_task( @@ -673,6 +674,7 @@ mod build_file_task_test { chunk_size: 4 * 1024 * 1024, dec_id: dec_id.to_owned(), access: None, + chunk_method: TransPublishChunkMethod::default(), }; let task = task_manager .create_task( From 415439a405b8ef1a3b7305e69f0b24f3d8103725 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 19:39:19 +0800 Subject: [PATCH 187/553] Add chunk length verify to poll_read method in cache reader --- .../cyfs-bdt-ext/src/cache/reader/cache.rs | 63 ++++++++++++++----- .../src/data/target_data_manager.rs | 2 + 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs index 6ca443db5..8a12ebc68 100644 --- a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs +++ b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs @@ -1,14 +1,13 @@ +use cyfs_base::*; use cyfs_bdt::{chunk::ChunkCache, DownloadTaskSplitRead}; use cyfs_chunk_cache::ChunkManagerRef; use cyfs_chunk_lib::*; -use cyfs_base::*; use async_std::io::{Read, Result}; use std::io::{Seek, SeekFrom}; use std::pin::Pin; use std::task::{Context, Poll}; - pub trait ChunkSplitReader: DownloadTaskSplitRead + Seek {} impl ChunkSplitReader for T {} @@ -19,15 +18,25 @@ pub struct ChunkListCacheReader { chunk_manager: ChunkManagerRef, last_cache_chunk: Option, + full_len: u64, + read_len: u64, } impl ChunkListCacheReader { pub fn new( chunk_manager: ChunkManagerRef, task_id: String, + full_len: u64, reader: Box, ) -> Self { - Self { task_id, reader, chunk_manager, last_cache_chunk: None, } + Self { + task_id, + reader, + chunk_manager, + last_cache_chunk: None, + full_len, + read_len: 0, + } } fn try_cache_chunk(&mut self, cache: &ChunkCache) { @@ -61,17 +70,30 @@ impl ChunkListCacheReader { async_std::task::spawn(async move { let ret = chunk_manager.exist(cache.chunk()).await; if ret { - debug!("cache chunk to chunk manager but already exists! chunk={}", cache.chunk()); + debug!( + "cache chunk to chunk manager but already exists! chunk={}", + cache.chunk() + ); return; } let cache_wrapper = ChunkCacheWrapper::new(cache.clone()); - match chunk_manager.put_chunk(cache.chunk(), Box::new(cache_wrapper)).await { + match chunk_manager + .put_chunk(cache.chunk(), Box::new(cache_wrapper)) + .await + { Ok(()) => { - info!("cache chunk to chunk manager success! chunk={}", cache.chunk()); + info!( + "cache chunk to chunk manager success! chunk={}", + cache.chunk() + ); } Err(e) => { - info!("cache chunk to chunk manager failed! chunk={}, {}", cache.chunk(), e); + info!( + "cache chunk to chunk manager failed! chunk={}, {}", + cache.chunk(), + e + ); } } }); @@ -87,11 +109,26 @@ impl Read for ChunkListCacheReader { match Pin::new(self.reader.as_mut()).poll_split_read(cx, buf) { Poll::Ready(ret) => match ret { Ok(Some((cache, range))) => { + self.read_len += range.len() as u64; self.try_cache_chunk(&cache); Poll::Ready(Ok(range.len())) } - Ok(None) => Poll::Ready(Ok(0)), - Err(e) => Poll::Ready(Err(e)), + Ok(None) => { + if self.full_len != self.read_len { + error!( + "unmatch data size got from bdt: data={}, len={}, got={}", + self.task_id, self.full_len, self.read_len + ); + } + Poll::Ready(Ok(0)) + } + Err(e) => { + warn!( + "read data from bdt got error! data={}, len={}, {}", + self.task_id, self.full_len, e + ); + Poll::Ready(Err(e)) + } }, Poll::Pending => Poll::Pending, } @@ -99,10 +136,7 @@ impl Read for ChunkListCacheReader { } impl Seek for ChunkListCacheReader { - fn seek( - self: &mut Self, - pos: SeekFrom, - ) -> std::io::Result { + fn seek(self: &mut Self, pos: SeekFrom) -> std::io::Result { Pin::new(self.reader.as_mut()).seek(pos) } } @@ -149,7 +183,8 @@ impl Chunk for ChunkCacheWrapper { } async fn read(&mut self, buf: &mut [u8]) -> BuckyResult { - let len = self.cache + let len = self + .cache .read(self.offset, buf, || std::future::pending()) .await?; self.offset += len; diff --git a/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs b/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs index 662b2b892..80bf56b8b 100644 --- a/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs +++ b/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs @@ -85,6 +85,7 @@ impl TargetDataManager { let reader = ChunkListCacheReader::new( self.chunk_manager.clone(), file_id.to_string(), + total_size, Box::new(reader), ); @@ -154,6 +155,7 @@ impl TargetDataManager { let reader = ChunkListCacheReader::new( self.chunk_manager.clone(), chunk_id.to_string(), + total_size as u64, Box::new(reader), ); From c5f416f29bb5db0b239234120d744de0fc73da2c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 3 Mar 2023 00:32:33 +0800 Subject: [PATCH 188/553] Add chunk length and hash verify when write to local cache --- .../cyfs-chunk-cache/src/local_chunk_cache.rs | 597 +++++++++++++----- .../src/trans_api/local/publish_manager.rs | 4 +- 2 files changed, 428 insertions(+), 173 deletions(-) diff --git a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs index 9bd4887c3..368554f41 100644 --- a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs +++ b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs @@ -1,17 +1,17 @@ -use std::fs::{create_dir_all}; +use crate::{Chunk, ChunkCache, ChunkMut, ChunkType, MMapChunk, MMapChunkMut, MemChunk}; +use cyfs_base::*; +use cyfs_chunk_lib::{ChunkMeta}; +use cyfs_debug::Mutex; +use futures_lite::AsyncWriteExt; +use num_traits::abs; +use num_traits::float::Float; +use scan_dir::ScanDir; +use std::fs::create_dir_all; use std::hash::Hasher; use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock}; use std::u64; -use cyfs_base::*; use sysinfo::{DiskExt, RefreshKind, SystemExt}; -use crate::{Chunk, ChunkCache, ChunkMut, MMapChunk, MMapChunkMut, MemChunk, ChunkType}; -use num_traits::float::Float; -use futures_lite::AsyncWriteExt; -use num_traits::abs; -use scan_dir::ScanDir; -use cyfs_chunk_lib::{ChunkMeta, ChunkRead}; -use cyfs_debug::Mutex; #[derive(Clone, RawEncode, RawDecode)] pub(crate) struct LocalChunkCacheMetaRecord { @@ -52,7 +52,7 @@ impl LocalChunkCacheMetaRecord { pub fn get_weight(&self, path: &str) -> Option { for (item, weight) in self.list.iter() { if path == item.as_str() { - return Some(*weight) + return Some(*weight); } } None @@ -71,40 +71,30 @@ impl LocalChunkCacheMeta { pub fn add_update_record(&mut self, disk_cache_list: Vec<(String, u32)>) { let record = match self.list.last() { - Some(last) => { - LocalChunkCacheMetaRecord::new(Some(last.hash()), disk_cache_list) - }, - None => { - LocalChunkCacheMetaRecord::new(None, disk_cache_list) - } + Some(last) => LocalChunkCacheMetaRecord::new(Some(last.hash()), disk_cache_list), + None => LocalChunkCacheMetaRecord::new(None, disk_cache_list), }; self.list.push(record); } pub fn last_hash(&self) -> Option { match self.list.last() { - Some(last) => { - last.prev_hash.clone() - }, - None => None + Some(last) => last.prev_hash.clone(), + None => None, } } pub fn is_latest(&self, disk_cache_list: &Vec<(String, u32)>) -> bool { match self.list.last() { - Some(last) => { - last.is_same(disk_cache_list) - }, - None => false + Some(last) => last.is_same(disk_cache_list), + None => false, } } pub fn get_latest_weight(&self, path: &str) -> Option { match self.list.last() { - Some(last) => { - last.get_weight(path) - }, - None => None + Some(last) => last.get_weight(path), + None => None, } } @@ -114,10 +104,8 @@ impl LocalChunkCacheMeta { pub fn get_latest_record(&self) -> Option { match self.list.last() { - Some(last) => { - Some(last.clone()) - }, - None => None + Some(last) => Some(last.clone()), + None => None, } } @@ -141,7 +129,7 @@ pub(crate) fn get_cache_path_list() -> Vec<(PathBuf, u64)> { cache_list } -pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64){ +pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64) { let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_disks_list()); let dist_list = system.disks(); let mut total = 0; @@ -149,7 +137,10 @@ pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64){ let mut max_match_path = PathBuf::new(); for disk in dist_list { let disk_mount = disk.mount_point().to_path_buf(); - if path.starts_with(disk_mount.as_path()) && max_match_path.to_string_lossy().to_string().len() < disk_mount.to_string_lossy().to_string().len() { + if path.starts_with(disk_mount.as_path()) + && max_match_path.to_string_lossy().to_string().len() + < disk_mount.to_string_lossy().to_string().len() + { max_match_path = disk_mount; total = disk.total_space(); available = disk.available_space(); @@ -160,21 +151,25 @@ pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64){ pub(crate) async fn get_path_size(path: PathBuf) -> BuckyResult { async_std::task::spawn_blocking(move || { - ScanDir::files().skip_dirs(true).walk(path.as_path(), |it| { - let mut sum = 0; - for (entry, _) in it { - match entry.metadata() { - Ok(meta) => sum += meta.len(), - Err(_) => {} + ScanDir::files() + .skip_dirs(true) + .walk(path.as_path(), |it| { + let mut sum = 0; + for (entry, _) in it { + match entry.metadata() { + Ok(meta) => sum += meta.len(), + Err(_) => {} + } } - } - sum - }).map_err(|_e| { - let msg = format!("scan path {} err", path.to_string_lossy().to_string()); - log::error!("{}", msg.as_str()); - BuckyError::new(BuckyErrorCode::Failed, msg) - }) - }).await + sum + }) + .map_err(|_e| { + let msg = format!("scan path {} err", path.to_string_lossy().to_string()); + log::error!("{}", msg.as_str()); + BuckyError::new(BuckyErrorCode::Failed, msg) + }) + }) + .await } pub(crate) trait DiskScanner: Send + Sync { @@ -196,13 +191,19 @@ pub(crate) struct LocalChunkCache LocalChunkCache { +impl + LocalChunkCache +{ pub async fn new(isolate: &str, scanner: SCANNER) -> BuckyResult { let obj = Self { disk_cache_list: RwLock::new(Vec::new()), cache_meta: Mutex::new(LocalChunkCacheMeta::new()), scanner, - isolate: if isolate.is_empty() { "default".to_string() } else { isolate.to_string() } + isolate: if isolate.is_empty() { + "default".to_string() + } else { + isolate.to_string() + }, }; obj.refresh_cache().await?; Ok(obj) @@ -225,21 +226,21 @@ impl LocalChun // 遍历磁盘列表 let cache_list = self.scanner.get_cache_path_list(); for (path, space) in cache_list.iter() { - log::info!("read cache path {} {}", path.to_string_lossy().to_string(), *space); + log::info!( + "read cache path {} {}", + path.to_string_lossy().to_string(), + *space + ); let path = path.as_path().join(self.isolate.as_str()); if !path.exists() { let _ = create_dir_all(path.as_path()); } let cache = match self.get_cache(path.as_path()) { - Some(cache) => { - cache - }, - None => { - Arc::new(CACHE::new(path.to_path_buf())) - } + Some(cache) => cache, + None => Arc::new(CACHE::new(path.to_path_buf())), }; let cache_meta = cache.get_local_cache_meta()?; - let weight = (space/1024/1024/1024) as u32; + let weight = (space / 1024 / 1024 / 1024) as u32; // 获取最新的cache元数据列表 if cache_meta.record_count() as i32 > max_record_count { @@ -255,12 +256,20 @@ impl LocalChun let mut meta_list = Vec::new(); for (cache, weight) in disk_cache_list.iter_mut() { let path_str = cache.get_cache_path().to_string_lossy().to_string(); - if let Some(latest_weight) = global_last_record.get_latest_weight(path_str.as_str()) { + if let Some(latest_weight) = global_last_record.get_latest_weight(path_str.as_str()) + { //如果当前空间大于上次记录空间,表示该区域已经扩容 if *weight > latest_weight { - let path_size = (get_path_size(cache.get_cache_path().to_path_buf()).await?/1024/1024/1024) as u32; + let path_size = (get_path_size(cache.get_cache_path().to_path_buf()) + .await? + / 1024 + / 1024 + / 1024) as u32; //如果新扩容区域小于上次记录空间的20%或扩容空间小于50G,则保持全新不变 - if ((*weight + path_size - latest_weight) as f32 / (latest_weight as f32) < 0.2 ) || (*weight + path_size - latest_weight < 50) { + if ((*weight + path_size - latest_weight) as f32 / (latest_weight as f32) + < 0.2) + || (*weight + path_size - latest_weight < 50) + { *weight = latest_weight; } else { *weight = *weight + path_size; @@ -269,10 +278,16 @@ impl LocalChun } else if *weight > 10 || *weight as f32 / (latest_weight as f32) > 0.1 { *weight = latest_weight; } else { - let path_size = (get_path_size(cache.get_cache_path().to_path_buf()).await?/1024/1024/1024) as u32; + let path_size = (get_path_size(cache.get_cache_path().to_path_buf()) + .await? + / 1024 + / 1024 + / 1024) as u32; //如果理论剩余空间和真实剩余空间的比例小于15%或理论剩余空间和真实剩余空间的差值小于5G,则保持权重不变 - if abs(1f32 - (latest_weight - path_size) as f32 / (*weight as f32)) < 0.15 || abs(latest_weight as i64 - path_size as i64 - *weight as i64) < 5 { + if abs(1f32 - (latest_weight - path_size) as f32 / (*weight as f32)) < 0.15 + || abs(latest_weight as i64 - path_size as i64 - *weight as i64) < 5 + { *weight = latest_weight; } else { *weight = path_size + *weight; @@ -286,7 +301,10 @@ impl LocalChun if !global_last_record.is_latest(&meta_list) { global_last_record.add_update_record(meta_list); - log::info!("chunk cache change.item count {}", global_last_record.record_count()); + log::info!( + "chunk cache change.item count {}", + global_last_record.record_count() + ); for (cache, _) in disk_cache_list.iter_mut() { cache.set_local_cache_meta(&global_last_record)?; @@ -317,7 +335,7 @@ impl LocalChun } for (disk_cache, weight) in disk_cache_list.iter() { let hash = Self::hash(chunk_id, disk_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; cache = Some(disk_cache); @@ -341,7 +359,7 @@ impl LocalChun } for (disk_cache, weight) in disk_cache_list.iter() { let hash = Self::hash(chunk_id, disk_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; cache = Some(disk_cache); @@ -357,7 +375,11 @@ impl LocalChun } } - async fn find_chunk_from_prev_async(&self, chunk_id: &ChunkId, cache: &Arc) -> BuckyResult<()> { + async fn find_chunk_from_prev_async( + &self, + chunk_id: &ChunkId, + cache: &Arc, + ) -> BuckyResult<()> { let cache_meta = self.cache_meta.lock().unwrap().clone(); let mut index = cache_meta.record_count() as i64 - 2; while index >= 0 { @@ -367,7 +389,7 @@ impl LocalChun for (cache_path, weight) in record.list.iter() { let tmp_cache = Arc::new(CACHE::new(PathBuf::from(cache_path.to_string()))); let hash = Self::hash(chunk_id, tmp_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; max_cache = Some(tmp_cache); @@ -378,7 +400,7 @@ impl LocalChun if let Ok(chunk) = tmp_cache.get_chunk(chunk_id, ChunkType::MMapChunk).await { cache.put_chunk(chunk_id, chunk).await?; tmp_cache.delete_chunk(chunk_id).await?; - return Ok(()) + return Ok(()); } } index -= 1; @@ -396,7 +418,7 @@ impl LocalChun for (cache_path, weight) in record.list.iter() { let tmp_cache = Arc::new(CACHE::new(PathBuf::from(cache_path.to_string()))); let hash = Self::hash(chunk_id, tmp_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; max_cache = Some(tmp_cache); @@ -405,7 +427,7 @@ impl LocalChun if max_cache.is_some() { let tmp_cache = max_cache.unwrap(); if tmp_cache.is_exist(chunk_id).await { - return Ok(tmp_cache) + return Ok(tmp_cache); } } index -= 1; @@ -415,13 +437,17 @@ impl LocalChun } #[async_trait::async_trait] -impl ChunkCache for LocalChunkCache { - async fn get_chunk(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult> { +impl ChunkCache + for LocalChunkCache +{ + async fn get_chunk( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult> { let cache = self.get_disk_cache(chunk_id)?; match cache.get_chunk(chunk_id, chunk_type).await { - Ok(chunk) => { - Ok(chunk) - }, + Ok(chunk) => Ok(chunk), Err(e) => { if e.code() == BuckyErrorCode::NotFound { self.find_chunk_from_prev_async(chunk_id, &cache).await?; @@ -459,24 +485,26 @@ impl ChunkCach async fn is_exist(&self, chunk_id: &ChunkId) -> bool { let cache = match self.get_disk_cache(chunk_id) { Ok(cache) => cache, - Err(_) => return false + Err(_) => return false, }; if !cache.is_exist(chunk_id).await { match self.find_chunk_from_prev_async(chunk_id, &cache).await { Ok(()) => true, - Err(_) => false + Err(_) => false, } } else { true } } - async fn get_chunk_meta(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult { + async fn get_chunk_meta( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult { let cache = self.get_disk_cache(chunk_id)?; match cache.get_chunk_meta(chunk_id, chunk_type).await { - Ok(chunk) => { - Ok(chunk) - }, + Ok(chunk) => Ok(chunk), Err(e) => { if e.code() == BuckyErrorCode::NotFound { self.find_chunk_from_prev_async(chunk_id, &cache).await?; @@ -518,24 +546,20 @@ impl SingleDiskChunkCache { let hash_str = file_id.to_base36(); let (tmp, last) = hash_str.split_at(hash_str.len() - 3); let (mut first, mut mid) = tmp.split_at(tmp.len() - 3); - + /* Do not use the following reserved names as filenames: CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、 LPT6、LPT7、LPT8、 LPT9 */ match mid { "con" | "aux" | "nul" | "prn" => { (first, mid) = tmp.split_at(tmp.len() - 4); } - _ => {}, + _ => {} } let last = match last { - "con" | "aux" | "nul" | "prn" => { - Cow::Owned(format!("{}_", last)) - } - _ => { - Cow::Borrowed(last) - }, + "con" | "aux" | "nul" | "prn" => Cow::Owned(format!("{}_", last)), + _ => Cow::Borrowed(last), }; - + let path = self.path.join(last.as_ref()).join(mid); if is_create && !path.exists() { if let Err(e) = create_dir_all(path.as_path()) { @@ -561,10 +585,16 @@ impl SingleDiskChunkCache { pub async fn remove_file(&self, file_id: &ChunkId) -> BuckyResult<()> { let file_path = self.get_file_path(file_id, false); - let _ = async_std::fs::remove_file(file_path.as_path()).await.map_err(|e| { - log::error!("remove file {} failed.err={}", file_path.to_string_lossy().to_string(), &e); - BuckyError::from(e) - }); + let _ = async_std::fs::remove_file(file_path.as_path()) + .await + .map_err(|e| { + log::error!( + "remove file {} failed.err={}", + file_path.to_string_lossy().to_string(), + &e + ); + BuckyError::from(e) + }); Ok(()) } @@ -577,7 +607,11 @@ impl SingleDiskChunkCache { let file_meta = match std::fs::metadata(file_path.as_path()) { Ok(meta) => meta, Err(e) => { - let msg = format!("read file {} meta err.{}", file_path.to_string_lossy().to_string(), e); + let msg = format!( + "read file {} meta err.{}", + file_path.to_string_lossy().to_string(), + e + ); log::error!("{}", msg); return false; } @@ -589,6 +623,67 @@ impl SingleDiskChunkCache { true } } + + async fn write_with_verify( + chunk_id: ChunkId, + mut chunk: Box, + mut file: async_std::fs::File, + file_path: &Path, + ) -> BuckyResult<()> { + use sha2::Digest; + + let mut sha256 = sha2::Sha256::new(); + let mut buf = Vec::with_capacity(1024 * 256); + unsafe { + buf.set_len(1024 * 256); + } + + let mut file_len = 0; + loop { + match chunk.read(&mut buf).await { + Ok(bytes) => { + if bytes == 0 { + break Ok(()); + } + + sha256.input(&buf[0..bytes]); + file_len += bytes; + + file.write_all(&buf[0..bytes]).await.map_err(|e| { + let msg = format!( + "write chunk slice to file failed! chunk={}, slice bytes={}, file={}, {}", + chunk_id, + bytes, + file_path.display(), + e + ); + log::error!("{}", msg); + let e: BuckyError = e.into(); + e.with_msg(msg) + })?; + } + Err(e) => { + break Err(e); + } + } + }?; + + if file_len != chunk_id.len() { + let msg = format!("mismatched chunk length! chunk={}, len={}, got={}", chunk_id, chunk_id.len(), file_len); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + } + + let hash: HashValue = sha256.result().into(); + let actual_id = ChunkId::new(&hash, file_len as u32); + if actual_id != chunk_id { + let msg = format!("mismatched chunk hash value! chunk={}, len={}, got={}", chunk_id, chunk_id.len(), actual_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + } + + Ok(()) + } } impl TSingleDiskChunkCache for SingleDiskChunkCache { @@ -616,7 +711,8 @@ impl TSingleDiskChunkCache for SingleDiskChunkCache { if !meta_path.exists() { return Ok(LocalChunkCacheMeta::new()); } - let (meta, _) = LocalChunkCacheMeta::decode_from_file(meta_path.as_path(), &mut Vec::new())?; + let (meta, _) = + LocalChunkCacheMeta::decode_from_file(meta_path.as_path(), &mut Vec::new())?; Ok(meta) } @@ -629,21 +725,33 @@ impl TSingleDiskChunkCache for SingleDiskChunkCache { #[async_trait::async_trait] impl ChunkCache for SingleDiskChunkCache { - async fn get_chunk(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult> { + async fn get_chunk( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult> { log::debug!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); let file_path = self.get_file_path(chunk_id, false); if !file_path.exists() { #[cfg(target_os = "windows")] { if !self.upgrade.try_update(&file_path, chunk_id) { - let msg = format!("get chunk's file but not exist! chunk={}, file={}", chunk_id, file_path.display()); + let msg = format!( + "get chunk's file but not exist! chunk={}, file={}", + chunk_id, + file_path.display() + ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } } #[cfg(not(target_os = "windows"))] { - let msg = format!("get chunk's file but not exist! chunk={}, file={}", chunk_id, file_path.display()); + let msg = format!( + "get chunk's file but not exist! chunk={}, file={}", + chunk_id, + file_path.display() + ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } @@ -653,13 +761,20 @@ impl ChunkCache for SingleDiskChunkCache { ChunkType::MMapChunk => { let chunk: Box = Box::new(MMapChunk::open(file_path, None).await?); Ok(chunk) - }, + } ChunkType::MemChunk => { - let buf = async_std::fs::read(file_path.as_path()).await.map_err(|e| { - let msg = format!("open chunk's file error! chunk={}, file={}, {}", chunk_id, file_path.display(), e); - log::error!("{}", msg); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let buf = async_std::fs::read(file_path.as_path()) + .await + .map_err(|e| { + let msg = format!( + "open chunk's file error! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; let chunk: Box = Box::new(MemChunk::from(buf)); Ok(chunk) } @@ -670,7 +785,12 @@ impl ChunkCache for SingleDiskChunkCache { let file_path = self.get_file_path(chunk_id, true); log::info!("new chunk {}", file_path.to_string_lossy().to_string()); if file_path.exists() { - let msg = format!("[{}:{}] file {} exist", file!(), line!(), file_path.to_string_lossy().to_string()); + let msg = format!( + "[{}:{}] file {} exist", + file!(), + line!(), + file_path.to_string_lossy().to_string() + ); log::error!("{}", msg.as_str()); return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, msg)); } @@ -694,40 +814,92 @@ impl ChunkCache for SingleDiskChunkCache { // log::info!("will put chunk, chunk={}, len={}, local file={}", chunk_id, chunk_id.len(), file_path.display()); if file_path.exists() { - let msg = format!("put chunk but local file already exist! chunk={}, file={},", chunk_id, file_path.display()); + let msg = format!( + "put chunk but local file already exist! chunk={}, file={},", + chunk_id, + file_path.display() + ); log::info!("{}", msg.as_str()); return Ok(()); } - let mut file = async_std::fs::OpenOptions::new().read(true).write(true).create(true).open(file_path.as_path()).await.map_err(|e| { - let msg = format!("put chunk but open local file failed! chunk={}, file={}, {}", chunk_id, file_path.display(), e); - log::error!("{}", msg); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let mut file = async_std::fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(file_path.as_path()) + .await + .map_err(|e| { + let msg = format!( + "put chunk but open local file failed! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; chunk.as_mut().seek(std::io::SeekFrom::Start(0)).await?; + if let Err(e) = Self::write_with_verify(chunk_id.to_owned(), chunk, file.clone(), &file_path).await { + if let Err(e) = async_std::fs::remove_file(&file_path).await { + log::error!("remove chunk local cache file failed! chunk={}, {}", chunk_id, e); + } + + return Err(e); + } + + /* let reader = ChunkRead::new(chunk); - let len = async_std::io::copy(reader, file.clone()).await.map_err(|e| { - let msg = format!("write chunk to file failed! chunk={}, len={}, file={}, {}", chunk_id, chunk_id.len(), file_path.display(), e); - log::error!("{}", msg); - let e: BuckyError = e.into(); - e.with_msg(msg) - })?; + let len = async_std::io::copy(reader, file.clone()) + .await + .map_err(|e| { + let msg = format!( + "write chunk to file failed! chunk={}, len={}, file={}, {}", + chunk_id, + chunk_id.len(), + file_path.display(), + e + ); + log::error!("{}", msg); + let e: BuckyError = e.into(); + e.with_msg(msg) + })?; if len != chunk_id.len() as u64 { - let msg = format!("write chunk to file but got unmatch len! chunk={}, len={}, read={}, file={}", chunk_id, chunk_id.len(), len, file_path.display()); + let msg = format!( + "write chunk to file but got unmatch len! chunk={}, len={}, read={}, file={}", + chunk_id, + chunk_id.len(), + len, + file_path.display() + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::IoError, msg)); } + */ + + if let Err(e) = file.flush().await { + if let Err(e) = async_std::fs::remove_file(&file_path).await { + log::error!("remove chunk local cache file failed! chunk={}, {}", chunk_id, e); + } - file.flush().await.map_err(|e| { - let msg = format!("put chunk to local file but flush failed! chunk={}, file={}, {}", chunk_id, file_path.display(), e); + let msg = format!( + "put chunk to local file but flush failed! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); log::error!("{}", msg); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + return Err(BuckyError::new(BuckyErrorCode::IoError, msg)); + } - log::info!("put chunk to local file complete! chunk={}, file={}", chunk_id, file_path.display()); + log::info!( + "put chunk to local file complete! chunk={}, file={}", + chunk_id, + file_path.display() + ); Ok(()) } @@ -735,25 +907,41 @@ impl ChunkCache for SingleDiskChunkCache { self.chunk_exist(chunk_id) } - async fn get_chunk_meta(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult { + async fn get_chunk_meta( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult { log::debug!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); let file_path = self.get_file_path(chunk_id, false); if !file_path.exists() { - let msg = format!("local chunk file not exists! chunk={}, file={}", file_path.display(), chunk_id); + let msg = format!( + "local chunk file not exists! chunk={}, file={}", + file_path.display(), + chunk_id + ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } match chunk_type { - ChunkType::MMapChunk => { - Ok(ChunkMeta::MMapChunk(file_path.to_string_lossy().to_string(), None)) - }, + ChunkType::MMapChunk => Ok(ChunkMeta::MMapChunk( + file_path.to_string_lossy().to_string(), + None, + )), ChunkType::MemChunk => { - let buf = async_std::fs::read(file_path.as_path()).await.map_err(|e| { - let msg = format!("open local chunk file failed! chunk={}, file={}, {}", chunk_id, file_path.display(), e); - log::error!("{}", msg.as_str()); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let buf = async_std::fs::read(file_path.as_path()) + .await + .map_err(|e| { + let msg = format!( + "open local chunk file failed! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); + log::error!("{}", msg.as_str()); + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; Ok(ChunkMeta::MemChunk(buf)) } } @@ -762,15 +950,18 @@ impl ChunkCache for SingleDiskChunkCache { #[cfg(test)] mod test_local_chunk_cache { + use crate::{ + Chunk, ChunkCache, ChunkMut, ChunkRead, ChunkType, ChunkWrite, DiskScanner, + LocalChunkCache, LocalChunkCacheMeta, TSingleDiskChunkCache, + }; + use cyfs_base::{hash_data, BuckyError, BuckyErrorCode, BuckyResult, ChunkId, HashValue}; + use cyfs_chunk_lib::ChunkMeta; + use futures_lite::{AsyncReadExt, AsyncWriteExt}; use std::collections::HashMap; use std::io::{SeekFrom, Write}; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::sync::Mutex; - use futures_lite::{AsyncReadExt, AsyncWriteExt}; - use cyfs_chunk_lib::ChunkMeta; - use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ChunkId, hash_data, HashValue}; - use crate::{ChunkCache, Chunk, ChunkMut, ChunkType, DiskScanner, LocalChunkCache, LocalChunkCacheMeta, TSingleDiskChunkCache, ChunkRead, ChunkWrite}; pub type RandomId = HashValue; @@ -797,20 +988,44 @@ mod test_local_chunk_cache { unsafe { if HAS_RUN { let mut list = Vec::new(); - list.push((PathBuf::from("/test1".to_string()), 1024*1024*1024*50)); - list.push((PathBuf::from("/test2".to_string()), 1024*1024*1024*100)); - list.push((PathBuf::from("/test3".to_string()), 1024*1024*1024*150)); - list.push((PathBuf::from("/test4".to_string()), 1024*1024*1024*200)); - list.push((PathBuf::from("/test5".to_string()), 1024*1024*1024*200)); + list.push((PathBuf::from("/test1".to_string()), 1024 * 1024 * 1024 * 50)); + list.push(( + PathBuf::from("/test2".to_string()), + 1024 * 1024 * 1024 * 100, + )); + list.push(( + PathBuf::from("/test3".to_string()), + 1024 * 1024 * 1024 * 150, + )); + list.push(( + PathBuf::from("/test4".to_string()), + 1024 * 1024 * 1024 * 200, + )); + list.push(( + PathBuf::from("/test5".to_string()), + 1024 * 1024 * 1024 * 200, + )); list } else { HAS_RUN = true; let mut list = Vec::new(); - list.push((PathBuf::from("/test1".to_string()), 1024*1024*1024*50)); - list.push((PathBuf::from("/test2".to_string()), 1024*1024*1024*100)); - list.push((PathBuf::from("/test3".to_string()), 1024*1024*1024*150)); - list.push((PathBuf::from("/test4".to_string()), 1024*1024*1024*200)); - list.push((PathBuf::from("/test5".to_string()), 1024*1024*1024*200)); + list.push((PathBuf::from("/test1".to_string()), 1024 * 1024 * 1024 * 50)); + list.push(( + PathBuf::from("/test2".to_string()), + 1024 * 1024 * 1024 * 100, + )); + list.push(( + PathBuf::from("/test3".to_string()), + 1024 * 1024 * 1024 * 150, + )); + list.push(( + PathBuf::from("/test4".to_string()), + 1024 * 1024 * 1024 * 200, + )); + list.push(( + PathBuf::from("/test5".to_string()), + 1024 * 1024 * 1024 * 200, + )); list } } @@ -830,7 +1045,7 @@ mod test_local_chunk_cache { path, cache_id, chunk_map: Mutex::new(Default::default()), - meta: Mutex::new(LocalChunkCacheMeta::new()) + meta: Mutex::new(LocalChunkCacheMeta::new()), } } @@ -855,15 +1070,17 @@ mod test_local_chunk_cache { #[async_trait::async_trait] impl ChunkCache for SingleDiskChunkCacheMock { - async fn get_chunk(&self, chunk_id: &ChunkId, _chunk_type: ChunkType) -> BuckyResult> { + async fn get_chunk( + &self, + chunk_id: &ChunkId, + _chunk_type: ChunkType, + ) -> BuckyResult> { return match self.chunk_map.lock().unwrap().get(chunk_id) { - Some(chunk) => { - Ok(Box::new(ChunkMock {buf: Vec::from(chunk.as_ref().deref())})) - }, - None => { - Err(BuckyError::new(BuckyErrorCode::NotFound, "")) - } - } + Some(chunk) => Ok(Box::new(ChunkMock { + buf: Vec::from(chunk.as_ref().deref()), + })), + None => Err(BuckyError::new(BuckyErrorCode::NotFound, "")), + }; } async fn new_chunk(&self, _chunk_id: &ChunkId) -> BuckyResult> { @@ -874,7 +1091,11 @@ mod test_local_chunk_cache { todo!() } - async fn put_chunk(&self, chunk_id: &ChunkId, mut chunk: Box) -> BuckyResult<()> { + async fn put_chunk( + &self, + chunk_id: &ChunkId, + mut chunk: Box, + ) -> BuckyResult<()> { log::info!("will put chunk, chunk={}, file={}", chunk_id); chunk.as_mut().seek(std::io::SeekFrom::Start(0)).await?; @@ -883,18 +1104,31 @@ mod test_local_chunk_cache { let mut buf = Vec::with_capacity(chunk_id.len()); let len = reader.read_to_end(&mut buf).await.map_err(|e| { - let msg = format!("read chunk to buffer failed! chunk={}, len={}, {}", chunk_id, chunk_id.len(), e); + let msg = format!( + "read chunk to buffer failed! chunk={}, len={}, {}", + chunk_id, + chunk_id.len(), + e + ); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::IoError, msg) })?; if len != chunk_id.len() { - let msg = format!("read chunk to buffer but got unmatch len! chunk={}, len={}, read={}", chunk_id, chunk_id.len(), len); + let msg = format!( + "read chunk to buffer but got unmatch len! chunk={}, len={}, read={}", + chunk_id, + chunk_id.len(), + len + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::IoError, msg)); } - self.chunk_map.lock().unwrap().insert(chunk_id.clone(), Box::new(ChunkMock{buf})); + self.chunk_map + .lock() + .unwrap() + .insert(chunk_id.clone(), Box::new(ChunkMock { buf })); Ok(()) } @@ -902,12 +1136,16 @@ mod test_local_chunk_cache { todo!() } - async fn get_chunk_meta(&self, _chunk_id: &ChunkId, _chunk_type: ChunkType) -> BuckyResult { + async fn get_chunk_meta( + &self, + _chunk_id: &ChunkId, + _chunk_type: ChunkType, + ) -> BuckyResult { todo!() } } pub struct ChunkMock { - buf: Vec + buf: Vec, } #[async_trait::async_trait] @@ -970,22 +1208,35 @@ mod test_local_chunk_cache { #[test] fn test_alloc() { async_std::task::block_on(async move { - let cache = LocalChunkCache::::new("", TestDiskScanner).await.unwrap(); + let cache = LocalChunkCache::::new("", TestDiskScanner) + .await + .unwrap(); let mut chunk_list = Vec::new(); for i in 0..1000000u32 { let random_id = RandomId::new_id(); - let chunk_id = ChunkId::new(&random_id, 8192*1024); + let chunk_id = ChunkId::new(&random_id, 8192 * 1024); chunk_list.push(chunk_id.clone()); - cache.put_chunk(&chunk_id, &mut ChunkMock{buf: i.to_be_bytes().to_vec()}).await.unwrap(); - let chunk = cache.get_chunk(&chunk_id, ChunkType::MemChunk).await.unwrap(); + cache + .put_chunk( + &chunk_id, + &mut ChunkMock { + buf: i.to_be_bytes().to_vec(), + }, + ) + .await + .unwrap(); + let chunk = cache + .get_chunk(&chunk_id, ChunkType::MemChunk) + .await + .unwrap(); let mut reader = ChunkRead::new(chunk); - let mut buf = [0u8;4]; + let mut buf = [0u8; 4]; let len = reader.read(&mut buf).await.unwrap(); assert_eq!(len, 4); let tmp = u32::from_be_bytes(buf); assert_eq!(u32::from_be_bytes(buf), i); - let chunk = Box::new(ChunkMock{buf: Vec::new()}); + let chunk = Box::new(ChunkMock { buf: Vec::new() }); let mut write = ChunkWrite::new(chunk); let len = write.write(&buf).await.unwrap(); assert_eq!(len, 4); @@ -993,7 +1244,11 @@ mod test_local_chunk_cache { { let list = cache.disk_cache_list.read().unwrap(); for (item, weight) in list.iter() { - println!("weight {} count {}", *weight, item.chunk_map.lock().unwrap().len()); + println!( + "weight {} count {}", + *weight, + item.chunk_map.lock().unwrap().len() + ); } } diff --git a/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs b/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs index 377315077..015083804 100644 --- a/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs +++ b/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs @@ -350,8 +350,8 @@ impl PublishLocalDirTask { .join(sub_path.strip_prefix("/").unwrap()) .join(file_name); log::info!( - "publish file {}", - file_path.to_string_lossy().to_string() + "publish file {}, {}", + file_path.to_string_lossy().to_string(), object_id, ); file_recorder .record_file_chunk_list(file_path.as_path(), &file, self.chunk_method) From df7015a33e9eddc20ed4c4c82434978aae669995 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 3 Mar 2023 15:15:58 +0800 Subject: [PATCH 189/553] Improve congtent-based mime sniffing mechanism in cyfs-runtime --- src/service/cyfs-runtime/src/mime.rs | 48 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/service/cyfs-runtime/src/mime.rs b/src/service/cyfs-runtime/src/mime.rs index d6e7a5653..35af7139c 100644 --- a/src/service/cyfs-runtime/src/mime.rs +++ b/src/service/cyfs-runtime/src/mime.rs @@ -4,6 +4,8 @@ use http_types::{mime, Mime, Url}; use mime_sniffer::{HttpRequest, MimeTypeSniffer}; use std::borrow::Cow; use std::str::FromStr; +use async_std::io::BufRead as AsyncBufRead; +use async_std::prelude::*; pub(crate) struct MimeHelper; @@ -77,29 +79,20 @@ impl MimeHelper { // 根据内容猜测 // read some content and try sniff the mime - use async_std::io::ReadExt; let body_len = resp.len(); if body_len == Some(0) { return; } - let mut body = resp.take_body().into_reader(); - let mut content: Vec = vec![0; 512]; - let read_content_len; - match body.read(&mut content).await { - Ok(bytes) => { - if bytes == 0 { - warn!("sniff mime read resp body but got empty! url={}", url); - return; - } + let body = resp.take_body().into_reader(); + let mut body = body.take(512); - read_content_len = bytes; - } - Err(e) => { - error!("sniff read resp body but error! url={}, {}", url, e); - resp.set_body(http_types::Body::from_reader(body, body_len)); - return; - } + let mut content: Vec = Vec::with_capacity(512); + if let Err(e) = body.read_to_end(&mut content).await { + error!("sniff read resp body but error! url={}, {}", url, e); + let new_body = Self::merge_body(body_len, content, body.into_inner()); + resp.set_body(new_body); + return; } let str_url = url.to_string(); @@ -155,7 +148,21 @@ impl MimeHelper { } } - let new_body = http_types::Body::from_bytes(content[..read_content_len].to_vec()); + let new_body = Self::merge_body(body_len, content, body.into_inner()); + resp.set_body(new_body); + } + + fn merge_body( + body_len: Option, + content: Vec, + body_reader: Box, + ) -> http_types::Body { + if content.len() == 0 { + return http_types::Body::from_reader(body_reader, body_len); + } + + let read_content_len = content.len(); + let new_body = http_types::Body::from_bytes(content); let tail_len = match body_len { Some(len) => { @@ -172,8 +179,7 @@ impl MimeHelper { None => None, }; - let tail_body = http_types::Body::from_reader(body, tail_len); - let new_body = new_body.chain(tail_body); - resp.set_body(new_body); + let tail_body = http_types::Body::from_reader(body_reader, tail_len); + new_body.chain(tail_body) } } From 846e8700377278f8d525929018af7e4b2ca57bd3 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Fri, 3 Mar 2023 20:06:22 +0800 Subject: [PATCH 190/553] Fix: sn client stop ping after second try --- src/component/cyfs-bdt/src/sn/client/ping/client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-bdt/src/sn/client/ping/client.rs b/src/component/cyfs-bdt/src/sn/client/ping/client.rs index 06dc15952..a23a14249 100644 --- a/src/component/cyfs-bdt/src/sn/client/ping/client.rs +++ b/src/component/cyfs-bdt/src/sn/client/ping/client.rs @@ -502,7 +502,8 @@ impl PingClient { stack.keystore().reset_peer(&self.sn()); let session = session.reset(None, None); info!("{} start second try", self); - *active = ActiveState::SecondTry(session); + *active = ActiveState::SecondTry(session.clone_as_ping_session()); + next.to_start = Some(session); }, ActiveState::SecondTry(_) => { next.waiter = Some(waiter.transfer()); From 9d7cf7238b12cfd3a7f7f3ae53e6d65e74db4088 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Fri, 3 Mar 2023 20:17:21 +0800 Subject: [PATCH 191/553] Fix: sn client stop ping after second try --- src/component/cyfs-bdt/src/sn/client/ping/client.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/component/cyfs-bdt/src/sn/client/ping/client.rs b/src/component/cyfs-bdt/src/sn/client/ping/client.rs index a23a14249..d13e770b0 100644 --- a/src/component/cyfs-bdt/src/sn/client/ping/client.rs +++ b/src/component/cyfs-bdt/src/sn/client/ping/client.rs @@ -415,6 +415,7 @@ impl PingClient { struct NextStep { waiter: Option, update: Option<(Endpoint, Endpoint)>, + to_start: Option>, ping_once: bool, update_cache: Option> } @@ -424,6 +425,7 @@ impl PingClient { Self { waiter: None, update: None, + to_start: None, ping_once: false, update_cache: None } @@ -531,6 +533,13 @@ impl PingClient { } } + if let Some(session) = next.to_start { + let client = self.clone(); + task::spawn(async move { + client.sync_session_resp(session.as_ref(), session.wait().await); + }); + } + if let Some(waiter) = next.waiter { waiter.wake(); } From 710b8f581e87e3e102c1f520f7a2e6ea8256df6b Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 15:38:38 +0800 Subject: [PATCH 192/553] Add continuous service publish --- scripts/pack.js | 76 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index d59ef46d2..c5f54d0dc 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -3,10 +3,9 @@ const child_process = require('child_process'); const targets = process.argv[2].split(";") const type = process.argv[3].split(";") const { apps, services } = require('./build_config') -const path = require('path') +const path = require('path'); +const assert = require('assert'); -const onlyput = process.argv[4] || "put" -const action = process.argv[5] || "put" const buildnumber = process.argv[6] || "0" const channel = process.argv[7] || "nightly" @@ -14,6 +13,41 @@ if (!fs.existsSync('Cargo.toml')) { console.error('cannot find Cargo.toml in cwd! check working dir') } +const PublishStep = { + Pack: 1, + Upload: 2, + SetVersion: 3, + Finish: 4 +} + +const step_file_name = "curstep" + +let processing = {}; +if (fs.existsSync(step_file_name)) { + processing = JSON.parse(fs.readFileSync(processing_name)) +} + +function set_step(service_name, step, arg) { + processing[service_name] = {step: step, arg: arg}; + fs.writeFileSync(step_file_name, JSON.stringify(processing)) +} + +function get_step_arg(service_name, step) { + if (processing[service_name].step === step) { + return processing[service_name].arg; + } + + return undefined; +} + +function need_step(service_name, step) { + let old_info = processing[service_name]; + if (!old_info) { + return true + } + + return old_info.step < step +} const protocols = { 'http:': require('http'), @@ -138,10 +172,12 @@ async function run() { console.error(`service ${service.name} has no id!`); process.exit(1); } + if (!service.pub) { continue } - if (onlyput !== "onlyput") { + + if (need_step(service.name, PublishStep.Pack)) { for (const target of targets) { if (service.exclude && service.exclude.includes(target)) { continue @@ -149,31 +185,40 @@ async function run() { if (service.include && !service.include.includes(target)) { continue } - + let config_path = service.config_file[target] || service.config_file.default fs.copyFileSync(`service/${service.name}/${config_path}`, `dist/services/${service.name}/${target}/package.cfg`) - + if (service.assets && service.assets[target]) { for (const asset of service.assets[target]) { fs.copyFileSync(asset.from, `dist/services/${service.name}/${target}/${asset.to}`) } } - + child_process.execSync(`bash -c "./pack-tools -d services/${service.name}/${target}"`, { cwd: 'dist', stdio: 'inherit' }) fs.rmSync(`dist/services/${service.name}/${target}`, {recursive: true, force: true}); } + set_step(service.name, PublishStep.Pack) } - child_process.execSync(`cyfs-client ${action} services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) - - let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) + if (need_step(service.name, PublishStep.Upload)) { + child_process.execSync(`cyfs-client put services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) + let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) + set_step(service.name, PublishStep.Upload, fid) + } - // 运行app-tool,添加版本和fid - let app_version = version + "-preview"; - let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; - console.log("will run app tool cmd:", cmd) - child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) + if (need_step(service.name, PublishStep.SetVersion)) { + // 运行app-tool,添加版本和fid + let fid = get_step_arg(service.name, PublishStep.Upload); + let app_version = version + "-preview"; + let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; + console.log("will run app tool cmd:", cmd) + child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) + set_step(service.name, PublishStep.SetVersion, version) + } + let version = get_step_arg(service.name, PublishStep.SetVersion) + assert(!!version) device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) } @@ -184,6 +229,7 @@ async function run() { } run().then(() => { + try {fs.removeSync(step_file_name)} catch(e) {} process.exit(0) }) From 3a5572adeda01a98c701e38fc0aa7bd47770e915 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 15:40:02 +0800 Subject: [PATCH 193/553] Remove unused publish script params --- scripts/pack.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index c5f54d0dc..3729ffd82 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -6,8 +6,8 @@ const { apps, services } = require('./build_config') const path = require('path'); const assert = require('assert'); -const buildnumber = process.argv[6] || "0" -const channel = process.argv[7] || "nightly" +const buildnumber = process.argv[4] || "0" +const channel = process.argv[5] || "nightly" if (!fs.existsSync('Cargo.toml')) { console.error('cannot find Cargo.toml in cwd! check working dir') @@ -209,7 +209,7 @@ async function run() { if (need_step(service.name, PublishStep.SetVersion)) { // 运行app-tool,添加版本和fid - let fid = get_step_arg(service.name, PublishStep.Upload); + let fid = get_step_arg(service.name, PublishStep.Upload) let app_version = version + "-preview"; let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; console.log("will run app tool cmd:", cmd) From c86f8464cc01111d4cb8be40825f991ce370e72a Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 16:55:52 +0800 Subject: [PATCH 194/553] Remove curstep file when publish finish --- scripts/pack.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index 3729ffd82..eb9f8d32a 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -217,9 +217,9 @@ async function run() { set_step(service.name, PublishStep.SetVersion, version) } - let version = get_step_arg(service.name, PublishStep.SetVersion) - assert(!!version) - device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) + let service_version = get_step_arg(service.name, PublishStep.SetVersion) + assert(!!service_version) + device_config.push({ "id": service.id, "ver": `${service_version}`, "status": 1 }) } fs.writeFileSync('dist/device-config.cfg', JSON.stringify(device_config)) @@ -229,7 +229,7 @@ async function run() { } run().then(() => { - try {fs.removeSync(step_file_name)} catch(e) {} + fs.rmSync(step_file_name, {force: true, maxRetries: 3}) process.exit(0) }) From 6933484881412f8a76a0580a5d59c55e8302098b Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 17:14:47 +0800 Subject: [PATCH 195/553] Bump and publish cargo packages --- cargo_pub_rev | 2 +- src/component/cyfs-base/Cargo.toml | 2 +- src/component/cyfs-bdt/Cargo.toml | 4 ++-- src/component/cyfs-core/Cargo.toml | 6 ++---- src/component/cyfs-debug/Cargo.toml | 2 +- src/component/cyfs-lib/Cargo.toml | 2 +- src/component/cyfs-meta-lib/Cargo.toml | 4 ++-- src/component/cyfs-perf/cyfs-perf-base/Cargo.toml | 4 ++-- src/component/cyfs-perf/cyfs-perf-client/Cargo.toml | 6 +++--- src/component/cyfs-task-manager/Cargo.toml | 2 +- src/component/cyfs-util/Cargo.toml | 2 +- 11 files changed, 17 insertions(+), 19 deletions(-) diff --git a/cargo_pub_rev b/cargo_pub_rev index f4faa68c7..e724f4d9f 100644 --- a/cargo_pub_rev +++ b/cargo_pub_rev @@ -1 +1 @@ -95a5c99d \ No newline at end of file +27b2f448 \ No newline at end of file diff --git a/src/component/cyfs-base/Cargo.toml b/src/component/cyfs-base/Cargo.toml index 9ce32803e..9c0dc81fe 100644 --- a/src/component/cyfs-base/Cargo.toml +++ b/src/component/cyfs-base/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-base' -version = '0.6.9' +version = '0.6.10' authors = ['liuzhicong '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-bdt/Cargo.toml b/src/component/cyfs-bdt/Cargo.toml index dcf843d0a..4c2ef1679 100644 --- a/src/component/cyfs-bdt/Cargo.toml +++ b/src/component/cyfs-bdt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-bdt' -version = '0.7.0' +version = '0.7.1' authors = ['liuzhicong '] edition = '2021' license = 'BSD-2-Clause' @@ -40,4 +40,4 @@ serde = { version = '1.0', features = ['derive'] } nix = '0.24' [dev-dependencies] -local-ip-address = '0.5.1' \ No newline at end of file +local-ip-address = '0.5.1' diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index d478a8d58..e075f74dd 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-core' -version = '0.6.5' +version = '0.6.6' authors = ['weiqiushi '] edition = '2021' license = 'BSD-2-Clause' @@ -29,6 +29,4 @@ once_cell = '1.12' hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } -sha2 = { version = '0.8' } -generic-array = { version = '0.12', default-features = false, features = ['serde'] } -semver = "1.0" +semver = '1.0' diff --git a/src/component/cyfs-debug/Cargo.toml b/src/component/cyfs-debug/Cargo.toml index 50e071920..f64231710 100644 --- a/src/component/cyfs-debug/Cargo.toml +++ b/src/component/cyfs-debug/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-debug' -version = '0.6.3' +version = '0.6.4' authors = ['liyaxing '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-lib/Cargo.toml b/src/component/cyfs-lib/Cargo.toml index c64a19e1b..6784d2a15 100644 --- a/src/component/cyfs-lib/Cargo.toml +++ b/src/component/cyfs-lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-lib' -version = '0.8.0' +version = '0.8.1' authors = ['liyaxing '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-meta-lib/Cargo.toml b/src/component/cyfs-meta-lib/Cargo.toml index d19e44fbe..32a83ac3e 100644 --- a/src/component/cyfs-meta-lib/Cargo.toml +++ b/src/component/cyfs-meta-lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-meta-lib' -version = '0.6.2' +version = '0.6.3' authors = ['weiqiushi '] edition = '2021' license = 'BSD-2-Clause' @@ -18,4 +18,4 @@ log = '0.4' serde_json = '1.0' rand = '0.7.3' primitive-types = { version = '0.9' } -lru_time_cache = "0.11" +lru_time_cache = '0.11' diff --git a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml index 9ff1ed0a6..a555d2e70 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-perf-base' -version = '0.6.2' +version = '0.6.3' authors = ['wangzhi '] edition = '2021' license = 'BSD-2-Clause' @@ -21,7 +21,7 @@ int-enum = '0.4' protobuf = { version = '2', features = ['with-bytes'] } serde = { version = '1.0', features = ['derive'] } serde_json = '1.0' -lazy_static = "1.4" +lazy_static = '1.4' [dev-dependencies] async-std = { version = '1.11', features = ['attributes'] } diff --git a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml index f9c167319..c85719330 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml @@ -1,14 +1,14 @@ [package] name = 'cyfs-perf-client' -version = '0.6.1' +version = '0.6.2' authors = ['wangzhi '] edition = '2021' license = 'BSD-2-Clause' description = 'Rust cyfs-perf-client package' [dependencies] -log = { version = '0.4'} +log = { version = '0.4' } serde_json = '1.0' int-enum = '0.4' cyfs-perf-base = { path = '../cyfs-perf-base', version = '0.6' } @@ -22,7 +22,7 @@ async-std = { version = '1.11', features = ['unstable', 'attributes'] } rand = '0.7' sha2 = '0.8' async-trait = '0.1.53' -chrono = "0.4" +chrono = '0.4' [target.'cfg(target_os = "android")'.dependencies] jni = '0.19' diff --git a/src/component/cyfs-task-manager/Cargo.toml b/src/component/cyfs-task-manager/Cargo.toml index c79bcb320..0b9f005d1 100644 --- a/src/component/cyfs-task-manager/Cargo.toml +++ b/src/component/cyfs-task-manager/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-task-manager' -version = '0.6.2' +version = '0.6.3' edition = '2021' license = 'BSD-2-Clause' description = 'Rust cyfs-task-manager package' diff --git a/src/component/cyfs-util/Cargo.toml b/src/component/cyfs-util/Cargo.toml index 313201623..3b2cf72a8 100644 --- a/src/component/cyfs-util/Cargo.toml +++ b/src/component/cyfs-util/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-util' -version = '0.6.5' +version = '0.6.6' authors = ['weiqiushi '] edition = '2021' license = 'BSD-2-Clause' From 2ee2202d132e5d7707e25b99ddc5cb5783d473c9 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 17:29:59 +0800 Subject: [PATCH 196/553] AppManager support install web-packed DecApp --- src/service/app-manager/src/package.rs | 42 ++++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/service/app-manager/src/package.rs b/src/service/app-manager/src/package.rs index d6537a206..4e4028294 100644 --- a/src/service/app-manager/src/package.rs +++ b/src/service/app-manager/src/package.rs @@ -51,8 +51,8 @@ impl AppPackage { let service_path = target_path.join("service"); // 下载service文件,/cyfs/tmp/app/{appid}/service.dl let service_pkg_path = target_path.join("service").with_extension("dl"); - let service_file_num = Self::download_service(dir, owner, client, &service_pkg_path).await?; - if service_file_num > 0 { + let service_exists = Self::download_service(dir, owner, client, &service_pkg_path).await?; + if service_exists { // 解压service zip文件到tmp目录,/cyfs/tmp/app/{appid}/service info!("extract app service {} to {}", service_pkg_path.display(), service_path.display()); Self::extract(&service_pkg_path, &service_path)?; @@ -89,24 +89,34 @@ impl AppPackage { Ok(()) } - pub async fn download_acl(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { - Self::download_files(dir, owner, client, "acl", target_path).await + pub async fn download_acl(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + Self::download_files(dir, owner, client, "acl", target_path).await.map(|size|size > 0) } - pub async fn download_service(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + pub async fn download_service(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { let system_config = get_system_config(); let target = system_config.target.clone(); //拼app service的inner_path,当前为"service/{target}.zip" let service_inner_path = format!("service/{}.zip", &target); - Self::download_files(dir, owner, client, &service_inner_path, target_path).await + Self::download_files(dir, owner, client, &service_inner_path, target_path).await.map(|size|size > 0) } - pub async fn download_web(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { - Self::download_files(dir, owner, client, "web", target_path).await + pub async fn download_web(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + // 先尝试下载web.zip文件 + let web_zip_tmp_path = get_temp_path().join(format!("{}-web.zip", dir)); + if Self::download_files(dir, owner, client, "web.zip", &web_zip_tmp_path).await? == 1 { + // 如果有,这里解压 + info!("extract app web {} to {}", web_zip_tmp_path.display(), target_path.display()); + Self::extract(&web_zip_tmp_path, &target_path)?; + Ok(true) + } else { + Self::download_files(dir, owner, client, "web", target_path).await.map(|size|size > 0) + } + } - pub async fn download_dep(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { - Self::download_files(dir, owner, client, "dependent", target_path).await + pub async fn download_dep(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + Self::download_files(dir, owner, client, "dependent", target_path).await.map(|size|size > 0) } // 下载一个文件夹 @@ -128,22 +138,14 @@ impl AppPackage { pub fn extract(pkg_path: &Path, target_folder: &Path) -> BuckyResult<()> { if target_folder.is_dir() { fs::remove_dir_all(target_folder).map_err(|e| { - error!( - "remove target_folder failed! path={}, err={}", - target_folder.display(), - e - ); + error!("remove target_folder failed! path={}, err={}", target_folder.display(), e); e })?; info!("remove exists target_folder success! dir={}", target_folder.display()); } fs::create_dir_all(target_folder).map_err(|e| { - error!( - "create target_folder failed! path={}, err={}", - target_folder.display(), - e - ); + error!("create target_folder failed! path={}, err={}", target_folder.display(), e); e })?; From eaf4e73821b848b59a70eae12aceaf72f993ee09 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 18:28:02 +0800 Subject: [PATCH 197/553] Update Cargo.lock --- src/Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 0649e040a..aa257e2fa 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1517,7 +1517,7 @@ dependencies = [ [[package]] name = "cyfs-base" -version = "0.6.9" +version = "0.6.10" dependencies = [ "aes 0.7.5", "async-recursion", @@ -1588,7 +1588,7 @@ dependencies = [ [[package]] name = "cyfs-bdt" -version = "0.7.0" +version = "0.7.1" dependencies = [ "async-std", "async-trait", @@ -1802,7 +1802,7 @@ dependencies = [ [[package]] name = "cyfs-core" -version = "0.6.5" +version = "0.6.6" dependencies = [ "async-std", "async-trait", @@ -1829,7 +1829,7 @@ dependencies = [ [[package]] name = "cyfs-debug" -version = "0.6.3" +version = "0.6.4" dependencies = [ "async-h1", "async-std", @@ -1935,7 +1935,7 @@ dependencies = [ [[package]] name = "cyfs-lib" -version = "0.8.0" +version = "0.8.1" dependencies = [ "async-h1", "async-std", @@ -2036,7 +2036,7 @@ dependencies = [ [[package]] name = "cyfs-meta-lib" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -2171,7 +2171,7 @@ dependencies = [ [[package]] name = "cyfs-perf-base" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -2190,7 +2190,7 @@ dependencies = [ [[package]] name = "cyfs-perf-client" -version = "0.6.1" +version = "0.6.2" dependencies = [ "android_logger", "async-std", @@ -2397,7 +2397,7 @@ dependencies = [ [[package]] name = "cyfs-task-manager" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "async-trait", @@ -2426,7 +2426,7 @@ dependencies = [ [[package]] name = "cyfs-util" -version = "0.6.5" +version = "0.6.6" dependencies = [ "async-h1", "async-std", From f78249e65c66dabb34cdcdefe781489e79294560 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 19:53:36 +0800 Subject: [PATCH 198/553] Fix service pub script --- scripts/pack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pack.js b/scripts/pack.js index eb9f8d32a..ab45fa21a 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -24,7 +24,7 @@ const step_file_name = "curstep" let processing = {}; if (fs.existsSync(step_file_name)) { - processing = JSON.parse(fs.readFileSync(processing_name)) + processing = JSON.parse(fs.readFileSync(step_file_name)) } function set_step(service_name, step, arg) { From 1c1cb340a692dec802cd35a1cd1bd9947b29d5ef Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 20:06:36 +0800 Subject: [PATCH 199/553] Fix continuous script error --- scripts/build.js | 17 ++--------------- scripts/build_config.js | 3 ++- scripts/pack.js | 12 +++++------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index d2947a592..77205e6b5 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,7 +1,6 @@ const fs = require('fs') const build_util = require('./build_util') const build_config = require('./build_config') -const child_process = require('child_process'); // build_util.reflesh_cargo(); @@ -18,25 +17,13 @@ if (!fs.existsSync('Cargo.toml')) { console.error('cannot find Cargo.toml in cwd! check working dir') } -function prepare_bash(base_path, dirs) { - child_process.execSync(`bash -c "rm -rf ${base_path}"`); - child_process.execSync(`bash -c "mkdir ${base_path} -p"`); - for (const dir of dirs) { - child_process.execSync(`bash -c "cp -r -f ${dir} ${base_path}/"`); - } -} - function build(catalogy, need_pack, need_bin) { - try{fs.rmSync(`dist/${catalogy}`, {recursive: true, force: true})}catch(error){} + fs.rmSync(build_config.step_file, {force: true, maxRetries: 3}) + fs.rmSync(`dist/${catalogy}`, {recursive: true, force: true}) if (build_config[catalogy] === undefined) { console.error(`build catalogy ${catalogy} not exists in config`) return } - /* - if (process.argv[2].includes("unknown-linux")) { - // 这里拷贝rust_src下的必要文件到bash的文件夹下 - prepare_bash("~/workspace/ffs", ["3rd", "component", "service", "tests", "tools", "Cargo.toml", "Cargo.lock"]) - }*/ for (const prog of build_config[catalogy]) { for (const target of targets) { diff --git a/scripts/build_config.js b/scripts/build_config.js index 0dbe25639..a2f38c228 100644 --- a/scripts/build_config.js +++ b/scripts/build_config.js @@ -146,5 +146,6 @@ module.exports = { sdk, installer, metas, - misc + misc, + step_file: "curstep" } \ No newline at end of file diff --git a/scripts/pack.js b/scripts/pack.js index ab45fa21a..3e797e7b8 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -2,7 +2,7 @@ const fs = require('fs') const child_process = require('child_process'); const targets = process.argv[2].split(";") const type = process.argv[3].split(";") -const { apps, services } = require('./build_config') +const { apps, services, step_file } = require('./build_config') const path = require('path'); const assert = require('assert'); @@ -20,16 +20,14 @@ const PublishStep = { Finish: 4 } -const step_file_name = "curstep" - let processing = {}; -if (fs.existsSync(step_file_name)) { - processing = JSON.parse(fs.readFileSync(step_file_name)) +if (fs.existsSync(step_file)) { + processing = JSON.parse(fs.readFileSync(step_file)) } function set_step(service_name, step, arg) { processing[service_name] = {step: step, arg: arg}; - fs.writeFileSync(step_file_name, JSON.stringify(processing)) + fs.writeFileSync(step_file, JSON.stringify(processing)) } function get_step_arg(service_name, step) { @@ -229,7 +227,7 @@ async function run() { } run().then(() => { - fs.rmSync(step_file_name, {force: true, maxRetries: 3}) + fs.rmSync(step_file, {force: true, maxRetries: 3}) process.exit(0) }) From 32811226f030291cf6b3ab3af70c80ae45a06cb8 Mon Sep 17 00:00:00 2001 From: liqirun Date: Tue, 7 Mar 2023 20:46:35 +0800 Subject: [PATCH 200/553] bdt debuger tool support new SN/NDN api and multi streams test --- src/Cargo.lock | 1 + src/component/cyfs-bdt/src/debug/command.rs | 21 +- src/component/cyfs-bdt/src/debug/stub.rs | 392 +++++++++++++------- src/component/cyfs-bdt/src/stack.rs | 2 +- src/tools/bdt-debuger-deamon/Cargo.toml | 1 + src/tools/bdt-debuger-deamon/src/main.rs | 143 +++++-- 6 files changed, 376 insertions(+), 184 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index aa257e2fa..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -645,6 +645,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-debug", + "cyfs-util", "log 0.4.17", "md5", ] diff --git a/src/component/cyfs-bdt/src/debug/command.rs b/src/component/cyfs-bdt/src/debug/command.rs index 3594fb662..8efecd612 100644 --- a/src/component/cyfs-bdt/src/debug/command.rs +++ b/src/component/cyfs-bdt/src/debug/command.rs @@ -31,12 +31,14 @@ pub fn debug_command_line() -> clap::App<'static, 'static> { .subcommand(SubCommand::with_name("nc") .arg(Arg::with_name("remote").required(true)) .arg(Arg::with_name("port").required(true)) + .arg(Arg::with_name("bench").required(false)) + .arg(Arg::with_name("task").required(false)) ) .subcommand(SubCommand::with_name("get_chunk") .arg(Arg::with_name("remotes").required(true)) .arg(Arg::with_name("timeout").required(true)) .arg(Arg::with_name("chunk_id").required(true)) - .arg(Arg::with_name("local_path").required(true)) + .arg(Arg::with_name("local_path").required(false)) ) .subcommand(SubCommand::with_name("get_file") .arg(Arg::with_name("remotes").required(true)) @@ -100,10 +102,14 @@ impl DebugCommand { let remote = remote_device(stack, subcommand.value_of("remote").unwrap()).await .map_err(|err| format!("load remote desc {} failed for {}\r\n", subcommand.value_of("remote").unwrap(), err))?; let port = u16::from_str(subcommand.value_of("port").unwrap()).unwrap(); + let bench = u32::from_str(subcommand.value_of("bench").unwrap_or("0")).unwrap(); + let task_num = u32::from_str(subcommand.value_of("task").unwrap_or("1")).unwrap(); Ok(Self::Nc(DebugCommandNc { remote, port, - timeout: Duration::from_secs(8) + timeout: Duration::from_secs(8), + bench, + task_num, })) }, "get_chunk" => { @@ -114,12 +120,12 @@ impl DebugCommand { for remote_file in remotes_split { let remote = remote_device(stack, remote_file).await .map_err(|err| format!("load remote desc {} failed for {}\r\n", subcommand.value_of("remote").unwrap(), err))?; - remotes.push(remote.desc().device_id()); + remotes.push(remote.desc().clone()); } let chunk_id_str = String::from_str(subcommand.value_of("chunk_id").unwrap()).unwrap(); let chunk_id = ChunkId::from_str(&chunk_id_str.as_str()).map_err(|err| format!("load chunk_id {} fail: {}\r\n", chunk_id_str, err))?; - let local_path_str = String::from_str(subcommand.value_of("local_path").unwrap()).unwrap(); + let local_path_str = String::from_str(subcommand.value_of("local_path").unwrap_or("default")).unwrap(); let local_path = PathBuf::from_str(&local_path_str.as_str()).unwrap(); let timeout = u32::from_str(subcommand.value_of("timeout").unwrap()).unwrap(); @@ -214,14 +220,17 @@ pub struct DebugCommandPing { pub timeout: Duration } +#[derive(Clone, Debug)] pub struct DebugCommandNc { pub remote: Device, pub port: u16, - pub timeout: Duration + pub timeout: Duration, + pub bench: u32, + pub task_num: u32, } pub struct DebugCommandGetChunk { - pub remotes: Vec, + pub remotes: Vec, pub timeout: u32, pub chunk_id: ChunkId, pub local_path: PathBuf, diff --git a/src/component/cyfs-bdt/src/debug/stub.rs b/src/component/cyfs-bdt/src/debug/stub.rs index 8c7289566..0f4aa5c07 100644 --- a/src/component/cyfs-bdt/src/debug/stub.rs +++ b/src/component/cyfs-bdt/src/debug/stub.rs @@ -21,36 +21,39 @@ use crate::{ datagram::{self, DatagramOptions}, types::*, ndn::*, - utils::* + utils::*, }; use super::command::*; -// use super::super::sn::client::SnStatus; +use super::super::sn::client::SnStatus; struct DebugStubImpl { stack: WeakStack, listener: TcpListener, + chunk_store: MemChunkStore, } #[derive(Clone)] pub struct Config { pub local: String, - pub port: u16 + pub port: u16, + pub chunk_store: MemChunkStore, } #[derive(Clone)] pub struct DebugStub(Arc); impl DebugStub { - pub async fn open(weak_stack: WeakStack) -> BuckyResult { + pub async fn open(weak_stack: WeakStack, chunk_store: MemChunkStore) -> BuckyResult { let stack = Stack::from(&weak_stack); let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::from_str(stack.config().debug.as_ref().unwrap().local.as_str()).unwrap()), stack.config().debug.as_ref().unwrap().port); let listener = TcpListener::bind(addr).await?; Ok(Self(Arc::new(DebugStubImpl { stack: weak_stack, - listener + listener, + chunk_store, }))) - } + } pub fn listen(&self) { const READ_CMD_TIMEOUT: u64 = 30; @@ -138,38 +141,40 @@ impl DebugStub { Ok(()) } - async fn sn_conn_status(&self, _tunnel: TcpStream, _command: DebugCommandSnConnStatus) -> Result<(), String> { - // let mut tunnel = tunnel; + async fn sn_conn_status(&self, tunnel: TcpStream, command: DebugCommandSnConnStatus) -> Result<(), String> { + let mut tunnel = tunnel; - // let stack = Stack::from(&self.0.stack); - // let timeout = { - // if command.timeout_sec == 0 { - // 6 - // } else { - // command.timeout_sec - // } - // }; + let stack = Stack::from(&self.0.stack); + let timeout = { + if command.timeout_sec == 0 { + 6 + } else { + command.timeout_sec + } + }; - // let sleep_ms = 200; - // let mut counter = timeout*(1000/sleep_ms); - // loop { - // let sn_status = stack.sn_client().ping().status(); + let sleep_ms = 200; + let mut counter = timeout*(1000/sleep_ms); + loop { + let sn_status = stack.sn_client().ping().status(); - // if let SnStatus::Online = sn_status { - // let _ = tunnel.write_all("Ok: sn connected\r\n".as_ref()).await; + if let Some(sn_status) = sn_status { + if let SnStatus::Online = sn_status { + let _ = tunnel.write_all("Ok: sn connected\r\n".as_ref()).await; - // return Ok(()) - // } + return Ok(()) + } + } - // counter -= 1; - // if counter == 0 { - // break ; - // } + counter -= 1; + if counter == 0 { + break ; + } - // task::sleep(Duration::from_millis(sleep_ms)).await; - // } + task::sleep(Duration::from_millis(sleep_ms)).await; + } - // let _ = tunnel.write_all("Err: sn connect timeout\r\n".as_ref()).await; + let _ = tunnel.write_all("Err: sn connect timeout\r\n".as_ref()).await; Ok(()) } @@ -283,93 +288,85 @@ impl DebugStub { } async fn nc(&self, tunnel: TcpStream, command: DebugCommandNc) -> Result<(), String> { - let mut tunnel = tunnel; let stack = Stack::from(&self.0.stack); - let _ = tunnel.write_all("connecting stream\r\n".as_ref()).await; - - let question = b"question?"; - let mut conn = stack.stream_manager().connect( - command.port, - question.to_vec(), - BuildTunnelParams { - remote_const: command.remote.desc().clone(), - remote_sn: None, - remote_desc: Some(command.remote.clone()) - }).await.map_err(|err| format!("Err: {}\r\n", err.msg().to_string()))?; - - let _ = tunnel.write_all("Connect success, read answer\r\n".as_ref()).await; - - let mut answer = [0; 128]; - match conn.read(&mut answer).await { - Ok(len) => { - let s = format!("Read answer success, len={} content={:?}\r\n", - len, String::from_utf8(answer[..len].to_vec()).expect("")); - let _ = tunnel.write_all(s.as_bytes()).await; - }, - Err(e) => { - let s = format!("Read answer fail, err={}\r\n", e); - let _ = tunnel.write_all(s.as_bytes()).await; - return Ok(()); - } + let task_num = if command.task_num == 0 { + 1 + } else { + command.task_num + }; + let mut tasks = vec![]; + + for task_id in 0..task_num { + let mut t = tunnel.clone(); + let c = command.clone(); + let s = stack.clone(); + tasks.push(task::spawn(async move { + match nc_task(t.clone(), c, s, task_id).await { + Err(e) => { + let _ = t.write_all(format!("nc_task err={}\r\n", e).as_ref()).await; + }, + Ok(_) => { + } + } + })); } - let _ = conn.write_all(b"hello world.").await; - - let mut buf = [0u8; 128]; - match conn.read(&mut buf).await { - Ok(len) => { - let s = format!("Read data success, len={} content={:?}\r\n", - len, String::from_utf8(buf[..len].to_vec()).expect("")); - let _ = tunnel.write_all(s.as_bytes()).await; - }, - Err(e) => { - let s = format!("Read data fail, err={}\r\n", e); - let _ = tunnel.write_all(s.as_bytes()).await; - return Ok(()); - } + for t in tasks { + let _ = t.await; } - let _ = tunnel.write_all("Ok: stream connected\r\n".as_ref()).await; - - let _ = conn.shutdown(Shutdown::Both); - Ok(()) } async fn get_chunk(&self, tunnel: TcpStream, command: DebugCommandGetChunk) -> Result<(), String> { let mut tunnel = tunnel; - + let chunk_id = command.chunk_id; let remotes = command.remotes; - let timeout = command.timeout; - let local_path = command.local_path; + //let local_path = command.local_path; - let _ = tunnel.write_all("start downloading chunk..\r\n".as_ref()).await; let stack = Stack::from(&self.0.stack); - let context = SampleDownloadContext::id_streams(&stack, "".to_owned(), &remotes).await - .map_err(|e| format!("download err: {}\r\n", e))?; - let (_, reader) = download_chunk(&stack, - chunk_id.clone(), - None, - context).await - .map_err(|e| format!("download err: {}\r\n", e))?; - let _ = future::timeout(Duration::from_secs(timeout as u64), LocalChunkWriter::new(local_path.clone(), None, &chunk_id).write(reader)).await - .map_err(|e| { - format!("download err: {}\r\n", e) - })?; + let chunk_store = self.0.chunk_store.clone(); + let context = SampleDownloadContext::desc_streams("".to_string(), remotes); + let begin = Instant::now(); + match download_chunk(&stack, chunk_id.clone(),None, context).await { + Ok((_, reader)) => { + chunk_store.write_chunk(&chunk_id, reader).await.unwrap(); + match future::timeout(Duration::from_secs(600), get_chunk_wait_finish(stack.clone(), chunk_id.clone())).await { + Err(e) => { + let _ = tunnel.write_all(format!("get_chunk_wait_finish err={}\r\n", e).as_ref()).await; + }, + Ok(r) => { + match r { + Ok(n) => { + let cost_secs = begin.elapsed().as_secs_f64(); + let _ = tunnel.write_all(format!("get success\r\n").as_ref()).await; + if chunk_id.len() != n { + let _ = tunnel.write_all(format!("data wrong, recv_len={} want={}\r\n", n, chunk_id.len()).as_ref()).await; + } else { + let len = n as f64; + let speed = if cost_secs > 0.0 { + len / cost_secs / 1024.0 + } else { + 999999.9 + }; + let _ = tunnel.write_all(format!("cost={:.3}s len={:.1}KB speed={:.1}KB/s\r\n", + cost_secs, len/1024.0, speed).as_ref()).await; + } + }, + Err(e) => { + let _ = tunnel.write_all(format!("get_chunk_wait_finish err={}\r\n", e).as_ref()).await; + } + } + } + } + }, + Err(e) => { + let _ = tunnel.write_all(format!("download_chunk err={}\r\n", e).as_ref()).await; + } + } - let _ = tunnel.write_all("waiting..\r\n".as_ref()).await; - let task_start_time = Instant::now(); - // let ret = watchdog_download_finished(path, timeout).await; - // if ret.is_ok() { - let size = get_filesize(&local_path); - let cost = Instant::now() - task_start_time; - let cost_sec = (cost.as_millis() as f64) / 1000.0; - let speed = (size as f64) * 8.0 / cost_sec / 1000000.0; - let _ = tunnel.write_all(format!("download chunk finish.\r\nsize: {:.1} MB\r\ncost: {:.1} s\r\nspeed: {:.1} Mbps\r\n", - size/1024/1024, cost_sec, speed).as_bytes()).await; - // } Ok(()) } @@ -407,53 +404,47 @@ impl DebugStub { format!("download err: {}\r\n", e) })?; - - // let ret = watchdog_download_finished(task.clone_as_task(), timeout).await; let _ = tunnel.write_all("download file finish.\r\n".as_ref()).await; Ok(()) } - async fn put_chunk(&self, _tunnel: TcpStream, _command: DebugCommandPutChunk) -> Result<(), String> { - // FIXME: impl put chunk debug command with - // let mut tunnel = tunnel; - // let stack = Stack::from(&self.0.stack); - // let local_path = command.local_path; + async fn put_chunk(&self, tunnel: TcpStream, command: DebugCommandPutChunk) -> Result<(), String> { + let mut tunnel = tunnel; + let local_path = command.local_path; - // if local_path.as_path().exists() { - // let mut file = async_std::fs::File::open(local_path.as_path()).await.map_err(|e| { - // format!("open file err: {}\r\n", e) - // })?; - // let mut content = Vec::::new(); - // let _ = file.read_to_end(&mut content).await.map_err(|e| { - // format!("read file err: {}\r\n", e) - // })?; + if local_path.as_path().exists() { + let mut file = async_std::fs::File::open(local_path.as_path()).await.map_err(|e| { + format!("open file err: {}\r\n", e) + })?; + let mut content = Vec::::new(); + let _ = file.read_to_end(&mut content).await.map_err(|e| { + format!("read file err: {}\r\n", e) + })?; - // if content.len() == 0 { - // return Err(format!("file size is zero\r\n")); - // } + if content.len() == 0 { + return Err(format!("file size is zero\r\n")); + } - // match ChunkId::calculate(content.as_slice()).await { - // Ok(chunk_id) => { - // LocalChunkWriter::new(&chunk_id, local_path, None).await - // .map_err(|e| { - // format!("download err: {}\r\n", e) - // })? - // .track_path().await - // .map_err(|e| { - // format!("download err: {}\r\n", e) - // })?; - // let _ = tunnel.write_all(format!("put chunk success. chunk_id: {}\r\n", - // chunk_id.to_string()).as_bytes()).await; - // Ok(()) - // }, - // Err(e) => { - // Err(format!("calculate chunk id err: {}\r\n", e)) - // } - // } - // } else { - // Err(format!("file not exists: {}\r\n", local_path.to_str().unwrap())) - // } - Err("not supported now".to_owned()) + let chunk_store = self.0.chunk_store.clone(); + match ChunkId::calculate(content.as_slice()).await { + Ok(chunk_id) => { + match chunk_store.add(chunk_id.clone(), Arc::new(content)).await { + Ok(_) => { + let _ = tunnel.write_all(format!("put chunk success, chunk_id={}\r\n", chunk_id).as_ref()).await; + }, + Err(e) => { + let _ = tunnel.write_all(format!("put chunk fail, err={}\r\n", e).as_ref()).await; + } + } + Ok(()) + }, + Err(e) => { + Err(format!("calculate chunk id err: {}\r\n", e)) + } + } + } else { + Err(format!("file not exists: {}\r\n", local_path.to_str().unwrap())) + } } async fn put_file(&self, _tunnel: TcpStream, _command: DebugCommandPutFile) -> Result<(), String> { @@ -600,4 +591,121 @@ fn rand_data_gen_buf(len: usize) -> Vec { } buf +} + +fn rand_char(len: usize) -> Vec { + let mut buf = Vec::new(); + buf.resize(len, 0u8); + + for i in 0..len { + buf[i] = 97 + rand::random::() % 26; + } + + buf +} + +async fn get_chunk_wait_finish(stack: Stack, chunk_id: ChunkId) -> BuckyResult { + let mut len = 0; + loop { + let ret = stack.ndn().chunk_manager().store().get(&chunk_id).await; + if let Ok(mut reader) = ret { + let mut content = vec![0u8; 2048]; + + loop { + let n = reader.read(content.as_mut_slice()).await?; + if n == 0 { + break ; + } + len += n; + } + + return Ok(len); + } else { + task::sleep(Duration::from_millis(200)).await; + } + } +} + +async fn nc_task(tunnel: TcpStream, command: DebugCommandNc, stack: Stack, task_id: u32) -> Result<(), String> { + let mut tunnel = tunnel; + let _ = tunnel.write_all(format!("[{}] connecting stream\r\n", task_id).as_ref()).await; + + let question = b"question?"; + let mut conn = stack.stream_manager().connect( + command.port, + question.to_vec(), + BuildTunnelParams { + remote_const: command.remote.desc().clone(), + remote_sn: None, + remote_desc: Some(command.remote.clone()) + }).await.map_err(|err| format!("Err: {}\r\n", err.msg().to_string()))?; + + let _ = tunnel.write_all(format!("[{}] Connect success, read answer\r\n", task_id).as_ref()).await; + + let mut answer = [0; 128]; + match conn.read(&mut answer).await { + Ok(len) => { + let s = format!("[{}] Read answer success, len={} content={:?}\r\n", + task_id, len, String::from_utf8(answer[..len].to_vec()).expect("")); + let _ = tunnel.write_all(s.as_bytes()).await; + }, + Err(e) => { + let s = format!("[{}] Read answer fail, err={}\r\n", task_id, e); + let _ = tunnel.write_all(s.as_bytes()).await; + return Ok(()); + } + } + + let _ = conn.write_all(b"hello world").await; + + let mut buf = [0u8; 128]; + match conn.read(&mut buf).await { + Ok(len) => { + let s = format!("[{}] Read data success, len={} content={:?}\r\n", + task_id, len, String::from_utf8(buf[..len].to_vec()).expect("")); + let _ = tunnel.write_all(s.as_bytes()).await; + }, + Err(e) => { + let s = format!("[{}] Read data fail, err={}\r\n", task_id, e); + let _ = tunnel.write_all(s.as_bytes()).await; + return Ok(()); + } + } + + let _ = tunnel.write_all(format!("[{}] Ok: stream connected\r\n", task_id).as_ref()).await; + + if command.bench > 0 { + let _ = tunnel.write_all(format!("[{}] start bench size={}MB\r\n", task_id, command.bench).as_ref()).await; + + let buf = rand_char(1024); + let mut i: u32 = 0; + let max = command.bench * 1024; + let begin = Instant::now(); + loop { + match conn.write_all(&buf).await { + Ok(_) => { + i += 1; + }, + Err(e) => { + let _ = tunnel.write_all(format!("[{}] write err={}\r\n", task_id, e).as_ref()).await; + break; + } + } + if i >= max { + break; + } + } + let cost = begin.elapsed().as_secs_f64(); + let speed = if cost > 0.0 { + i as f64 / cost + } else { + 999999.9 + }; + let _ = tunnel.write_all(format!("[{}] bench over. cost={:.3}s len={}KB speed={:.1}KB/s\r\n", + task_id, cost, i, speed).as_ref()).await; + } + + let _ = conn.shutdown(Shutdown::Both); + + Ok(()) } \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index c7f556e85..3a45b6a98 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -330,7 +330,7 @@ impl Stack { } let debug_stub = if stack.config().debug.is_some() { - Some(DebugStub::open(stack.to_weak()).await?) + Some(DebugStub::open(stack.to_weak(), stack.config().debug.as_ref().unwrap().chunk_store.clone()).await?) } else { None }; diff --git a/src/tools/bdt-debuger-deamon/Cargo.toml b/src/tools/bdt-debuger-deamon/Cargo.toml index 2fc55d5d4..94f25a2ef 100644 --- a/src/tools/bdt-debuger-deamon/Cargo.toml +++ b/src/tools/bdt-debuger-deamon/Cargo.toml @@ -12,6 +12,7 @@ description = "Rust bdt-debuger-deamon package" cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-bdt = { path = "../../component/cyfs-bdt" } +cyfs-util = { path = '../../component/cyfs-util', version = '0.6' } async-std = { version = "1.11", features = ["unstable", "attributes"] } clap = "2.34.0" log = "0.4" diff --git a/src/tools/bdt-debuger-deamon/src/main.rs b/src/tools/bdt-debuger-deamon/src/main.rs index a59b4c7cc..8b8ee4aa9 100644 --- a/src/tools/bdt-debuger-deamon/src/main.rs +++ b/src/tools/bdt-debuger-deamon/src/main.rs @@ -1,12 +1,14 @@ -use std::{io::Read, path::Path, str::FromStr, net::Shutdown}; +use std::{io::Read, path::Path, str::FromStr, net::Shutdown, time::Duration}; use async_std::{ task, stream::StreamExt, - io::prelude::{ReadExt}, + io::{prelude::{ReadExt}, WriteExt}, + future, }; use clap::{App, Arg}; use cyfs_base::*; -use cyfs_bdt::{self, Stack, StackOpenParams}; +use cyfs_bdt::*; +use log::*; fn load_dev_by_path(path: &str) -> Option { let desc_path = Path::new(path); @@ -52,8 +54,9 @@ async fn main() { .arg(Arg::with_name("active_pn").long("active_pn").takes_value(true).default_value("").help("active pn")) .arg(Arg::with_name("passive_pn").long("passive_pn").takes_value(true).default_value("").help("passive pn")) .arg(Arg::with_name("device_cache").long("device_cache").takes_value(true).default_value("").help("device cache")) + .arg(Arg::with_name("quiet").long("quiet").takes_value(false).default_value("0").help("quiet mode")) .get_matches(); - + let mut endpoints = vec![]; for ep in matches.values_of("ep").unwrap() { if let Ok(ep) = Endpoint::from_str(ep) { @@ -64,6 +67,8 @@ async fn main() { } } + let quiet = u16::from_str(matches.value_of("quiet").unwrap()).unwrap(); + let sns = load_sn(); let default_desc_path = Path::new("deamon.desc"); @@ -72,12 +77,24 @@ async fn main() { println!("deamon.desc not exists, generate new one"); let private_key = PrivateKey::generate_rsa(1024).unwrap(); let public_key = private_key.public(); - + + let sn_list = match sns.as_ref() { + Some(sns) => { + let mut sn_list = Vec::new(); + for sn in sns.iter() { + println!("sn_list push={}", sn.desc().device_id()); + sn_list.push(sn.desc().device_id()); + } + sn_list + }, + None => vec![], + }; + let device = Device::new( None, UniqueId::default(), endpoints.clone(), - vec![], + sn_list, vec![], public_key, Area::default(), @@ -109,7 +126,7 @@ async fn main() { return; } let mut device = device.unwrap(); - + info!("device={:?}", device); let private_key = { let mut buf = vec![]; @@ -124,23 +141,23 @@ async fn main() { let deamon_id = device.desc().device_id(); let deamon_name = format!("bdt-debuger-deamon-{}", deamon_id); - cyfs_debug::CyfsLoggerBuilder::new_app(deamon_name.as_str()) - .level("info") - .console("info") - .build() - .unwrap() - .start(); - + if quiet == 0 { + cyfs_debug::CyfsLoggerBuilder::new_app(deamon_name.as_str()) + .level("info") + .console("info") + .build() + .unwrap() + .start(); + } cyfs_debug::PanicBuilder::new(deamon_name.as_str(), deamon_name.as_str()) .exit_on_panic(true) .build() .start(); - let device_endpoints = device.mut_connect_info().mut_endpoints(); - device_endpoints.clear(); - for ep in endpoints { - device_endpoints.push(ep); + device_endpoints.clear(); + for ep in endpoints { + device_endpoints.push(ep); } let local = matches.value_of("local").unwrap(); @@ -151,12 +168,16 @@ async fn main() { } let port = port.unwrap(); + let chunk_store = MemChunkStore::new(); let mut params = StackOpenParams::new(deamon_name.as_str()); params.config.debug = Some(cyfs_bdt::debug::Config { local: local.to_string(), - port + port, + chunk_store: chunk_store.clone(), }); + let sns2 = sns.clone(); params.known_sn = sns; + params.config.interface.udp.sn_only = false; if let Some(active_pn) = matches.value_of("active_pn") { params.active_pn = load_dev_vec(active_pn); @@ -164,6 +185,7 @@ async fn main() { if let Some(passive_pn) = matches.value_of("passive_pn") { params.passive_pn = load_dev_vec(passive_pn); } + params.chunk_store = Some(Box::new(chunk_store.clone())); let stack = Stack::open( device, @@ -172,11 +194,40 @@ async fn main() { if let Err(err) = stack { println!("open stack failed for {}", err); - return; + return ; } let stack = stack.unwrap(); + if sns2.is_some() { + stack.reset_sn_list(sns2.unwrap()); + } + + match future::timeout( + Duration::from_secs(5), + stack.sn_client().ping().wait_online(), + ).await { + Ok(res) => { + match res { + Ok(res) => { + match res { + SnStatus::Online => {}, + _ => { + println!("sn offline"); + } + } + }, + Err(e) => { + println!("connect sn err={}", e); + } + } + }, + Err(e) => { + println!("wait_online err={}", e); + } + } + + if let Some(device_cache) = matches.value_of("device_cache") { if device_cache.len() > 0 { let dev = load_dev_by_path(device_cache).unwrap(); @@ -204,24 +255,46 @@ async fn main() { loop { if let Some(stream) = incoming.next().await { if let Ok(mut stream) = stream { - println!("question len={} content={:?}", - stream.question.len(), String::from_utf8(stream.question).expect("")); + task::spawn(async move { + println!("question len={} content={:?}", + stream.question.len(), String::from_utf8(stream.question).expect("")); - let _ = stream.stream.confirm(&vec![]).await; + let answer = b"answer!"; + let _ = stream.stream.confirm(&answer.to_vec()).await; - task::spawn(async move { - let mut buf = vec![]; - match stream.stream.read_to_end(&mut buf).await { - Ok(len) => { - println!("read data success. len={} data={}", - len, String::from_utf8(buf[..len].to_vec()).expect("")); - }, - Err(e) => { - println!("read data err: {}", e); - } + let mut read_buf = [0; 128]; + if let Ok(n) = stream.stream.read(&mut read_buf).await { + println!("read len={} data={}", n, String::from_utf8(read_buf[..n].to_vec()).expect("")); + } + + let write_buf = b"abcdefg"; + if let Ok(n) = stream.stream.write(write_buf).await { + println!("write len={}", n); } - let _ = stream.stream.shutdown(Shutdown::Both); + task::spawn(async move { + let mut buf = vec![0u8; 2048]; + let mut total = 0; + loop { + match stream.stream.read(&mut buf).await { + Ok(n) => { + total += n; + if n == 0 { + break; + } + }, + Err(e) => { + println!("read err={}", e); + break; + } + } + } + task::sleep(std::time::Duration::from_millis(200)).await; + match stream.stream.shutdown(Shutdown::Both) { + Ok(_) => println!("shutdown ok, total={}", total), + Err(e) => println!("shutdown err: {:?}", e), + } + }); }); } } @@ -232,4 +305,4 @@ async fn main() { println!("stack debug deamon running..."); async_std::future::pending::<()>().await; -} \ No newline at end of file +} From 8c45095ea928814c94e1ed9b6132b94a6bc3bd45 Mon Sep 17 00:00:00 2001 From: jing-git Date: Thu, 9 Mar 2023 16:40:32 +0800 Subject: [PATCH 201/553] Support peer to build tunnel without SN in LAN --- .../cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs | 5 +++++ .../cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs b/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs index c1a522ff5..51dc8a24a 100644 --- a/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs +++ b/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs @@ -185,6 +185,11 @@ impl ConnectStreamBuilder { } } } + } else if let Some(remote) = known_remote { + info!("{} explore_endpoint_pair with known remote {:?} again", self, remote.connect_info().endpoints()); + let _ = self.explore_endpoint_pair(remote, first_box.clone(), |_| true); + } else { + warn!("{} no sn and unkown remote", self); } } diff --git a/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs b/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs index 4901a8195..0e67a1eb5 100644 --- a/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs +++ b/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs @@ -144,6 +144,11 @@ impl ConnectTunnelBuilder { } } } + } else if let Some(remote) = known_remote { + info!("{} explore_endpoint_pair with known remote {:?} again", self, remote.connect_info().endpoints()); + let _ = self.explore_endpoint_pair(remote, first_box.clone(), |_| true); + } else { + warn!("{} no sn and unkown remote", self); } } From e8be03b647b353c29b479410a85041f83be92f71 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 202/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/component/cyfs-core/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index e075f74dd..e32db7eb9 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -30,3 +30,4 @@ hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } semver = '1.0' +sha2 = { version = '0.8' } \ No newline at end of file diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From d1bec6bd308ec3d7f2e3b974010f5055394273b3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:13:38 +0800 Subject: [PATCH 203/553] merge from buckyos --- src/component/cyfs-group/Cargo.toml | 2 +- src/component/cyfs-noc/src/blob/file.rs | 1 - src/component/cyfs-stack/Cargo.toml | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 599e13b51..aaab4ed76 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -28,7 +28,7 @@ async-recursion = '1.0' rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } -cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index 13838c174..9417d1377 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -4,7 +4,6 @@ use cyfs_lib::*; use std::borrow::Cow; use std::path::{Path, PathBuf}; -use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 1e9264e88..76148a72e 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -15,6 +15,7 @@ cyfs-bdt = { path = "../../component/cyfs-bdt" } cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } +cyfs-group = { path = "../../component/cyfs-group" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } From b81d7f3cd757c4322d1f2629a52f6edfd17054b9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:22:30 +0800 Subject: [PATCH 204/553] rename GroupRPathMgr to GroupManager --- .../src/dec/{rpath_mgr.rs => group_manager.rs} | 4 ++-- src/component/cyfs-group/src/dec/mod.rs | 4 ++-- src/component/cyfs-group/src/network/listener.rs | 6 +++--- src/component/cyfs-stack/src/stack/cyfs_stack.rs | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_mgr.rs => group_manager.rs} (99%) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/group_manager.rs similarity index 99% rename from src/component/cyfs-group/src/dec/rpath_mgr.rs rename to src/component/cyfs-group/src/dec/group_manager.rs index 644fc2fcf..56ef5e7d9 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -34,9 +34,9 @@ struct LocalInfo { } #[derive(Clone)] -pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); +pub struct GroupManager(Arc<(LocalInfo, RwLock)>); -impl GroupRPathMgr { +impl GroupManager { pub fn new( signer: RsaCPUObjectSigner, non_driver: Box, diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index a1f964e95..b4e753a27 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod delegate_factory; mod rpath_client; mod rpath_control; -mod rpath_mgr; +mod group_manager; pub use delegate_factory::*; pub use rpath_client::*; pub use rpath_control::*; -pub use rpath_mgr::*; +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6a6d7b549..e66ef8a43 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; -use crate::{GroupRPathMgr, HotstuffPackage}; +use crate::{GroupManager, HotstuffPackage}; pub struct Listener; impl Listener { pub fn spawn( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { async_std::task::spawn(async move { @@ -20,7 +20,7 @@ impl Listener { async fn run( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { loop { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 877464822..f7b54b532 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,9 +35,9 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; -use cyfs_group::GroupRPathMgr; +use cyfs_bdt::{DeviceCache, SnStatus, StackGuard}; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; +use cyfs_group::GroupManager; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -105,7 +105,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupRPathMgr, + group_manager: GroupManager, } impl CyfsStackImpl { @@ -428,7 +428,7 @@ impl CyfsStackImpl { config.clone(), ); - let group_manager = GroupRPathMgr::new( + let group_manager = GroupManager::new( signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), @@ -1159,7 +1159,7 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupRPathMgr { + pub fn group_mgr(&self) -> &GroupManager { &self.stack.group_manager } From baad9e94aea4e2e99eed19790fc2b955a70e76a7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 21:19:34 +0800 Subject: [PATCH 205/553] integrate GroupState, not finish --- .../cyfs-base/src/objects/object_map/mod.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 4 + .../cyfs-group/src/statepath/design.md | 26 +-- .../src/storage/engine/group_state_path.rs | 178 +++++++++++++++ .../cyfs-group/src/storage/engine/mod.rs | 9 + .../src/storage/engine/storage_engine.rs | 23 ++ .../engine/storage_engine_group_state.rs | 207 ++++++++++++++++++ .../storage_engine_mock.rs} | 53 ++--- .../cyfs-group/src/storage/group_storage.rs | 71 +++++- src/component/cyfs-group/src/storage/mod.rs | 4 +- 12 files changed, 524 insertions(+), 70 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs create mode 100644 src/component/cyfs-group/src/storage/engine/mod.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs rename src/component/cyfs-group/src/storage/{storage_engine.rs => engine/storage_engine_mock.rs} (76%) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index be52c2ea5..3bbc5f131 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -2,6 +2,7 @@ mod access; mod cache; mod check; mod diff; +mod isolate_path_env; mod iterator; mod lock; mod object_map; @@ -13,7 +14,6 @@ mod path_iterator; mod root; mod single_env; mod visitor; -mod isolate_path_env; pub use access::*; pub use cache::*; @@ -25,4 +25,5 @@ pub use path::*; pub use path_env::*; pub use path_iterator::*; pub use root::*; +pub use single_env::*; pub use visitor::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ff4e06380..e89498b83 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -18,7 +18,7 @@ use crate::{ consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** @@ -1461,12 +1461,13 @@ impl HotstuffRunner { continue; } - if let Some(ending) = proposal.effective_ending() { - if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.desc().object_id()); - timeout_proposals.push(proposal); - continue; - } + let ending = proposal.effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), + |ending| bucky_time_to_system_time(ending)); + if now >= ending { + remove_proposals.push(proposal.desc().object_id()); + timeout_proposals.push(proposal); + continue; } match self.delegate.on_execute(&proposal, result_state_id).await { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index aa7babc44..1170176b2 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,6 +14,7 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 56ef5e7d9..95c931720 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,6 +6,7 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, @@ -31,6 +32,7 @@ struct LocalInfo { non_driver: Arc>, datagram: DatagramTunnelGuard, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl GroupManager { signer: RsaCPUObjectSigner, non_driver: Box, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); @@ -50,6 +53,7 @@ impl GroupManager { non_driver: Arc::new(non_driver), datagram: datagram.clone(), bdt_stack, + global_state_mgr, }; let raw = GroupRPathMgrRaw { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index b73a46939..7ec71d4d5 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -7,22 +7,18 @@ | |--list-->Set | |--option-->GroupOption | -|--.dec-state // for dec;各Group的dec状态放这里 -| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 -| |--${dec-id} | .group // 一个dec管理的${r-path}状态 -| | | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | -| -|--.link // 区块链结构,记录状态变更链条 -| |--${group-id} -| |--${dec-id} | .group // .group表示group本身的演变共识 +|--${group-id} +| |--${dec-id} +| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 +| | // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-chunk-->Chunk(Group) +| |--group-blob-->BLOB(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs new file mode 100644 index 000000000..4e67d6e1f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/group_state_path.rs @@ -0,0 +1,178 @@ +use cyfs_base::ObjectId; + +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; + +pub struct GroupStatePath { + rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, +} + +impl GroupStatePath { + pub fn new(rpath: String) -> Self { + Self { + rpath, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.rpath.as_str() + } + + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() + } + + pub fn link(&self) -> &str { + self.link.as_str() + } + + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() + } + + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() + } + + pub fn range(&self) -> &str { + self.range.as_str() + } + + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) + } + + pub fn commit_block(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn commit_proposals(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_PROPOSALS, + ]) + } + + pub fn prepares(&self) -> &str { + self.prepares.as_str() + } + + pub fn prepare_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() + } + + pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.pre_commits.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() + } + + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() + } + + pub fn recycle(&self) -> &str { + self.recycle.as_str() + } + + pub fn adding(&self) -> &str { + self.adding.as_str() + } +} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs new file mode 100644 index 000000000..71d5cc49f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -0,0 +1,9 @@ +mod group_state_path; +mod storage_engine; +mod storage_engine_group_state; +mod storage_engine_mock; + +pub(super) use group_state_path::*; +pub(super) use storage_engine::*; +pub(super) use storage_engine_group_state::*; +pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs new file mode 100644 index 000000000..e48e607bc --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -0,0 +1,23 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Send + Sync + Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs new file mode 100644 index 000000000..3aba73e31 --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -0,0 +1,207 @@ +use std::{collections::HashSet, sync::Arc}; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, +}; + +use crate::StatePath; + +use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; + +const ACCESS: Option = None; + +#[derive(Clone)] +pub struct StorageEngineGroupState { + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, +} + +impl StorageEngineGroupState { + pub async fn load( + dec_group_state: ObjectMapRootManagerRef, + state_path: GroupStatePath, + ) -> BuckyResult { + Ok(Self { + state_mgr: todo!(), + state_path: Arc::new(state_path), + }) + } + + pub async fn create_writer(&self) -> BuckyResult { + Ok( + StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) + .await?, + ) + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineGroupState { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + let op_env = self.state_mgr.create_op_env(ACCESS)?; + let block_id = op_env + .get_by_path(self.state_path.commit_block(height).as_str()) + .await?; + block_id.map_or( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), + |block_id| Ok(block_id), + ) + } +} + +#[derive(Clone)] +pub struct StorageEngineGroupStateWriter { + state_mgr: ObjectMapRootManagerRef, + op_env: ObjectMapPathOpEnvRef, + prepare_op_env: ObjectMapSingleOpEnvRef, + prepare_map_id: Option, + state_path: Arc, +} + +impl StorageEngineGroupStateWriter { + async fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; + let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; + match prepare_map_id.as_ref() { + Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, + None => { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await? + } + }; + + Ok(Self { + op_env, + prepare_op_env, + state_path, + state_mgr, + prepare_map_id, + }) + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; + new_prepare + .create_new(ObjectMapSimpleContentType::Map) + .await?; + new_prepare + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + let new_prepare_block = new_prepare.commit().await?; + + self.prepare_op_env + .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .await + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str()) + .await? + .is_some() + { + assert!(false); + } + + // TODO + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineGroupStateWriter<'a> { + fn drop(&mut self) {} +} diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs similarity index 76% rename from src/component/cyfs-group/src/storage/storage_engine.rs rename to src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b9376618b..6208b0680 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -2,28 +2,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -#[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; - async fn push_proposals( - &mut self, - proposal_ids: &[ObjectId], - timestamp: u64, - ) -> BuckyResult<()>; - - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; -} - -#[async_trait::async_trait] -pub trait StorageEngine { - async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult; - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; -} +use super::{StorageEngine, StorageWriter}; struct StorageEngineMockFinishProposalMgr { flip_timestamp: u64, @@ -58,6 +37,10 @@ impl StorageEngineMock { }, } } + + pub async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) + } } #[async_trait::async_trait] @@ -69,19 +52,15 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult { - Ok(StorageEngineMockWriter { engine: self }) - } - - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { - let is_finished = self - .finish_proposals - .adding - .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) - .is_some(); - Ok(is_finished) - } + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + // let is_finished = self + // .finish_proposals + // .adding + // .get(proposal_id) + // .or(self.finish_proposals.over.get(proposal_id)) + // .is_some(); + // Ok(is_finished) + // } } pub struct StorageEngineMockWriter<'a> { @@ -164,9 +143,9 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: u64, + timestamp: Option, ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + if let Some(timestamp) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 440613f51..bc9fc6009 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, time::SystemTime}; +use std::{ + collections::{HashMap, HashSet}, + time::SystemTime, +}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, @@ -6,10 +9,13 @@ use cyfs_base::{ }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; + +use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; +use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; -use super::{storage_engine::StorageEngineMock, StorageEngine}; +const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; pub enum BlockLinkState { Expired, @@ -23,6 +29,12 @@ pub enum BlockLinkState { InvalidBranch, } +struct FinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -39,6 +51,8 @@ pub struct GroupStorage { prepares: HashMap, pre_commits: HashMap, + finish_proposals: FinishProposalMgr, + storage_engine: StorageEngineMock, } @@ -50,11 +64,19 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + // let group_state = root_state_mgr + // .load_root_state(group_id, Some(group_id.clone()), true) + // .await? + // .expect("create group state failed."); + + // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + Ok(Self { group, group_id: group_id.clone(), @@ -70,6 +92,11 @@ impl GroupStorage { pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), local_device_id, + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, }) } @@ -78,6 +105,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -240,10 +268,17 @@ impl GroupStorage { .iter() .map(|p| p.proposal.clone()) .collect(); - writer.push_proposals( - finish_proposals.as_slice(), - new_header.named_object().desc().create_time(), - ); + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + writer + .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } // update memory @@ -276,6 +311,20 @@ impl GroupStorage { if self.first_block.is_none() { self.first_block = self.header_block.clone(); } + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.finish_proposals.over); + self.finish_proposals.flip_timestamp = timestamp; + } + + for proposal in new_header.proposals() { + let is_new = self.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -551,7 +600,13 @@ impl GroupStorage { // find in storage - self.storage_engine.is_proposal_finished(proposal_id).await + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d95cf7ddd..d4440419e 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,7 @@ mod dec_storage; +mod engine; mod group_storage; -mod storage_engine; pub use dec_storage::*; +use engine::*; pub use group_storage::*; -pub(crate) use storage_engine::*; From 3282440bf83d75b4e137bd8294bda21d40138f5e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 17:28:17 +0800 Subject: [PATCH 206/553] integrate GroupState update --- .../cyfs-group/src/statepath/design.md | 11 +- .../src/statepath/group_statepath.rs | 257 +++++------- .../src/storage/engine/group_state_path.rs | 178 --------- .../cyfs-group/src/storage/engine/mod.rs | 2 - .../src/storage/engine/storage_engine.rs | 17 +- .../engine/storage_engine_group_state.rs | 367 +++++++++++++----- .../src/storage/engine/storage_engine_mock.rs | 30 +- .../cyfs-group/src/storage/group_storage.rs | 30 +- .../cyfs-stack/src/stack/cyfs_stack.rs | 1 + 9 files changed, 439 insertions(+), 454 deletions(-) delete mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 7ec71d4d5..70a61e428 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -25,15 +25,10 @@ | |--last-vote-round-->u64 // 最后一次投票的轮次 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height}) -| | |--block-->GroupConsensusBlock +| |--str(${height})->block | | -| |--prepares // Prepare状态的block -| | |--${block.id} -| | |--block -| |--pre-commits // pre-commit状态的block -| | |--${block.id} -| | |--block +| |--prepares->Set // Prepare状态的block +| |--pre-commits->Set // pre-commit状态的block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index c0daef478..eade0f9e4 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,19 +1,17 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; -pub const STATEPATH_SEPARATOR: &str = "/"; - -pub const STATEPATH_GROUPS: &str = "groups"; - -pub const STATEPATH_DEC_STATE: &str = ".dec-state"; - -pub const STATEPATH_LINK: &str = ".link"; -pub const STATEPATH_GROUP_HASH: &str = "group-hash"; -pub const STATEPATH_USERS: &str = "users"; -pub const STATEPATH_USERS_NONCE: &str = "nonce"; -pub const STATEPATH_RANGE: &str = "range"; -pub const STATEPATH_BLOCK: &str = "block"; - -pub const STATEPATH_RPATHS: &str = ".r-paths"; +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; @@ -23,180 +21,131 @@ lazy_static::lazy_static! { pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } -pub struct StatePath { - group_id: ObjectId, - group_id_str: String, - dec_id: ObjectId, - dec_id_str: String, +pub struct GroupStatePath { rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, } -impl StatePath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { +impl GroupStatePath { + pub fn new(rpath: String) -> Self { Self { - group_id_str: group_id.to_string(), - group_id, - dec_id_str: dec_id.to_string(), - dec_id, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), rpath, } } pub fn join(fields: &[&str]) -> String { - fields.join(STATEPATH_SEPARATOR) - } - - pub fn dec_state() -> String { - STATEPATH_DEC_STATE.to_string() - } - - pub fn dec_state_group(&self) -> String { - Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) - } - - pub fn dec_state_dec(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + fields.join(STATE_PATH_SEPARATOR) } - pub fn dec_state_rpath(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn root(&self) -> &str { + self.rpath.as_str() } - pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - sub_path, - ]) + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() } - pub fn link() -> String { - STATEPATH_LINK.to_string() + pub fn link(&self) -> &str { + self.link.as_str() } - pub fn link_group(&self) -> String { - Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() } - pub fn link_dec(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() } - pub fn link_rpath(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn range(&self) -> &str { + self.range.as_str() } - pub fn link_group_hash(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_GROUP_HASH, - ]) + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) } - pub fn link_users(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - ]) + pub fn prepares(&self) -> &str { + self.prepares.as_str() } - pub fn link_user(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - ]) + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() } - pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - STATEPATH_USERS_NONCE, - ]) + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() } - pub fn link_range(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_RANGE, - ]) - } - - pub fn link_height(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - ]) - } - - pub fn link_block(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - STATEPATH_BLOCK, - ]) - } - - pub fn rpaths(&self) -> String { - STATEPATH_RPATHS.to_string() - } -} - -pub struct GroupUpdateStatePath; - -impl GroupUpdateStatePath { - pub fn latest_version() -> &'static str { - STATEPATH_GROUP_DEC_LATEST_VERSION + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() } - pub fn version_seq(version_seq: u64) -> String { - version_seq.to_string() + pub fn recycle(&self) -> &str { + self.recycle.as_str() } - pub fn group_hash(group_hash: &ObjectId) -> String { - group_hash.to_string() + pub fn adding(&self) -> &str { + self.adding.as_str() } } diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs deleted file mode 100644 index 4e67d6e1f..000000000 --- a/src/component/cyfs-group/src/storage/engine/group_state_path.rs +++ /dev/null @@ -1,178 +0,0 @@ -use cyfs_base::ObjectId; - -pub const STATE_PATH_SEPARATOR: &str = "/"; -pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; -pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; -pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; -pub const GROUP_STATE_PATH_RANGE: &str = "range"; -pub const GROUP_STATE_PATH_BLOCK: &str = "block"; -pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; -pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; -pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; -pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; -pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; -pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; -pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; -pub const GROUP_STATE_PATH_ADDING: &str = "adding"; - -pub struct GroupStatePath { - rpath: String, - dec_state: String, - link: String, - group_blob: String, - last_vote_round: String, - range: String, - prepares: String, - pre_commits: String, - finish_proposals: String, - flip_time: String, - recycle: String, - adding: String, -} - -impl GroupStatePath { - pub fn new(rpath: String) -> Self { - Self { - rpath, - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, - ]), - last_vote_round: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, - ]), - range: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_RANGE, - ]), - prepares: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PREPARES, - ]), - pre_commits: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PRE_COMMITS, - ]), - finish_proposals: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - ]), - flip_time: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_FLIP_TIME, - ]), - recycle: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_RECYCLE, - ]), - adding: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_ADDING, - ]), - } - } - - pub fn join(fields: &[&str]) -> String { - fields.join(STATE_PATH_SEPARATOR) - } - - pub fn root(&self) -> &str { - self.rpath.as_str() - } - - pub fn dec_state(&self) -> &str { - self.dec_state.as_str() - } - - pub fn link(&self) -> &str { - self.link.as_str() - } - - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() - } - - pub fn last_vote_round(&self) -> &str { - self.last_vote_round.as_str() - } - - pub fn range(&self) -> &str { - self.range.as_str() - } - - pub fn commit_height(&self, height: u64) -> String { - Self::join(&[self.link.as_str(), height.to_string().as_str()]) - } - - pub fn commit_block(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn commit_proposals(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_PROPOSALS, - ]) - } - - pub fn prepares(&self) -> &str { - self.prepares.as_str() - } - - pub fn prepare_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.prepares.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn pre_commits(&self) -> &str { - self.pre_commits.as_str() - } - - pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.pre_commits.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn finish_proposals(&self) -> &str { - self.finish_proposals.as_str() - } - - pub fn flip_time(&self) -> &str { - self.flip_time.as_str() - } - - pub fn recycle(&self) -> &str { - self.recycle.as_str() - } - - pub fn adding(&self) -> &str { - self.adding.as_str() - } -} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs index 71d5cc49f..c185cb24c 100644 --- a/src/component/cyfs-group/src/storage/engine/mod.rs +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -1,9 +1,7 @@ -mod group_state_path; mod storage_engine; mod storage_engine_group_state; mod storage_engine_mock; -pub(super) use group_state_path::*; pub(super) use storage_engine::*; pub(super) use storage_engine_group_state::*; pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e48e607bc..e19c46b81 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,19 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { +pub trait StorageWriter: Send + Sync { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()>; async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()>; - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + + async fn commit(mut self) -> BuckyResult<()>; } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 3aba73e31..731725e95 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use crate::StatePath; +use crate::{ + GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, +}; -use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; +use super::{StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -41,7 +44,7 @@ impl StorageEngine for StorageEngineGroupState { async fn find_block_by_height(&self, height: u64) -> BuckyResult { let op_env = self.state_mgr.create_op_env(ACCESS)?; let block_id = op_env - .get_by_path(self.state_path.commit_block(height).as_str()) + .get_by_path(self.state_path.commit_height(height).as_str()) .await?; block_id.map_or( Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), @@ -57,6 +60,7 @@ pub struct StorageEngineGroupStateWriter { prepare_op_env: ObjectMapSingleOpEnvRef, prepare_map_id: Option, state_path: Arc, + write_result: BuckyResult<()>, } impl StorageEngineGroupStateWriter { @@ -65,16 +69,20 @@ impl StorageEngineGroupStateWriter { state_path: Arc, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; - let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; - match prepare_map_id.as_ref() { - Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, - None => { - prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await? - } - }; + let prepare_map_id = + if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { + if err.code() == BuckyErrorCode::NotFound { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + None + } else { + return Err(err); + } + } else { + prepare_op_env.get_current_root().await + }; Ok(Self { op_env, @@ -82,126 +90,299 @@ impl StorageEngineGroupStateWriter { state_path, state_mgr, prepare_map_id, + write_result: Ok(()), }) } -} - -#[async_trait::async_trait] -impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { - let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; - new_prepare - .create_new(ObjectMapSimpleContentType::Map) - .await?; - new_prepare - .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) - .await?; - let new_prepare_block = new_prepare.commit().await?; + async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { self.prepare_op_env - .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .insert(block_id) .await + .map(|is_changed| assert!(is_changed)) } - async fn insert_pre_commit( + async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, is_instead: bool, ) -> BuckyResult<()> { - if !self - .prepare_op_env - .remove_with_key(block_id.to_string().as_str()) - .await? - .is_some() - { - assert!(false); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); - // TODO if is_instead { - self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); - } else { - if !self.engine.pre_commit_blocks.insert(block_id.clone()) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block pre-commit twice", - )); - } + self.op_env + .remove_with_path(self.state_path.pre_commits(), &None) + .await?; } - Ok(()) + self.op_env + .insert_with_path(self.state_path.pre_commits(), block_id) + .await } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if self - .engine - .commit_blocks - .insert(height, block_id.clone()) - .is_some() - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block commit twice", - )); - } + async fn push_commit_inner( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.op_env + .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) + .await?; - self.engine.block_height_range.1 = height; + let range_obj = make_range_obj(min_height, height); + if height == 1 { + self.op_env + .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) + .await?; + } else { + let prev_range = make_range_obj(min_height, height - 1); + let prev_value = self + .op_env + .set_with_key( + self.state_path.link(), + GROUP_STATE_PATH_RANGE, + &range_obj, + &Some(prev_range), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_range); + }; + + // update state from dec-app + if result_state_id == prev_result_state_id { + return Ok(()); + } else { + match result_state_id { + Some(result_state_id) => { + if prev_result_state_id.is_none() { + self.op_env + .insert_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + ) + .await?; + } else { + let prev_value = self + .op_env + .set_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + prev_result_state_id, + false, + ) + .await?; + assert_eq!(&prev_value, prev_result_state_id); + } + } + None => { + self.op_env + .remove_with_path(self.state_path.dec_state(), prev_result_state_id) + .await?; + } + } + } Ok(()) } - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - if !self.engine.prepare_blocks.remove(block_id) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "try remove prepare not exists", - )); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); } Ok(()) } - async fn push_proposals( + async fn push_proposals_inner( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); - self.engine.finish_proposals.flip_timestamp = timestamp; + if proposal_ids.is_empty() { + return Ok(()); } - for proposal_id in proposal_ids { - if !self - .engine - .finish_proposals - .adding - .insert(proposal_id.clone()) - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "dup finish proposal", - )); + let add_single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + + if let Some((timestamp, prev_timestamp)) = timestamp { + let new_over = self + .op_env + .remove_with_path(self.state_path.adding(), &None) + .await?; + + if let Some(new_over) = new_over.as_ref() { + self.op_env + .set_with_path(self.state_path.recycle(), new_over, &None, true) + .await?; } + + let timestamp_obj = make_u64_obj(timestamp); + if prev_timestamp != 0 { + let prev_timestamp_obj = make_u64_obj(prev_timestamp); + let prev_value = self + .op_env + .set_with_path( + self.state_path.flip_time(), + ×tamp_obj, + &Some(prev_timestamp_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_timestamp_obj); + } else { + self.op_env + .insert_with_key( + self.state_path.finish_proposals(), + GROUP_STATE_PATH_FLIP_TIME, + ×tamp_obj, + ) + .await?; + } + + add_single_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + } else { + add_single_op_env + .load_by_path(self.state_path.adding()) + .await?; } + for proposal_id in proposal_ids { + let is_new = add_single_op_env.insert(proposal_id).await?; + assert!(is_new); + } + let adding_set_id = add_single_op_env.commit().await?; + let prev_value = self + .op_env + .set_with_path(self.state_path.adding(), &adding_set_id, &None, true) + .await?; + Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - self.engine.last_vote_round = round; + async fn set_last_vote_round_inner(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert!(round > prev_value); + if round == prev_value { + return Ok(()); + } - Ok(()) + let round_obj = make_u64_obj(round); + + if prev_value == 0 { + self.op_env + .insert_with_path(self.state_path.last_vote_round(), &round_obj) + .await + } else { + let prev_obj = make_u64_obj(prev_value); + let prev_value = self + .op_env + .set_with_path( + self.state_path.last_vote_round(), + &round_obj, + &Some(prev_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_obj); + Ok(()) + } + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result.clone() + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result.clone() + } + + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self + .push_commit_inner( + height, + block_id, + result_state_id, + prev_result_state_id, + min_height, + ) + .await; + self.write_result.clone() + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.remove_prepares_inner(block_ids).await; + self.write_result.clone() + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.push_proposals_inner(proposal_ids, timestamp).await; + self.write_result.clone() + } + + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.set_last_vote_round_inner(round, prev_value).await; + self.write_result.clone() + } + + async fn commit(mut self) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + + let prepare_map_id = self.prepare_op_env.commit().await?; + self.op_env + .set_with_path( + self.state_path.prepares(), + &prepare_map_id, + &self.prepare_map_id, + self.prepare_map_id.is_none(), + ) + .await?; + self.op_env.commit().await.map(|_| ()) } } -impl<'a> Drop for StorageEngineGroupStateWriter<'a> { - fn drop(&mut self) {} +fn make_range_obj(min: u64, max: u64) -> ObjectId { + let mut range_buf = [0u8; 24]; + let (low, high) = range_buf.split_at_mut(12); + low.copy_from_slice(&min.to_le_bytes()); + high.copy_from_slice(&max.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() +} + +fn make_u64_obj(value: u64) -> ObjectId { + let mut range_buf = [0u8; 8]; + range_buf.copy_from_slice(&value.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 6208b0680..b944d3735 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -13,6 +13,7 @@ struct StorageEngineMockFinishProposalMgr { pub struct StorageEngineMock { last_vote_round: u64, + result_state_id: Option, block_height_range: (u64, u64), commit_blocks: HashMap, @@ -30,6 +31,7 @@ impl StorageEngineMock { commit_blocks: HashMap::new(), prepare_blocks: HashSet::new(), pre_commit_blocks: HashSet::new(), + result_state_id: None, finish_proposals: StorageEngineMockFinishProposalMgr { flip_timestamp: 0, over: HashSet::new(), @@ -108,7 +110,18 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + assert!(height > min_height); + assert_eq!(height, self.engine.block_height_range.1 + 1); + assert_eq!(prev_result_state_id, &self.engine.result_state_id); + if self .engine .commit_blocks @@ -123,6 +136,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } self.engine.block_height_range.1 = height; + self.engine.result_state_id = result_state_id.clone(); Ok(()) } @@ -143,12 +157,13 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if let Some(timestamp) = timestamp { + if let Some((timestamp, prev_timestamp)) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + assert_eq!(prev_timestamp, self.engine.finish_proposals.flip_timestamp); self.engine.finish_proposals.flip_timestamp = timestamp; } @@ -170,13 +185,14 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert_eq!(self.engine.last_vote_round, prev_value); self.engine.last_vote_round = round; Ok(()) } -} -impl<'a> Drop for StorageEngineMockWriter<'a> { - fn drop(&mut self) {} + async fn commit(mut self) -> BuckyResult<()> { + Ok(()) + } } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index bc9fc6009..a7284f403 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -13,7 +13,7 @@ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; +use super::{engine::StorageEngineMock, StorageEngine}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -42,15 +42,14 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, + group_chunk_id: ObjectId, dec_state_id: Option, // commited/header state id - group_chunk_id: ObjectId, last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, prepares: HashMap, pre_commits: HashMap, - finish_proposals: FinishProposalMgr, storage_engine: StorageEngineMock, @@ -258,7 +257,15 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit(new_header.height(), new_header.block_id().object_id()) + .push_commit( + new_header.height(), + new_header.block_id().object_id(), + new_header.result_state_id(), + self.header_block + .as_ref() + .map_or(&None, |b| b.result_state_id()), + self.first_block.as_ref().map_or(0, |b| b.height()), + ) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -272,7 +279,10 @@ impl GroupStorage { let timestamp = new_header.named_object().desc().create_time(); if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer - .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.finish_proposals.flip_timestamp)), + ) .await?; } else { writer @@ -281,6 +291,8 @@ impl GroupStorage { } } + writer.commit().await?; + // update memory if self .prepares @@ -293,7 +305,6 @@ impl GroupStorage { match new_header { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); - self.header_block = Some(new_header); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); self.prepares.remove(&new_pre_commit.0); @@ -309,7 +320,7 @@ impl GroupStorage { } if self.first_block.is_none() { - self.first_block = self.header_block.clone(); + self.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); @@ -325,6 +336,7 @@ impl GroupStorage { assert!(is_new); } + self.header_block = Some(new_header); return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -359,7 +371,9 @@ impl GroupStorage { // storage let mut writer = self.storage_engine.create_writer().await?; - writer.set_last_vote_round(round).await?; + writer + .set_last_vote_round(round, self.last_vote_round) + .await?; self.last_vote_round = round; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index f7b54b532..4c91fe145 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -432,6 +432,7 @@ impl CyfsStackImpl { signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), + global_state_manager.clone_processor(), )?; let mut stack = Self { From 2d2f74829fff6e57ced136c3228d7af34068cfea Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 20:15:19 +0800 Subject: [PATCH 207/553] integrate GroupState load --- .../cyfs-group/src/dec/group_manager.rs | 12 +- .../src/storage/engine/storage_engine.rs | 37 ++++ .../engine/storage_engine_group_state.rs | 180 ++++++++++++++-- .../cyfs-group/src/storage/group_storage.rs | 198 ++++++++++-------- 4 files changed, 327 insertions(+), 100 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95c931720..5ecfcdba2 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -372,6 +372,7 @@ impl GroupManager { let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -379,7 +380,15 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; + let store = GroupStorage::load( + group_id, + dec_id, + rpath, + non_driver.clone(), + local_device_id.object_id().clone(), + &root_state_mgr, + ) + .await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -430,6 +439,7 @@ impl GroupManager { init_state, non_driver.clone(), local_device_id.object_id().clone(), + &root_state_mgr, ) .await? } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e19c46b81..735277a3a 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,4 +1,41 @@ +use std::collections::{HashMap, HashSet}; + use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct FinishProposalMgr { + pub flip_timestamp: u64, + pub over: HashSet, + pub adding: HashSet, +} + +pub struct StorageCacheInfo { + pub dec_state_id: Option, // commited/header state id + pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub header_block: Option, + pub first_block: Option, + pub prepares: HashMap, + pub pre_commits: HashMap, + pub finish_proposals: FinishProposalMgr, +} + +impl StorageCacheInfo { + pub fn new(init_state_id: Option) -> Self { + Self { + dec_state_id: init_state_id, + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 731725e95..ee429a78f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,16 +1,18 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, - ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, + ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_RANGE, }; -use super::{StorageEngine, StorageWriter}; +use super::{StorageCacheInfo, StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -21,14 +23,110 @@ pub struct StorageEngineGroupState { } impl StorageEngineGroupState { - pub async fn load( - dec_group_state: ObjectMapRootManagerRef, - state_path: GroupStatePath, - ) -> BuckyResult { - Ok(Self { - state_mgr: todo!(), + pub(crate) async fn load_cache( + state_mgr: &ObjectMapRootManagerRef, + non_driver: &NONDriverHelper, + state_path: &GroupStatePath, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; + + let last_vote_round = op_env + .get_by_path(state_path.last_vote_round()) + .await? + .map(|id| parse_u64_obj(&id)); + + let mut first_header_block_ids: Vec = vec![]; + let commit_range = op_env + .get_by_path(state_path.range()) + .await? + .map(|id| parse_range_obj(&id)); + let commit_block = match commit_range { + Some((first_height, header_height)) => { + let first_block_id = op_env + .get_by_path(state_path.commit_height(first_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(first_block_id); + + if header_height == first_height { + Some((first_block_id, first_block_id)) + } else { + let header_block_id = op_env + .get_by_path(state_path.commit_height(header_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(header_block_id); + Some((first_block_id, header_block_id)) + } + } + None => None, + }; + + let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let pre_commit_block_ids = + load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + + let flip_timestamp = op_env + .get_by_path(state_path.flip_time()) + .await? + .map_or(0, |id| parse_u64_obj(&id)); + + let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; + let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + + let load_block_ids = [ + first_header_block_ids.as_slice(), + prepare_block_ids.as_slice(), + pre_commit_block_ids.as_slice(), + ] + .concat(); + + let load_blocks = futures::future::join_all( + load_block_ids + .iter() + .map(|id| non_driver.get_block(id, None)), + ) + .await; + + let mut cache = StorageCacheInfo::new(dec_state_id); + cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); + cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); + cache.finish_proposals.flip_timestamp = flip_timestamp; + + let prepare_block_pos = match commit_block { + Some((first_block_id, header_block_id)) => { + cache.first_block = Some(load_blocks.get(0).unwrap().clone()?); + if header_block_id == first_block_id { + cache.header_block = cache.first_block.clone(); + 1 + } else { + cache.header_block = Some(load_blocks.get(1).unwrap().clone()?); + 2 + } + } + None => 0, + }; + + let (prepare_blocks, pre_commit_blocks) = + load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); + for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { + cache.prepares.insert(block_id, block.clone()?); + } + for (block, block_id) in pre_commit_blocks.iter().zip(pre_commit_block_ids) { + cache.pre_commits.insert(block_id, block.clone()?); + } + + Ok(cache) + } + + pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + Self { + state_mgr, state_path: Arc::new(state_path), - }) + } } pub async fn create_writer(&self) -> BuckyResult { @@ -132,12 +230,14 @@ impl StorageEngineGroupStateWriter { .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) .await?; - let range_obj = make_range_obj(min_height, height); if height == 1 { + let range_obj = make_range_obj(1, height); self.op_env .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) .await?; } else { + assert!(min_height < height); + let range_obj = make_range_obj(min_height, height); let prev_range = make_range_obj(min_height, height - 1); let prev_value = self .op_env @@ -376,13 +476,63 @@ impl StorageWriter for StorageEngineGroupStateWriter { fn make_range_obj(min: u64, max: u64) -> ObjectId { let mut range_buf = [0u8; 24]; let (low, high) = range_buf.split_at_mut(12); - low.copy_from_slice(&min.to_le_bytes()); - high.copy_from_slice(&max.to_le_bytes()); + low[..8].copy_from_slice(&min.to_le_bytes()); + high[..8].copy_from_slice(&max.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } +fn parse_range_obj(obj: &ObjectId) -> (u64, u64) { + let range_buf = obj.data(); + assert_eq!(range_buf.len(), 24); + let (low_buf, high_buf) = range_buf.split_at(12); + let mut low = [0u8; 8]; + low.copy_from_slice(&low_buf[..8]); + let mut high = [0u8; 8]; + high.copy_from_slice(&high_buf[..8]); + + (u64::from_le_bytes(low), u64::from_le_bytes(high)) +} + fn make_u64_obj(value: u64) -> ObjectId { let mut range_buf = [0u8; 8]; range_buf.copy_from_slice(&value.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } + +fn parse_u64_obj(obj: &ObjectId) -> u64 { + let mut buf = [0u8; 8]; + buf.copy_from_slice(obj.data()); + u64::from_le_bytes(buf) +} + +async fn load_object_ids_with_path( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Set(id) => object_ids.push(id.clone()), + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a7284f403..5ad19ea15 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -11,9 +11,14 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::GlobalStateManagerRawProcessorRef; -use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; +use crate::{ + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, +}; -use super::{engine::StorageEngineMock, StorageEngine}; +use super::{ + engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + StorageEngine, +}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -29,12 +34,6 @@ pub enum BlockLinkState { InvalidBranch, } -struct FinishProposalMgr { - flip_timestamp: u64, - over: HashSet, - adding: HashSet, -} - pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -44,15 +43,9 @@ pub struct GroupStorage { non_driver: NONDriverHelper, group_chunk_id: ObjectId, - dec_state_id: Option, // commited/header state id - last_vote_round: u64, // 参与投票的最后一个轮次 - header_block: Option, - first_block: Option, - prepares: HashMap, - pre_commits: HashMap, - finish_proposals: FinishProposalMgr, + cache: StorageCacheInfo, - storage_engine: StorageEngineMock, + storage_engine: StorageEngineGroupState, } impl GroupStorage { @@ -63,18 +56,18 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); - // let group_state = root_state_mgr - // .load_root_state(group_id, Some(group_id.clone()), true) - // .await? - // .expect("create group state failed."); + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); - // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; Ok(Self { group, @@ -82,20 +75,13 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - dec_state_id: init_state_id, group_chunk_id: group_chunk_id.object_id(), - last_vote_round: 0, - header_block: None, - first_block: None, - prepares: HashMap::new(), - pre_commits: HashMap::new(), - storage_engine: StorageEngineMock::new(), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + GroupStatePath::new(rpath.to_string()), + ), local_device_id, - finish_proposals: FinishProposalMgr { - flip_timestamp: 0, - over: HashSet::new(), - adding: HashSet::new(), - }, + cache: StorageCacheInfo::new(init_state_id), }) } @@ -104,37 +90,62 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - // unimplemented!() - Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); + + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + + let state_path = GroupStatePath::new(rpath.to_string()); + let cache = + StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + group_chunk_id: group_chunk_id.object_id(), + storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + local_device_id, + cache: cache, + }) } pub fn header_block(&self) -> &Option { - &self.header_block + &self.cache.header_block } pub fn header_round(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.round()) + self.cache.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.height()) + self.cache.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - &self.first_block + &self.cache.first_block } pub fn prepares(&self) -> &HashMap { - &self.prepares + &self.cache.prepares } pub fn pre_commits(&self) -> &HashMap { - &self.pre_commits + &self.cache.pre_commits } pub fn group(&self) -> &Group { @@ -146,34 +157,37 @@ impl GroupStorage { } pub fn dec_state_id(&self) -> &Option { - &self.dec_state_id + &self.cache.dec_state_id } pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { let header_height = self.header_height(); let block = match height.cmp(&header_height) { std::cmp::Ordering::Less => { - if height == self.first_block.as_ref().map_or(0, |b| b.height()) { - self.first_block.clone() + if height == self.cache.first_block.as_ref().map_or(0, |b| b.height()) { + self.cache.first_block.clone() } else { // find in storage let block_id = self.storage_engine.find_block_by_height(height).await?; Some(self.non_driver.get_block(&block_id, None).await?) } } - std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Equal => self.cache.header_block.clone(), std::cmp::Ordering::Greater => { if height == header_height + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.height() == height) .or(self + .cache .prepares .iter() .find(|(_, block)| block.height() == height)) .map(|(_, block)| block.clone()) } else if height == header_height + 2 { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.height() == height) .map(|(_, block)| block.clone()) @@ -202,16 +216,17 @@ impl GroupStorage { // prepare update memory if let Some(prev_block_id) = prev_block_id { - if let Some(prev_block) = self.prepares.get(prev_block_id) { + if let Some(prev_block) = self.cache.prepares.get(prev_block_id) { new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); if let Some(prev_prev_block_id) = prev_block.prev_block_id() { - if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + if let Some(prev_prev_block) = self.cache.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); assert_eq!( prev_prev_block.prev_block_id(), - self.header_block + self.cache + .header_block .as_ref() .map(|b| b.block_id().object_id().clone()) .as_ref() @@ -220,7 +235,7 @@ impl GroupStorage { new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.block_id().object_id(); - for (id, block) in self.prepares.iter() { + for (id, block) in self.cache.prepares.iter() { if block.prev_block_id().map(|prev_id| { assert_ne!(prev_id, prev_block_id); prev_id == new_header_id @@ -261,10 +276,11 @@ impl GroupStorage { new_header.height(), new_header.block_id().object_id(), new_header.result_state_id(), - self.header_block + self.cache + .header_block .as_ref() .map_or(&None, |b| b.result_state_id()), - self.first_block.as_ref().map_or(0, |b| b.height()), + self.cache.first_block.as_ref().map_or(0, |b| b.height()), ) .await?; @@ -277,11 +293,11 @@ impl GroupStorage { .collect(); let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer .push_proposals( finish_proposals.as_slice(), - Some((timestamp, self.finish_proposals.flip_timestamp)), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), ) .await?; } else { @@ -295,6 +311,7 @@ impl GroupStorage { // update memory if self + .cache .prepares .insert(block_id.object_id().clone(), block) .is_some() @@ -304,53 +321,60 @@ impl GroupStorage { match new_header { Some(new_header) => { - self.dec_state_id = new_header.result_state_id().clone(); + self.cache.dec_state_id = new_header.result_state_id().clone(); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); - self.prepares.remove(&new_pre_commit.0); + self.cache.prepares.remove(&new_pre_commit.0); let mut removed_blocks = HashMap::from([new_pre_commit]); - std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + std::mem::swap(&mut self.cache.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = removed_blocks.into_values().collect(); for id in remove_prepares.iter() { - removed_blocks.push(self.prepares.remove(id).unwrap()); + removed_blocks.push(self.cache.prepares.remove(id).unwrap()); } - if self.first_block.is_none() { - self.first_block = Some(new_header.clone()); + if self.cache.first_block.is_none() { + self.cache.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MS + { let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.finish_proposals.over); - self.finish_proposals.flip_timestamp = timestamp; + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; } for proposal in new_header.proposals() { - let is_new = self.finish_proposals.adding.insert(proposal.proposal); + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); assert!(is_new); } - self.header_block = Some(new_header); - return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + self.cache.header_block = Some(new_header); + return Ok(Some(( + self.cache.header_block.as_ref().unwrap(), + removed_blocks, + ))); } None => { if let Some(new_pre_commit) = new_pre_commit { assert!(remove_prepares.is_empty()); if self + .cache .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) .is_some() { assert!(false); } - self.prepares + self.cache + .prepares .remove(&new_pre_commit.0) .expect("any block in pre-commit should be from prepare"); } @@ -361,21 +385,21 @@ impl GroupStorage { } pub fn last_vote_round(&self) -> u64 { - self.last_vote_round + self.cache.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - if round <= self.last_vote_round { + if round <= self.cache.last_vote_round { return Ok(()); } // storage let mut writer = self.storage_engine.create_writer().await?; writer - .set_last_vote_round(round, self.last_vote_round) + .set_last_vote_round(round, self.cache.last_vote_round) .await?; - self.last_vote_round = round; + self.cache.last_vote_round = round; Ok(()) } @@ -533,15 +557,16 @@ impl GroupStorage { } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { - if let Some(block) = self.header_block.as_ref() { + if let Some(block) = self.cache.header_block.as_ref() { if block.block_id().object_id() == block_id { return Ok(block.clone()); } } - self.prepares + self.cache + .prepares .get(block_id) - .or(self.pre_commits.get(block_id)) + .or(self.cache.pre_commits.get(block_id)) .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) .map(|block| block.clone()) } @@ -553,20 +578,24 @@ impl GroupStorage { std::cmp::Ordering::Less => { return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Equal => self.cache.header_block.as_ref(), std::cmp::Ordering::Greater => if round == header_round + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .prepares .iter() .find(|(_, block)| block.round() == round)) } else { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .pre_commits .iter() .find(|(_, block)| block.round() == round)) @@ -615,10 +644,11 @@ impl GroupStorage { // find in storage let is_finished = self + .cache .finish_proposals .adding .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) + .or(self.cache.finish_proposals.over.get(proposal_id)) .is_some(); Ok(is_finished) } @@ -647,7 +677,7 @@ impl GroupStorage { &self, round: u64, ) -> (BuckyResult, Vec) { - if self.header_block.is_none() { + if self.cache.header_block.is_none() { return ( Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), vec![], @@ -655,7 +685,7 @@ impl GroupStorage { } let mut blocks = vec![]; - let mut block = self.header_block.clone().unwrap(); + let mut block = self.cache.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; let mut max_height = block.height(); From 9dbbe13640ffa07f624b2e7470abbefaf0dffe52 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 15:20:55 +0800 Subject: [PATCH 208/553] update example for GroupState --- src/tests/group-example/src/main.rs | 479 +++++++++++++++++++--------- 1 file changed, 332 insertions(+), 147 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ffb45ccec..e7948f740 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -3,27 +3,28 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, }; use cyfs_stack::CyfsStack; -use Common::{ - create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, - EXAMPLE_RPATH, -}; +use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; + mod Common { - use std::sync::Arc; + use std::{fmt::format, io::ErrorKind, sync::Arc}; + use async_std::{fs, stream::StreamExt}; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, - UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -35,113 +36,109 @@ mod Common { CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, }; - use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members( + fn create_member( name_prefix: &str, - count: usize, - ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + index: usize, + port: u16, + ) -> ((People, PrivateKey), (Device, PrivateKey)) { log::info!("create members"); - let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); - let mut members = vec![]; + let name = format!("{}-{}", name_prefix, index); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); + endpoint.mut_addr().set_port(port); + endpoint.set_area(EndpointArea::Wan); + + let mut device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + device_private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); - for i in 0..count { - let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_rsa(1024).unwrap(); - let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); - let mut owner = - People::new(None, vec![], private_key.public(), None, Some(name), None).build(); - - let mut endpoint = Endpoint::default(); - endpoint.set_protocol(Protocol::Udp); - endpoint - .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); - endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_area(EndpointArea::Wan); - - let mut device = Device::new( - Some(owner.desc().object_id()), - UniqueId::create_with_random(), - vec![endpoint], - vec![], // TODO: 当前版本是否支持无SN? - vec![], - device_private_key.public(), - Area::default(), - DeviceCategory::PC, - ) - .build(); - - owner - .ood_list_mut() - .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - - let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); - let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); - let device_desc_hash = device.desc().raw_hash_value().unwrap(); - let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); - - let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = - async_std::task::block_on(async move { - let owner_desc_signature = signer - .sign( - owner_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let owner_body_signature = signer - .sign( - owner_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let desc_signature = signer - .sign( - device_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - let body_signature = signer - .sign( - device_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - ( - owner_desc_signature, - owner_body_signature, - desc_signature, - body_signature, + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), ) - }); + .await + .unwrap(); - device.signs_mut().set_desc_sign(desc_signature.clone()); - device.signs_mut().set_body_sign(body_signature); + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); - log::info!( + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", owner.name().unwrap(), owner.desc().object_id(), @@ -152,12 +149,9 @@ mod Common { owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() ); - owner.signs_mut().set_desc_sign(owner_desc_signature); - owner.signs_mut().set_body_sign(owner_body_signature); - members.push(((owner, private_key), (device, device_private_key))); - } - - members + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + ((owner, private_key), (device, device_private_key)) } fn create_group( @@ -194,16 +188,167 @@ mod Common { group } + // (succ, not-found) + fn check_read_buf(file_path: &str, result: &std::io::Result>) -> (bool, bool) { + match result.as_ref() { + Ok(b) => { + if b.len() == 0 { + (false, true) + } else { + (true, false) + } + } + Err(err) if ErrorKind::NotFound == err.kind() => (false, true), + Err(err) => { + log::warn!("read file {} failed: {:?}", file_path, err); + (false, false) + } + } + } + + async fn init_member_from_dir( + save_path: &str, + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + fs::create_dir_all(save_path) + .await + .expect(format!("create dir {} failed", save_path).as_str()); + + let min_port = 30217_u16; + + let mut members = vec![]; + + for i in 0..count { + let index = i + 1; + let people_desc_file_path = format!("{}/people-{}.desc", save_path, index); + let people_sec_file_path = format!("{}/people-{}.sec", save_path, index); + let device_desc_file_path = format!("{}/device-{}.desc", save_path, index); + let device_sec_file_path = format!("{}/device-{}.sec", save_path, index); + + let people_desc_r = fs::read(people_desc_file_path.clone()).await; + let people_sec_r = fs::read(people_sec_file_path.clone()).await; + let device_desc_r = fs::read(device_desc_file_path.clone()).await; + let device_sec_r = fs::read(device_sec_file_path.clone()).await; + + let (is_people_desc_succ, is_people_desc_not_found) = + check_read_buf(people_desc_file_path.as_str(), &people_desc_r); + let (is_people_sec_succ, is_people_sec_not_found) = + check_read_buf(people_sec_file_path.as_str(), &people_sec_r); + let (is_device_desc_succ, is_device_desc_not_found) = + check_read_buf(device_desc_file_path.as_str(), &device_desc_r); + let (is_device_sec_succ, is_device_sec_not_found) = + check_read_buf(device_sec_file_path.as_str(), &device_sec_r); + + if is_people_desc_succ + && is_people_sec_succ + && is_device_desc_succ + && is_device_sec_succ + { + // decode + let people_desc = People::raw_decode(people_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_desc_file_path).as_str()) + .0; + let people_sec = PrivateKey::raw_decode(people_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_sec_file_path).as_str()) + .0; + let device_desc = Device::raw_decode(device_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_desc_file_path).as_str()) + .0; + let device_sec = PrivateKey::raw_decode(device_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_sec_file_path).as_str()) + .0; + members.push(((people_desc, people_sec), (device_desc, device_sec))); + } else if is_people_desc_not_found + && is_people_sec_not_found + && is_device_desc_not_found + && is_device_sec_not_found + { + // create & save + let member = create_member(name_prefix, index, min_port + i as u16); + fs::write( + people_desc_file_path.as_str(), + member.0 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", people_desc_file_path).as_str()); + fs::write(people_sec_file_path.as_str(), member.0 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", people_sec_file_path).as_str()); + fs::write( + device_desc_file_path.as_str(), + member.1 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", device_desc_file_path).as_str()); + fs::write(device_sec_file_path.as_str(), member.1 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", device_sec_file_path).as_str()); + + members.push(member); + } else { + println!("read members failed!"); + std::process::exit(-1); + } + } + + members + } + + pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/admins", "admin", 4).await + } + + pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/members", "member", 9).await + } + + pub async fn init_group( + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + fs::create_dir_all("./test-group") + .await + .expect("create dir ./test-group failed"); + + let read_group_r = fs::read("./test-group/group.desc").await; + match read_group_r { + Ok(buf) => { + if buf.len() > 0 { + return Group::raw_decode(buf.as_slice()) + .expect("decode ./test-group/group.desc failed") + .0; + } + } + Err(err) => { + if ErrorKind::NotFound != err.kind() { + println!("read group failed: {:?}", err); + std::process::exit(-1); + } + } + } + + let group = create_group(admins.get(0).unwrap(), admins, members, oods); + fs::write("./test-group/group.desc", group.to_vec().unwrap()) + .await + .expect("save file ./test-group/group.desc failed"); + group + } + fn init_stack_params( people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); - let mut member_device: Vec = - EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); + let mut admin_device: Vec = admins.iter().map(|m| m.1.clone()).collect(); + let mut member_device: Vec = members.iter().map(|m| m.1.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { @@ -242,7 +387,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { + for (member, device) in admins.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -260,7 +405,7 @@ mod Common { )); } - for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { + for (member, device) in members.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -279,17 +424,17 @@ mod Common { } known_objects.list.push(NONObjectInfo::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_GROUP.to_vec().unwrap(), + group.desc().object_id(), + group.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( - EXAMPLE_GROUP.clone(), + group.clone(), )))), )); - let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( - EXAMPLE_DEC_APP.desc().object_id(), + dec_app.desc().object_id(), dec_app_vec, Some(Arc::new(AnyNamedObject::Core(typeless))), )); @@ -301,8 +446,13 @@ mod Common { people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> CyfsStack { - let params = init_stack_params(people, private_key, device); + let params = + init_stack_params(people, private_key, device, admins, members, group, dec_app); log::info!("cyfs-stack.open"); @@ -316,10 +466,6 @@ mod Common { stack } - - pub fn dummy(people: People, device: Device) { - log::info!("common::dummy"); - } } mod Client { @@ -352,22 +498,21 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + GroupProposalObject, }; use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; use cyfs_stack::CyfsStack; - use crate::Common::EXAMPLE_DEC_APP_ID; - pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { let group_mgr = cyfs_stack.group_mgr(); group_mgr .register( - EXAMPLE_DEC_APP_ID.clone(), + dec_app_id.clone(), Box::new(GroupRPathDelegateFactory { local_name }), ) .await @@ -575,13 +720,14 @@ mod GroupDecService { } } -fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { +fn create_proposal( + delta: u64, + owner: ObjectId, + group_id: ObjectId, + dec_id: ObjectId, +) -> GroupProposal { GroupProposal::create( - GroupRPath::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id().clone(), - EXAMPLE_RPATH.clone(), - ), + GroupRPath::new(group_id, dec_id, EXAMPLE_RPATH.to_string()), "add".to_string(), Some(Vec::from(delta.to_be_bytes())), None, @@ -614,23 +760,57 @@ async fn main_run() { log::info!("will open stacks"); + let admins = init_admins().await; + let members = init_members().await; + let group = init_group( + admins.iter().map(|m| &m.0 .0).collect(), + members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| &m.1 .0).collect(), + ) + .await; + let group_id = group.desc().object_id(); + let dec_app = DecApp::create( + admins.get(0).unwrap().0 .0.desc().object_id(), + EXAMPLE_APP_NAME.as_str(), + ); + let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); + let mut admin_stacks: Vec = vec![]; - for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { - // dummy(admin.clone(), device.clone()); - let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; + for ((admin, _), (device, private_key)) in admins.iter() { + let cyfs_stack = create_stack( + admin.clone(), + private_key, + device.clone(), + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + group.clone(), + dec_app.clone(), + ) + .await; admin_stacks.push(cyfs_stack); } for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); - DecService::run(&stack, admin.name().unwrap().to_string()).await; + let ((admin, _), _) = admins.get(i).unwrap(); + DecService::run( + &stack, + admin.name().unwrap().to_string(), + dec_app_id.clone(), + ) + .await; let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group.desc().object_id(), + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -647,14 +827,19 @@ async fn main_run() { let PROPOSAL_COUNT = 1000usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; - let proposal = create_proposal(i as u64, owner.desc().object_id()); + let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let proposal = create_proposal( + i as u64, + owner.desc().object_id(), + group_id, + dec_app_id.object_id().clone(), + ); let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -676,7 +861,7 @@ async fn main_run() { zone: None, zone_category: DeviceZoneCategory::CurrentDevice, }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + dec: dec_app_id.object_id().clone(), verified: None, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), @@ -700,8 +885,8 @@ async fn main_run() { let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) From f6288fca9060bd8f90614682b71e843512d85826 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 17:36:21 +0800 Subject: [PATCH 209/553] fix: path error --- .../src/statepath/group_statepath.rs | 13 ++++++++-- src/tests/group-example/src/main.rs | 26 +++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eade0f9e4..280fb6948 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -39,51 +39,60 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_GROUP_BLOB, ]), last_vote_round: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), range: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_RANGE, ]), prepares: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PREPARES, ]), pre_commits: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PRE_COMMITS, ]), finish_proposals: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, ]), flip_time: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_FLIP_TIME, ]), recycle: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_RECYCLE, ]), adding: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e7948f740..e29b1be6d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -337,13 +337,13 @@ mod Common { } fn init_stack_params( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -443,13 +443,13 @@ mod Common { } pub async fn create_stack( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> CyfsStack { let params = init_stack_params(people, private_key, device, admins, members, group, dec_app); @@ -778,9 +778,9 @@ async fn main_run() { let mut admin_stacks: Vec = vec![]; for ((admin, _), (device, private_key)) in admins.iter() { let cyfs_stack = create_stack( - admin.clone(), + admin, private_key, - device.clone(), + device, admins .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) @@ -789,8 +789,8 @@ async fn main_run() { .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) .collect(), - group.clone(), - dec_app.clone(), + &group, + &dec_app, ) .await; admin_stacks.push(cyfs_stack); @@ -898,7 +898,7 @@ async fn main_run() { }); if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(200)).await; + async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } From 421577f17af878fa7f74a250e49572e8d01d399c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 18:34:11 +0800 Subject: [PATCH 210/553] fix: commit storage --- src/component/cyfs-group/src/storage/group_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 5ad19ea15..30fc08cad 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -398,6 +398,7 @@ impl GroupStorage { writer .set_last_vote_round(round, self.cache.last_vote_round) .await?; + writer.commit().await?; self.cache.last_vote_round = round; From 9863115f4cb1d8931f75aaa822c964ed02f8bc81 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 211/553] fix: type of pre-commits --- .../cyfs-group/src/dec/group_manager.rs | 21 ++++++++++--------- .../engine/storage_engine_group_state.rs | 20 +++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5ecfcdba2..7ba376368 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,16 +289,17 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - let rpath = header_block.r_path(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::StateChangeNotify(header_block, qc_block), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = header_block.r_path(); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::StateChangeNotify(header_block, qc_block), + // remote, + // ) + // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index ee429a78f..c6acb7b52 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,7 +5,6 @@ use cyfs_base::{ ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -213,9 +212,11 @@ impl StorageEngineGroupStateWriter { .await?; } - self.op_env - .insert_with_path(self.state_path.pre_commits(), block_id) - .await + let is_changed = self.op_env + .insert(self.state_path.pre_commits(), block_id) + .await?; + assert!(is_changed); + Ok(()) } async fn push_commit_inner( @@ -469,7 +470,16 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.prepare_map_id.is_none(), ) .await?; - self.op_env.commit().await.map(|_| ()) + self.op_env.commit().await.map_or_else( + |err| { + if err.code() == BuckyErrorCode::AlreadyExists { + Ok(()) + } else { + Err(err) + } + }, + |_| Ok(()), + ) } } From 5fac7fcf6a08ce1b187b7d107a3693acab805714 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:42:12 +0800 Subject: [PATCH 212/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e29b1be6d..316630f6a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: None, + isolate: Some(device.desc().object_id()), sync_service: false, shared_stack: false, }, From 6ed655fabaa58d37683037624376cff667478d16 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:49:08 +0800 Subject: [PATCH 213/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 316630f6a..d69fcae2d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: Some(device.desc().object_id()), + isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: false, }, From 5ea1a5340895534c4722679f3b2b7d5b9e9039c6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 21 Feb 2023 19:52:57 +0800 Subject: [PATCH 214/553] fix: the round for the first block when restart --- src/component/cyfs-core/src/coreobj.rs | 1 + .../src/group/group_quorum_certificate.rs | 144 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 2 + .../src/consensus/hotstuff/hotstuff.rs | 60 +++++++- .../cyfs-group/src/dec/group_manager.rs | 34 +++-- .../cyfs-group/src/network/non_driver.rs | 30 +++- .../cyfs-group/src/statepath/design.md | 1 + .../src/statepath/group_statepath.rs | 16 +- .../src/storage/engine/storage_engine.rs | 5 +- .../engine/storage_engine_group_state.rs | 130 ++++++++++++---- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 136 ++++++++++++----- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- src/tests/group-example/src/main.rs | 24 +-- 14 files changed, 493 insertions(+), 100 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_quorum_certificate.rs diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 724f0debb..30bf0e013 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupRPathStatus = 703, GroupAction = 704, + GroupQuorumCertificate = 705, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs new file mode 100644 index 000000000..7c3ad77fc --- /dev/null +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -0,0 +1,144 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, DescContent, EmptyBodyContent, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBuilder, NamedObjectId, RawDecode, RawEncode, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_RAW, +}; + +use crate::{CoreObjectType, HotstuffBlockQC, HotstuffTimeout}; + +#[derive(Clone)] +pub enum GroupQuorumCertificateDescContent { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), +} + +impl DescContent for GroupQuorumCertificateDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupQuorumCertificate as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupQuorumCertificateDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +pub type GroupQuorumCertificateType = + NamedObjType; +pub type GroupQuorumCertificateBuilder = + NamedObjectBuilder; + +pub type GroupQuorumCertificateId = NamedObjectId; +pub type GroupQuorumCertificate = NamedObjectBase; + +pub trait GroupQuorumCertificateObject { + fn quorum_round(&self) -> u64; +} + +impl GroupQuorumCertificateObject for GroupQuorumCertificate { + fn quorum_round(&self) -> u64 { + match self.desc().content() { + GroupQuorumCertificateDescContent::QC(qc) => qc.round, + GroupQuorumCertificateDescContent::TC(tc) => tc.round, + } + } +} + +impl RawEncode for GroupQuorumCertificateDescContent { + fn raw_measure( + &self, + purpose: &Option, + ) -> cyfs_base::BuckyResult { + let len = match self { + GroupQuorumCertificateDescContent::QC(qc) => qc.raw_measure(purpose)?, + GroupQuorumCertificateDescContent::TC(tc) => tc.raw_measure(purpose)?, + }; + + Ok(len + 1) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> cyfs_base::BuckyResult<&'a mut [u8]> { + match self { + GroupQuorumCertificateDescContent::QC(qc) => { + buf[0] = 0; + let buf = &mut buf[1..]; + qc.raw_encode(buf, purpose) + } + GroupQuorumCertificateDescContent::TC(tc) => { + buf[0] = 1; + let buf = &mut buf[1..]; + tc.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for GroupQuorumCertificateDescContent { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let obj_type = buf[0]; + let buf = &buf[1..]; + match obj_type { + 0 => { + let (qc, remain) = HotstuffBlockQC::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::QC(qc), remain)) + } + 1 => { + let (qc, remain) = HotstuffTimeout::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::TC(qc), remain)) + } + _ => Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown qc")), + } + } +} + +impl From for GroupQuorumCertificate { + fn from(qc: HotstuffBlockQC) -> Self { + let desc = GroupQuorumCertificateDescContent::QC(qc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl From for GroupQuorumCertificate { + fn from(tc: HotstuffTimeout) -> Self { + let desc = GroupQuorumCertificateDescContent::TC(tc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::QC(qc) => Ok(qc), + GroupQuorumCertificateDescContent::TC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is tc, expect qc")) + } + } + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::TC(tc) => Ok(tc), + GroupQuorumCertificateDescContent::QC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is qc, expect tc")) + } + } + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4c315c090..c153ab1ba 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,6 +1,7 @@ mod group_consensus_block; mod group_proposal; mod group_proposal_decide_param; +mod group_quorum_certificate; mod group_rpath; mod group_rpath_status; mod group_update_group_proposal_param; @@ -8,6 +9,7 @@ mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; pub use group_proposal_decide_param::*; +pub use group_quorum_certificate::*; pub use group_rpath::*; pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e89498b83..7868a7f90 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,7 +9,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; @@ -238,11 +238,36 @@ impl HotstuffRunner { rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); + let last_qc = store.last_qc(); + let (tc, qc) = last_qc + .as_ref() + .map_or((None, None), |qc| { + match qc.desc().content() { + cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), + cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), + } + }); - let round = store - .last_vote_round() - .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let last_vote_round = store + .last_vote_round(); + let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); + let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); + + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" + , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + + let max_round_qc_round = max_round_block + .as_ref() + .map_or(0, |block| + block.qc().as_ref().map_or(0, |qc| qc.round) + ); + let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); + let high_qc = if max_round_qc_round >= last_qc_round { + max_round_block.map_or(None, |b| b.qc().clone()) + } else { + qc + }; let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); @@ -277,7 +302,7 @@ impl HotstuffRunner { rpath, proposal_consumer, rx_proposal_waiter: None, - tc: None, + tc, state_pusher, tx_block_gen, rx_block_gen, @@ -627,6 +652,16 @@ impl HotstuffRunner { * 验证过的块执行这个函数 */ + if let Err(err) = self.non_driver.put_block(block).await { + if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + log::warn!( + "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", + self, block.block_id(), block.height(), block.round() + ); + return Err(err); + } + } + log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", self, block.block_id(), block.height(), block.round() @@ -1072,6 +1107,10 @@ impl HotstuffRunner { let qc_round = qc.round; let qc_prev_block_id = qc.prev_block_id; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); + + self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.process_qc(&Some(qc)).await; let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { @@ -1211,10 +1250,14 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", @@ -1324,6 +1367,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1814,6 +1861,7 @@ impl HotstuffRunner { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id + && max_round_block.round() == self.round && latest_group.is_ok() && last_group.is_ok() && last_group diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7ba376368..70fb10ba6 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -302,22 +302,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.r_path(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); @@ -397,6 +398,7 @@ impl GroupManager { return Err(e); } if let BuckyErrorCode::NotFound = e.code() { + log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); None } else { return Err(e); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4212a0355..979451b79 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,7 +7,9 @@ use cyfs_base::{ TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, +}; use cyfs_lib::NONObjectInfo; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -106,6 +108,32 @@ impl NONDriverHelper { Ok(()) } + pub async fn get_qc( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupQuorumCertificate::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn put_qc(&self, qc: &GroupQuorumCertificate) -> BuckyResult<()> { + let buf = qc.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let qc = NONObjectInfo { + object_id: qc.desc().object_id(), + object_raw: qc.to_vec()?, + object: Some(block_any), + }; + self.put_object(qc).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 70a61e428..cb964e066 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -23,6 +23,7 @@ | | |--${user-id} | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 280fb6948..0e6a887b0 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -5,6 +5,7 @@ pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -23,10 +24,12 @@ lazy_static::lazy_static! { pub struct GroupStatePath { rpath: String, + root: String, dec_state: String, link: String, group_blob: String, last_vote_round: String, + last_qc: String, range: String, prepares: String, pre_commits: String, @@ -39,6 +42,7 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { + root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ @@ -53,6 +57,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), + last_qc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_QC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -107,7 +117,7 @@ impl GroupStatePath { } pub fn root(&self) -> &str { - self.rpath.as_str() + self.root.as_str() } pub fn dec_state(&self) -> &str { @@ -126,6 +136,10 @@ impl GroupStatePath { self.last_vote_round.as_str() } + pub fn last_qc(&self) -> &str { + self.last_qc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index 735277a3a..aebf6fb96 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,6 +12,7 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub last_qc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -33,6 +34,7 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, + last_qc: None, } } } @@ -58,6 +60,7 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index c6acb7b52..2b61dbc47 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, }; use crate::{ @@ -27,26 +27,35 @@ impl StorageEngineGroupState { non_driver: &NONDriverHelper, state_path: &GroupStatePath, ) -> BuckyResult { - let op_env = state_mgr.create_op_env(ACCESS)?; - - let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; - - let last_vote_round = op_env - .get_by_path(state_path.last_vote_round()) - .await? - .map(|id| parse_u64_obj(&id)); + let op_env = state_mgr.create_op_env(ACCESS).map_err(|err| { + log::warn!("create_op_env failed {:?}", err); + err + })?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await; + let dec_state_id = map_not_found_option_to_option(dec_state_id)?; + + let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; + let last_vote_round = + map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; + let last_qc = map_not_found_option_to_option(last_qc)?; + let last_qc = match last_qc.as_ref() { + Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + None => None, + }; let mut first_header_block_ids: Vec = vec![]; - let commit_range = op_env - .get_by_path(state_path.range()) - .await? - .map(|id| parse_range_obj(&id)); + let commit_range = op_env.get_by_path(state_path.range()).await; + let commit_range = + map_not_found_option_to_option(commit_range)?.map(|id| parse_range_obj(&id)); let commit_block = match commit_range { Some((first_height, header_height)) => { let first_block_id = op_env .get_by_path(state_path.commit_height(first_height).as_str()) - .await? - .expect("first block is lost"); + .await; + let first_block_id = + map_not_found_option_to_option(first_block_id)?.expect("first block is lost"); first_header_block_ids.push(first_block_id); if header_height == first_height { @@ -54,7 +63,8 @@ impl StorageEngineGroupState { } else { let header_block_id = op_env .get_by_path(state_path.commit_height(header_height).as_str()) - .await? + .await; + let header_block_id = map_not_found_option_to_option(header_block_id)? .expect("first block is lost"); first_header_block_ids.push(header_block_id); Some((first_block_id, header_block_id)) @@ -64,13 +74,27 @@ impl StorageEngineGroupState { }; let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + if prepare_block_ids.len() == 0 && commit_range.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "not found in storage", + )); + } + let pre_commit_block_ids = load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; - let flip_timestamp = op_env - .get_by_path(state_path.flip_time()) - .await? - .map_or(0, |id| parse_u64_obj(&id)); + let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; + let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { + let n = parse_u64_obj(&id); + // log::debug!( + // "load flip timestamp {}/{} -> {}", + // id, + // id.to_hex().unwrap(), + // n + // ); + n + }); let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; @@ -82,15 +106,18 @@ impl StorageEngineGroupState { ] .concat(); - let load_blocks = futures::future::join_all( - load_block_ids - .iter() - .map(|id| non_driver.get_block(id, None)), - ) + let load_blocks = futures::future::join_all(load_block_ids.iter().map(|id| async { + let id = id.clone(); + non_driver.get_block(&id, None).await.map_err(|err| { + log::warn!("get block {} failed {:?}", id, err); + err + }) + })) .await; let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.last_qc = last_qc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -212,7 +239,8 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self.op_env + let is_changed = self + .op_env .insert(self.state_path.pre_commits(), block_id) .await?; assert!(is_changed); @@ -326,6 +354,15 @@ impl StorageEngineGroupStateWriter { let timestamp_obj = make_u64_obj(timestamp); if prev_timestamp != 0 { let prev_timestamp_obj = make_u64_obj(prev_timestamp); + // log::debug!( + // "will update flip-time from {} -> {}/{} to {} -> {}/{}", + // prev_timestamp, + // prev_timestamp_obj, + // prev_timestamp_obj.to_hex().unwrap(), + // timestamp, + // timestamp_obj, + // timestamp_obj.to_hex().unwrap(), + // ); let prev_value = self .op_env .set_with_path( @@ -337,6 +374,7 @@ impl StorageEngineGroupStateWriter { .await?; assert_eq!(prev_value.unwrap(), prev_timestamp_obj); } else { + // log::debug!("will update flip-time from None to {}", timestamp); self.op_env .insert_with_key( self.state_path.finish_proposals(), @@ -395,6 +433,13 @@ impl StorageEngineGroupStateWriter { Ok(()) } } + + async fn save_last_qc_inner(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_qc(), qc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -458,6 +503,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_qc_inner(qc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; @@ -522,6 +573,7 @@ async fn load_object_ids_with_path( let content = match op_env.list(full_path).await { Ok(content) => content, Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); if err.code() == BuckyErrorCode::NotFound { return Ok(vec![]); } else { @@ -546,3 +598,29 @@ async fn load_object_ids_with_path( Ok(object_ids) } + +fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { + match r { + Ok(t) => Ok(Some(t)), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} + +fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult> { + match r { + Ok(t) => Ok(t), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b944d3735..79491b186 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -192,6 +192,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 30fc08cad..3f9fc9910 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -8,7 +8,10 @@ use cyfs_base::{ ObjectDesc, ObjectId, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupQuorumCertificateObject, HotstuffTimeout, +}; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ @@ -20,7 +23,7 @@ use super::{ StorageEngine, }; -const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; +const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() as u64; pub enum BlockLinkState { Expired, @@ -96,16 +99,32 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver.get_group(group_id, None, None).await?; + let group = non_driver + .get_group(group_id, None, None) + .await + .map_err(|err| { + log::warn!("get group {} from noc failed {:?}", group_id, err); + err + })?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) - .await? + .await + .map_err(|err| { + log::warn!("load root state for group {} failed {:?}", group_id, err); + err + })? .expect("create group state failed."); - let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state + .get_dec_root_manager(dec_id, true) + .await + .map_err(|err| { + log::warn!("get root state manager for dec {} failed {:?}", dec_id, err); + err + })?; let state_path = GroupStatePath::new(rpath.to_string()); let cache = @@ -120,7 +139,7 @@ impl GroupStorage { group_chunk_id: group_chunk_id.object_id(), storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, - cache: cache, + cache, }) } @@ -286,24 +305,33 @@ impl GroupStorage { writer.remove_prepares(remove_prepares.as_slice()).await?; - let finish_proposals: Vec = new_header - .proposals() - .iter() - .map(|p| p.proposal.clone()) - .collect(); - - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { - writer - .push_proposals( - finish_proposals.as_slice(), - Some((timestamp, self.cache.finish_proposals.flip_timestamp)), - ) - .await?; - } else { - writer - .push_proposals(finish_proposals.as_slice(), None) - .await?; + if new_header.proposals().len() > 0 { + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + + let timestamp = new_header.named_object().desc().create_time(); + // log::debug!( + // "push proposals storage flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + writer + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), + ) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } } @@ -340,19 +368,28 @@ impl GroupStorage { self.cache.first_block = Some(new_header.clone()); } - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp - > PROPOSAL_MAX_TIMEOUT_AS_MS - { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); - self.cache.finish_proposals.flip_timestamp = timestamp; - } + if new_header.proposals().len() > 0 { + let timestamp = new_header.named_object().desc().create_time(); + + // log::debug!( + // "push proposals flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; + } - for proposal in new_header.proposals() { - let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); - assert!(is_new); + for proposal in new_header.proposals() { + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } } self.cache.header_block = Some(new_header); @@ -405,6 +442,33 @@ impl GroupStorage { Ok(()) } + pub fn last_qc(&self) -> &Option { + &self.cache.last_qc + } + + pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { + let quorum_round = qc.quorum_round(); + if quorum_round < self.cache.last_vote_round + || quorum_round + <= self + .cache + .last_qc + .as_ref() + .map_or(0, |qc| qc.quorum_round()) + { + return Ok(()); + } + + self.non_driver.put_qc(&qc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_qc(&qc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_qc = Some(qc); + Ok(()) + } + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { log::debug!( "[group storage] {} block_linked {} step1", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9414cda7c..fcb0dd6da 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, @@ -55,6 +55,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { } async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let access = AccessString::full(); + log::debug!("put object {} with access {}", obj.object_id, access); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { @@ -76,7 +78,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { flags: 0, }, object: obj, - access: None, // TODO access + access: Some(AccessString::full()), // TODO access }) .await .map(|_| ()) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d69fcae2d..b5b6f4ce4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,7 +1,8 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ - AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; @@ -23,8 +24,8 @@ mod Common { AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, - TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, - SIGNATURE_SOURCE_REFINDEX_SELF, + TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -210,13 +211,12 @@ mod Common { save_path: &str, name_prefix: &str, count: usize, + min_port: u16, ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { fs::create_dir_all(save_path) .await .expect(format!("create dir {} failed", save_path).as_str()); - let min_port = 30217_u16; - let mut members = vec![]; for i in 0..count { @@ -296,11 +296,13 @@ mod Common { } pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/admins", "admin", 4).await + let min_port = 30217_u16; + init_member_from_dir("./test-group/admins", "admin", 4, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/members", "member", 9).await + let min_port = 31217_u16; + init_member_from_dir("./test-group/members", "member", 9, min_port).await } pub async fn init_group( @@ -369,7 +371,7 @@ mod Common { }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { - bdt_listeners: vec![], + bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], tcp_listeners: vec![], ws_listener: None, }, @@ -868,7 +870,7 @@ async fn main_run() { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: Some(AccessString::full().value()), }; noc.put_object(&req).await; proposals.push(proposal); @@ -878,8 +880,8 @@ async fn main_run() { log::info!("proposals prepared."); - for i in 0..(PROPOSAL_COUNT - 1) { - let proposal = proposals.get(i).unwrap().clone(); + for i in 1..PROPOSAL_COUNT { + let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let control = stack From 17dda7929b2651ed8237beaec6537504411ed16b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 16:04:16 +0800 Subject: [PATCH 215/553] fix: first block with tc --- .../src/consensus/hotstuff/hotstuff.rs | 75 ++++++++++--------- .../src/statepath/group_statepath.rs | 12 +++ .../src/storage/engine/storage_engine.rs | 9 ++- .../engine/storage_engine_group_state.rs | 35 ++++++++- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 41 +++++++--- src/tests/group-example/src/main.rs | 2 + 7 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7868a7f90..a2a5e8f70 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -239,36 +239,30 @@ impl HotstuffRunner { ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); - let (tc, qc) = last_qc - .as_ref() - .map_or((None, None), |qc| { - match qc.desc().content() { - cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), - cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), - } - }); + let last_tc = store.last_tc(); let last_vote_round = store .last_vote_round(); - let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); - let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); + let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); + let quorum_round = block_quorum_round.max(timeout_quorum_round); + let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" - , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" + , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); - let max_round_qc_round = max_round_block - .as_ref() - .map_or(0, |block| - block.qc().as_ref().map_or(0, |qc| qc.round) - ); - let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); - let high_qc = if max_round_qc_round >= last_qc_round { + let high_qc = if max_round_qc_round >= block_quorum_round { max_round_block.map_or(None, |b| b.qc().clone()) } else { - qc + last_qc.clone() }; + let tc = last_tc.clone(); + let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; @@ -954,18 +948,22 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && qc_round - >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; if !is_valid_round { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {:?}", self, block.block_id(), block.round(), qc_round, - block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + block.tc().as_ref().map_or((0, 0), |tc| { + let qc_round = tc.votes.iter().map(|v| v.high_qc_round).max().unwrap(); + (tc.round, qc_round) + })); return None; } @@ -1109,7 +1107,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); - self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.store.save_qc(&qc).await?; self.process_qc(&Some(qc)).await; @@ -1125,7 +1123,7 @@ impl HotstuffRunner { })?; if self.local_device_id == new_leader { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } Ok(()) } @@ -1251,12 +1249,12 @@ impl HotstuffRunner { max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( @@ -1367,9 +1365,9 @@ impl HotstuffRunner { err })?; - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1535,7 +1533,7 @@ impl HotstuffRunner { self.remove_pending_proposals(remove_proposals).await; if self - .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .try_wait_proposals(executed_proposals.len(), &prev_block) .await { log::debug!( @@ -1739,12 +1737,12 @@ impl HotstuffRunner { async fn try_wait_proposals( &mut self, - executed_proposals: &[(GroupProposal, ExecuteResult)], + proposal_count: usize, pre_block: &Option, ) -> bool { // empty block, qc only, it's unuseful when no block to qc let mut will_wait_proposals = false; - if executed_proposals.len() == 0 { + if proposal_count == 0 { match pre_block.as_ref() { None => { log::warn!( @@ -1814,14 +1812,17 @@ impl HotstuffRunner { assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); - let tc = self.tc.as_ref().map_or(None, |tc| { + self.generate_block(self.with_tc()).await + } + + fn with_tc(&self) -> Option { + self.tc.as_ref().map_or(None, |tc| { if tc.round + 1 == self.round { Some(tc.clone()) } else { None } - }); - self.generate_block(tc).await + }) } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { @@ -1876,7 +1877,7 @@ impl HotstuffRunner { ); } _ => { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } } } diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0e6a887b0..72f48e601 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -6,6 +6,7 @@ pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; +pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -30,6 +31,7 @@ pub struct GroupStatePath { group_blob: String, last_vote_round: String, last_qc: String, + last_tc: String, range: String, prepares: String, pre_commits: String, @@ -63,6 +65,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_QC, ]), + last_tc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_TC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -140,6 +148,10 @@ impl GroupStatePath { self.last_qc.as_str() } + pub fn last_tc(&self) -> &str { + self.last_tc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index aebf6fb96..c4803d6ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,7 +12,8 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 - pub last_qc: Option, + pub last_qc: Option, + pub last_tc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -25,6 +26,8 @@ impl StorageCacheInfo { Self { dec_state_id: init_state_id, last_vote_round: 0, + last_qc: None, + last_tc: None, header_block: None, first_block: None, prepares: HashMap::new(), @@ -34,7 +37,6 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, - last_qc: None, } } } @@ -61,6 +63,7 @@ pub trait StorageWriter: Send + Sync { async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 2b61dbc47..b3a01fd60 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -38,10 +39,26 @@ impl StorageEngineGroupState { let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; let last_vote_round = map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; let last_qc = map_not_found_option_to_option(last_qc)?; let last_qc = match last_qc.as_ref() { - Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + Some(qc_id) => non_driver + .get_qc(qc_id, None) + .await? + .try_into() + .map_or(None, |qc| Some(qc)), + None => None, + }; + + let last_tc = op_env.get_by_path(state_path.last_tc()).await; + let last_tc = map_not_found_option_to_option(last_tc)?; + let last_tc = match last_tc.as_ref() { + Some(tc_id) => non_driver + .get_qc(tc_id, None) + .await? + .try_into() + .map_or(None, |tc| Some(tc)), None => None, }; @@ -118,6 +135,7 @@ impl StorageEngineGroupState { let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); cache.last_qc = last_qc; + cache.last_tc = last_tc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -440,6 +458,13 @@ impl StorageEngineGroupStateWriter { .await .map(|_| ()) } + + async fn save_last_tc_inner(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_tc(), tc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -509,6 +534,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_tc_inner(tc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 79491b186..ebeedd7ca 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -196,6 +196,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3f9fc9910..ee2618cde 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -10,7 +10,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffTimeout, + GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; @@ -442,30 +442,49 @@ impl GroupStorage { Ok(()) } - pub fn last_qc(&self) -> &Option { + pub fn last_qc(&self) -> &Option { &self.cache.last_qc } - pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { - let quorum_round = qc.quorum_round(); + pub async fn save_qc(&mut self, qc: &HotstuffBlockQC) -> BuckyResult<()> { + let quorum_round = qc.round; if quorum_round < self.cache.last_vote_round - || quorum_round - <= self - .cache - .last_qc - .as_ref() - .map_or(0, |qc| qc.quorum_round()) + || quorum_round <= self.cache.last_qc.as_ref().map_or(0, |qc| qc.round) { return Ok(()); } + let qc = GroupQuorumCertificate::from(qc.clone()); self.non_driver.put_qc(&qc).await?; let mut writer = self.storage_engine.create_writer().await?; writer.save_last_qc(&qc.desc().object_id()).await?; writer.commit().await?; - self.cache.last_qc = Some(qc); + self.cache.last_qc = Some(qc.try_into().unwrap()); + Ok(()) + } + + pub fn last_tc(&self) -> &Option { + &self.cache.last_tc + } + + pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + let quorum_round = tc.round; + if quorum_round < self.cache.last_vote_round + || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) + { + return Ok(()); + } + + let tc = GroupQuorumCertificate::from(tc.clone()); + self.non_driver.put_qc(&tc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_tc(&tc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_tc = Some(tc.try_into().unwrap()); Ok(()) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b5b6f4ce4..2ba99716e 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -798,6 +798,8 @@ async fn main_run() { admin_stacks.push(cyfs_stack); } + async_std::task::sleep(Duration::from_millis(10000)).await; + for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); From ebe0623f84daf523f28a1e33df5af4fef513c34a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:23:03 +0800 Subject: [PATCH 216/553] prepare for verify --- .../cyfs-core/protos/core_objects.proto | 14 -- src/component/cyfs-core/src/coreobj.rs | 1 - .../src/group/group_consensus_block.rs | 23 +++ .../cyfs-core/src/group/group_rpath_status.rs | 17 --- src/component/cyfs-core/src/group/mod.rs | 2 - .../protos/group_bft_protocol.proto | 6 + src/component/cyfs-group/src/crypto/crypto.rs | 14 -- src/component/cyfs-group/src/crypto/mod.rs | 3 - .../cyfs-group/src/dec/group_manager.rs | 35 +++-- .../src/dec_state/dec_state_requestor.rs | 32 ++-- src/component/cyfs-group/src/helper/verify.rs | 6 +- src/component/cyfs-group/src/lib.rs | 2 - .../src/objects/group_rpath_status.rs | 89 +++++++++++ src/component/cyfs-group/src/objects/mod.rs | 2 + .../cyfs-group/src/objects/protocol.rs | 140 +++++++++++++----- .../cyfs-group/src/storage/dec_storage.rs | 6 +- 16 files changed, 259 insertions(+), 133 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs delete mode 100644 src/component/cyfs-group/src/crypto/crypto.rs delete mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/objects/group_rpath_status.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 164c6bcd6..487ece4bd 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -431,20 +431,6 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } -message GroupRPathSubStatus { - string sub_path = 1; - repeated bytes state_id = 2; // for set -} - -message GroupRPathStatusDescContent { - bytes block_id = 1; - optional bytes sub_status_hash = 2; -} - -message GroupRPathStatusBodyContent { - repeated GroupRPathSubStatus sub_status = 1; -} - message GroupActionDescContent { // target GroupRPath r_path = 1; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 30bf0e013..3d53a082f 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -64,7 +64,6 @@ pub enum CoreObjectType { GroupProposal = 700, GroupUpdateGroup = 701, GroupConsensusBlock = 702, - GroupRPathStatus = 703, GroupAction = 704, GroupQuorumCertificate = 705, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 5d6d114c0..35c418552 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -38,6 +38,28 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } +impl GroupConsensusBlockDescContent { + pub fn rpath(&self) -> &GroupRPath { + &self.r_path + } + + pub fn result_state_id(&self) -> &Option { + &self.result_state_id + } + + pub fn height(&self) -> u64 { + self.height + } + + pub fn round(&self) -> u64 { + self.round + } + + pub fn group_chunk_id(&self) -> &ObjectId { + &self.group_chunk_id + } +} + #[derive(Clone, ProtobufTransformType)] #[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] pub struct HotstuffBlockQCSign { @@ -175,6 +197,7 @@ impl BodyContent for GroupConsensusBlockBodyContent { } } +pub type GroupConsensusBlockDesc = NamedObjectDesc; type GroupConsensusBlockType = NamedObjType; type GroupConsensusBlockBuilder = diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs deleted file mode 100644 index c55c41243..000000000 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::atomic::{AtomicU8, Ordering}; - -use crate::CoreObjectType; -use cyfs_base::*; -use serde::Serialize; -use sha2::Digest; - -// TODO: 后面再封装这个对象 -#[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus { - pub value_object_id: ObjectId, - pub block_id: ObjectId, - pub qc_block_id: ObjectId, -} - -#[cfg(test)] -mod test {} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index c153ab1ba..b2885d637 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -3,7 +3,6 @@ mod group_proposal; mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_rpath_status; mod group_update_group_proposal_param; pub use group_consensus_block::*; @@ -11,5 +10,4 @@ pub use group_proposal::*; pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 6ed8c3afe..621186522 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -15,3 +15,9 @@ message HotstuffTimeoutVote { bytes voter = 3; bytes signature = 4; } + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs deleted file mode 100644 index 9949f7a67..000000000 --- a/src/component/cyfs-group/src/crypto/crypto.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cyfs_base::{HashValue, ObjectId, Signature}; - -#[derive(Clone)] -pub struct Crypto {} - -impl Crypto { - pub fn sign(&self, hash: &HashValue) -> Signature { - unimplemented!() - } - - pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs deleted file mode 100644 index 066e79b6b..000000000 --- a/src/component/cyfs-group/src/crypto/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod crypto; - -pub use crypto::*; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 70fb10ba6..2f2229890 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,7 +289,7 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - // TODO: 暂时不实现 + // TODO: unimplemented // let rpath = header_block.r_path(); // let client = self // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) @@ -302,23 +302,22 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - // TODO: 暂时不实现 - // let rpath = result.as_ref().map_or_else( - // |(_, target)| target.check_rpath(), - // |(_, block, _)| block.r_path(), - // ); - // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - // .await?; - // client - // .on_message( - // HotstuffMessage::ProposalResult( - // proposal_id, - // result.map_err(|(err, _)| err), - // ), - // remote, - // ) - // .await; + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) + .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e30c0a5a7..369b3db6e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,10 +3,13 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; -use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; +use crate::{ + helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + CHANNEL_CAPACITY, +}; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -143,7 +146,7 @@ impl DecStateRequestorRunner { let result = self .verify_verifiable_state(sub_path.as_str(), &result, &remote) .await - .map(|_| result.value_object_id); + .map(|_| unimplemented!()); // TODO: 搜索目标值 self.query_state_notifier.reply(&sub_path, result).await } @@ -157,25 +160,22 @@ impl DecStateRequestorRunner { result: &GroupRPathStatus, remote: &ObjectId, ) -> BuckyResult<()> { - let header_block = self - .non_driver - .get_block(&result.block_id, Some(remote)) - .await?; - let qc_block = self - .non_driver - .get_block(&result.qc_block_id, Some(remote)) - .await?; + // let header_block = self + // .non_driver + // .get_block(&result.block_id, Some(remote)) + // .await?; + // let qc_block = self + // .non_driver + // .get_block(&result.qc_block_id, Some(remote)) + // .await?; - let qc = match qc_block.qc() { - Some(qc) => qc, - None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), - }; + let qc = &result.certificate; let group = self .non_driver .get_group( self.rpath.group_id(), - Some(header_block.group_chunk_id()), + Some(result.block_desc.content().group_chunk_id()), Some(&remote), ) .await?; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 2a384d1cf..b8ab12b69 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; + +use crate::GroupRPathStatus; pub async fn verify_block( block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index fefe3f808..ba8e83569 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -1,6 +1,5 @@ mod consensus; mod constant; -mod crypto; mod dec; mod dec_state; mod helper; @@ -12,7 +11,6 @@ mod utils; pub use consensus::*; pub use constant::*; -pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs new file mode 100644 index 000000000..f266d3dbd --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use cyfs_base::*; +use cyfs_core::{GroupConsensusBlockDesc, HotstuffBlockQC}; +use cyfs_lib::NONObjectInfo; +use prost::Message; + +#[derive(Clone)] +pub struct GroupRPathStatus { + pub block_desc: GroupConsensusBlockDesc, + pub certificate: HotstuffBlockQC, + pub status_map: HashMap, +} + +impl RawEncode for GroupRPathStatus { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + Ok(proto.encoded_len()) + } + + fn raw_encode<'a>( + &self, + mut buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + proto.encode_raw(&mut buf); + + Ok(buf) + } +} + +impl<'de> RawDecode<'de> for GroupRPathStatus { + fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + let (block_desc, remain) = + GroupConsensusBlockDesc::raw_decode(proto.block_desc.as_slice())?; + assert_eq!(remain.len(), 0); + let (certificate, remain) = HotstuffBlockQC::raw_decode(proto.certificate.as_slice())?; + assert_eq!(remain.len(), 0); + let mut status_map = HashMap::new(); + for obj_buf in proto.status_list.iter() { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status_map.insert(status.object_id, status); + } + + Ok(( + Self { + block_desc, + certificate, + status_map, + }, + buf, + )) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs index d6de55d79..5d1a8b13f 100644 --- a/src/component/cyfs-group/src/objects/mod.rs +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -1,7 +1,9 @@ mod group_decide_proposal; +mod group_rpath_status; mod group_update_proposal; mod protocol; pub use group_decide_proposal::*; +pub use group_rpath_status::*; pub use group_update_proposal::*; pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 3e5f513df..6c9f89e96 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,16 +2,15 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } -use std::result; - use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; +use crate::GroupRPathStatus; + #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), @@ -163,20 +162,16 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::ProposalResult({}, {:?})", proposal_id, - result.as_ref().map_or_else( - |err| { Err(err) }, - |(obj, block, qc)| { - let ok = format!( - "({:?}, {}/{}, {}/{})", - obj.as_ref().map(|o| o.object_id), - block.block_id(), - block.round(), - qc.block_id(), - qc.round() - ); - Ok(ok) - } - ) + result.as_ref().map(|(obj, block, qc)| { + format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + }) ) } Self::QueryState(sub_path) => { @@ -187,7 +182,17 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map(|status| { + let desc = status.block_desc.content(); + format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ) + }) ) } } @@ -196,6 +201,7 @@ impl std::fmt::Debug for HotstuffMessage { const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; +const PACKAGE_FLAG_QUERY_STATE_RESULT_OK: u8 = 0x80u8; #[derive(Clone)] pub(crate) enum HotstuffPackage { @@ -220,7 +226,10 @@ pub(crate) enum HotstuffPackage { >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, String, BuckyResult), + VerifiableState( + String, + Result, + ), } impl std::fmt::Debug for HotstuffPackage { @@ -296,12 +305,26 @@ impl std::fmt::Debug for HotstuffPackage { Self::QueryState(_, sub_path) => { write!(f, "HotstuffPackage::QueryState({})", sub_path) } - Self::VerifiableState(_, sub_path, result) => { + Self::VerifiableState(sub_path, result) => { write!( f, "HotstuffPackage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |status| { + let desc = status.block_desc.content(); + let ok = format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ); + Ok(ok) + } + ) ) } } @@ -323,7 +346,10 @@ impl HotstuffPackage { |(_, block, _)| block.r_path(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), - HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |status| status.block_desc.content().rpath(), + ), } } } @@ -399,10 +425,14 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::QueryState(addr, sub_path) => { addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { - 2 + addr.raw_measure(purpose)? - + sub_path.raw_measure(purpose)? - + result.raw_measure(purpose)? + HotstuffPackage::VerifiableState(sub_path, result) => { + sub_path.raw_measure(purpose)? + + match result { + Ok(status) => status.raw_measure(purpose)?, + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } } }; @@ -459,7 +489,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; if result.is_ok() { - buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + buf[0] |= PACKAGE_FLAG_PROPOSAL_RESULT_OK; } let buf = &mut buf[1..]; @@ -482,12 +512,20 @@ impl RawEncode for HotstuffPackage { let buf = sub_path.raw_encode(buf, purpose)?; addr.raw_encode(buf, purpose) } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { + HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; + if result.is_ok() { + buf[0] |= PACKAGE_FLAG_QUERY_STATE_RESULT_OK; + } let buf = &mut buf[1..]; - let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = sub_path.raw_encode(buf, purpose)?; - result.raw_encode(buf, purpose) + match result { + Ok(status) => status.raw_encode(buf, purpose), + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } } } } @@ -502,24 +540,28 @@ impl<'de> RawDecode<'de> for HotstuffPackage { 0 => { let buf = &buf[1..]; let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { @@ -527,17 +569,20 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } 7 => { @@ -549,6 +594,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), buf, @@ -557,6 +603,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { false => { let (err, buf) = BuckyError::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } } @@ -565,17 +612,29 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let buf = &buf[1..]; let (sub_path, buf) = String::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } 9 => { + let is_ok = (buf[0] & PACKAGE_FLAG_QUERY_STATE_RESULT_OK) != 0; let buf = &buf[1..]; - let (addr, buf) = decode_with_length(buf, 3)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (result, buf) = BuckyResult::::raw_decode(buf)?; - Ok(( - HotstuffPackage::VerifiableState(addr, sub_path, result), - buf, - )) + match is_ok { + true => { + let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok(( + HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), + buf, + )) + } + } } _ => unreachable!("unknown protocol"), } @@ -613,9 +672,10 @@ impl HotstuffPackage { HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) } - HotstuffMessage::VerifiableState(sub_path, result) => { - HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) - } + HotstuffMessage::VerifiableState(sub_path, result) => HotstuffPackage::VerifiableState( + sub_path, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ), } } } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 12e3629d8..cce00e736 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use async_std::sync::RwLock; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; +use cyfs_core::GroupConsensusBlock; + +use crate::GroupRPathStatus; #[derive(Clone)] pub struct DecStorageCache { @@ -11,8 +13,6 @@ pub struct DecStorageCache { pub qc_block: GroupConsensusBlock, } -// TODO: storage - #[derive(Clone)] pub struct DecStorage { cache: Arc>>, From a1d1ebde8360ef99e7d7df3114abf2a7b1b9102a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:28:28 +0800 Subject: [PATCH 217/553] compile --- .../cyfs-group/src/dec/group_manager.rs | 12 +++++++++--- .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 14 +++++++++----- src/component/cyfs-group/src/helper/verify.rs | 16 +++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 2f2229890..0d863e17b 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -328,13 +328,19 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - HotstuffPackage::VerifiableState(target, sub_path, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::VerifiableState(sub_path, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |status| status.block_desc.content().rpath(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .on_message( + HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), + remote, + ) .await; } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 369b3db6e..b5c3b107e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -180,7 +180,7 @@ impl DecStateRequestorRunner { ) .await?; - if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { Err(BuckyError::new( BuckyErrorCode::InvalidSignature, "verify failed", diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f33ec5fa..73afb0ad0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -315,10 +315,7 @@ impl DecStateSynchronizerRunner { remote: ObjectId, ) -> BuckyResult<()> { if qc_block.qc().is_none() { - log::warn!( - "the qc is none for qc-block({})", - qc_block.block_id() - ); + log::warn!("the qc is none for qc-block({})", qc_block.block_id()); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } @@ -365,7 +362,14 @@ impl DecStateSynchronizerRunner { } }; - if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + if header_block.check() + && verify_block( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + &group.1, + ) + .await? + { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index b8ab12b69..759bf2c4a 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,15 +1,17 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, +}; use crate::GroupRPathStatus; pub async fn verify_block( - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.block_id().object_id(); - if qc.round != block.round() || &qc.block_id != block_id { + let block_id = block_desc.object_id(); + if qc.round != block_desc.content().round() || qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, @@ -18,17 +20,13 @@ pub async fn verify_block( return Ok(false); } - if !block.check() { - return Ok(false); - } - unimplemented!() } pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { From c02f7323c4304a45c37d5d0c95ecfe9fda027dc2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 23 Feb 2023 21:02:07 +0800 Subject: [PATCH 218/553] Verify the value on sub-path from anyone OOD in group --- .../src/consensus/hotstuff/hotstuff.rs | 28 ++++- .../src/consensus/vote/committee.rs | 66 ++++++++++- .../cyfs-group/src/dec/group_manager.rs | 54 ++++++--- .../cyfs-group/src/dec/rpath_client.rs | 34 ++++-- .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../src/dec_state/dec_state_requestor.rs | 73 ++++++------ .../src/dec_state/dec_state_synchronizer.rs | 80 ++++++-------- src/component/cyfs-group/src/helper/verify.rs | 18 --- .../src/objects/group_rpath_status.rs | 4 +- .../cyfs-group/src/storage/dec_storage.rs | 76 ++++++++++++- .../src/storage/engine/storage_engine.rs | 4 +- .../engine/storage_engine_group_state.rs | 23 +++- .../cyfs-group/src/storage/group_storage.rs | 104 +++++++++++++++++- src/component/cyfs-group/src/utils.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 15 files changed, 410 insertions(+), 166 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index a2a5e8f70..667966a6c 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -187,6 +187,19 @@ impl Hotstuff { self.state_pusher.request_last_state(remote).await; } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_query_state: sub_path: {}, remote: {:?},", + self, + sub_path, + remote + ); + + self.tx_message + .send((HotstuffMessage::QueryState(sub_path), remote)) + .await; + } } struct HotstuffRunner { @@ -1834,6 +1847,19 @@ impl HotstuffRunner { Ok(()) } + async fn handle_query_state(&self, sub_path: String, remote: ObjectId) -> BuckyResult<()> { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + + Ok(()) + } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; @@ -1918,7 +1944,7 @@ impl HotstuffRunner { Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), - Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d3fbd489c..ad3a21e35 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,9 +10,13 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { @@ -136,6 +140,47 @@ impl Committee { Ok(()) } + pub async fn verify_block_desc_with_qc( + &self, + block_desc: &GroupConsensusBlockDesc, + qc: &HotstuffBlockQC, + from: ObjectId, + ) -> BuckyResult<()> { + let block_id = block_desc.object_id(); + + log::debug!( + "[group committee] {} verify block desc {} step1", + self.local_device_id, + block_id + ); + + if block_id != qc.block_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the block id is unmatch with the qc", + )); + } + + self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + .await?; + + log::debug!( + "[group committee] {} verify block desc {} step2", + self.local_device_id, + block_id + ); + + self.verify_qc_with_desc(qc, block_desc.content()).await?; + + log::debug!( + "[group committee] {} verify block desc {} step3", + self.local_device_id, + block_id + ); + + Ok(()) + } + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { let hash = vote.hash(); let device = self.non_driver.get_device(&vote.voter).await?; @@ -250,8 +295,17 @@ impl Committee { qc: &HotstuffBlockQC, prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { - if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); + self.verify_qc_with_desc(qc, prev_block.named_object().desc().content()) + .await + } + + pub async fn verify_qc_with_desc( + &self, + qc: &HotstuffBlockQC, + prev_block_desc: &GroupConsensusBlockDescContent, + ) -> BuckyResult<()> { + if qc.round != prev_block_desc.round() { + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block_desc.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, "round not match in qc", @@ -261,7 +315,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block.group_chunk_id()), + Some(prev_block_desc.group_chunk_id()), ) .await?; @@ -291,7 +345,7 @@ impl Committee { .map_or(Ok(()), |e| e) } - async fn check_group( + pub async fn check_group( &self, chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 0d863e17b..f7b7fbbbe 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -123,6 +123,7 @@ impl GroupManager { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); + let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), @@ -143,9 +144,13 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let state_proccessor = state_mgr + .load_root_state(local_device_id.object_id(), Some(local_id), true) + .await?; let client = RPathClient::load( - local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + state_proccessor.unwrap(), non_driver, network_sender, ) @@ -199,7 +204,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, Some(&block), Some(&remote), ) @@ -215,7 +220,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -231,7 +236,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -247,7 +252,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -263,7 +268,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -279,7 +284,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -321,12 +326,32 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message(HotstuffMessage::QueryState(sub_path), remote) + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + IsCreateRPath::No, + None, + Some(&remote), + ) .await; + + match control { + Ok(control) => { + control + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + _ => { + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + } } HotstuffPackage::VerifiableState(sub_path, result) => { let rpath = result.as_ref().map_or_else( @@ -436,15 +461,10 @@ impl GroupManager { let store = match store { Some(store) => store, None => { - let init_state = match is_auto_create { - IsCreateRPath::Yes(init_state) => init_state, - _ => unreachable!(), - }; GroupStorage::create( group_id, dec_id, rpath, - init_state, non_driver.clone(), local_device_id.object_id().clone(), &root_state_mgr, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 9f1d08579..8a1dd34a7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -5,18 +5,18 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, storage::DecStorage, - HotstuffMessage, CLIENT_POLL_TIMEOUT, + Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; struct RPathClientRaw { rpath: GroupRPath, - local_id: ObjectId, + local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, @@ -28,22 +28,31 @@ pub struct RPathClient(Arc); impl RPathClient { pub(crate) async fn load( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { - let dec_store = DecStorage::load().await?; + let dec_store = DecStorage::load(state_processor).await?; + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); + let state_sync = DecStateSynchronizer::new( - local_id, + local_device_id, rpath.clone(), + committee.clone(), non_driver.clone(), dec_store.clone(), ); let state_requestor = DecStateRequestor::new( - local_id, + local_device_id, rpath.clone(), + committee, network_sender.clone(), non_driver.clone(), dec_store.clone(), @@ -53,7 +62,7 @@ impl RPathClient { rpath, non_driver, network_sender, - local_id, + local_device_id, state_sync, state_requestor, }; @@ -77,7 +86,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -143,7 +152,7 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let random = rand::thread_rng().gen_range(0..oods.len()); let ood = oods.get(random).unwrap().clone(); @@ -154,14 +163,15 @@ impl RPathClient { Ok(()) } - pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 .non_driver .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); + let members = + group.select_members_with_distance(&self.0.local_device_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 101b34075..7abff1ec1 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -89,7 +89,9 @@ impl RPathControl { HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), HotstuffMessage::ProposalResult(_, _) => unreachable!(), - HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::QueryState(sub_path) => { + self.0.hotstuff.on_query_state(sub_path, remote).await + } HotstuffMessage::VerifiableState(_, _) => unreachable!(), } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index b5c3b107e..0a3544c09 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,10 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, CHANNEL_CAPACITY, }; @@ -19,9 +20,9 @@ enum DecStateRequestorMessage { } struct DecStateRequestorRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } #[derive(Clone)] @@ -29,8 +30,9 @@ pub struct DecStateRequestor(Arc); impl DecStateRequestor { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, store: DecStorage, @@ -39,8 +41,9 @@ impl DecStateRequestor { let notifier = CallReplyNotifier::new(); let mut runner = DecStateRequestorRunner::new( - local_id, + local_device_id, rpath, + committee, rx, store, network_sender, @@ -51,7 +54,7 @@ impl DecStateRequestor { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateRequestorRaw { - local_id, + local_device_id, tx_dec_state_req_message: tx, query_state_notifier: notifier, })) @@ -60,7 +63,7 @@ impl DecStateRequestor { pub async fn wait_query_state( &self, sub_path: String, - ) -> CallReplyWaiter> { + ) -> CallReplyWaiter>> { self.0.query_state_notifier.prepare(sub_path).await } @@ -88,21 +91,23 @@ impl DecStateRequestor { } struct DecStateRequestorRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, // timer: Timer, store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } impl DecStateRequestorRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<( DecStateRequestorMessage, ObjectId, @@ -110,10 +115,10 @@ impl DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, rx_dec_state_req_message, // timer: Timer::new(SYNCHRONIZER_TIMEOUT), @@ -121,6 +126,7 @@ impl DecStateRequestorRunner { query_state_notifier, network_sender, non_driver, + committee, } } @@ -144,9 +150,9 @@ impl DecStateRequestorRunner { match result { Ok(result) => { let result = self - .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .check_sub_path_value(sub_path.as_str(), &result, &remote) .await - .map(|_| unimplemented!()); // TODO: 搜索目标值 + .map(|r| r.cloned()); self.query_state_notifier.reply(&sub_path, result).await } @@ -154,40 +160,23 @@ impl DecStateRequestorRunner { } } - async fn verify_verifiable_state( + async fn check_sub_path_value<'a>( &self, sub_path: &str, - result: &GroupRPathStatus, + verifiable_status: &'a GroupRPathStatus, remote: &ObjectId, - ) -> BuckyResult<()> { - // let header_block = self - // .non_driver - // .get_block(&result.block_id, Some(remote)) - // .await?; - // let qc_block = self - // .non_driver - // .get_block(&result.qc_block_id, Some(remote)) - // .await?; - - let qc = &result.certificate; - - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(result.block_desc.content().group_chunk_id()), - Some(&remote), + ) -> BuckyResult> { + self.committee + .verify_block_desc_with_qc( + &verifiable_status.block_desc, + &verifiable_status.certificate, + remote.clone(), ) .await?; - if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "verify failed", - )) - } else { - Ok(()) - } + self.store + .check_sub_path_value(sub_path, verifiable_status) + .await } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 73afb0ad0..7272b3882 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -10,10 +10,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::{verify_block, Timer}, + helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, + Committee, CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -32,7 +32,7 @@ enum DecStateSynchronizerMessage { } struct DecStateSynchronizerRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, proposal_result_notifier: CallReplyNotifier>>, } @@ -42,8 +42,9 @@ pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { @@ -51,8 +52,9 @@ impl DecStateSynchronizer { let notifier = CallReplyNotifier::new(); let mut runner = DecStateSynchronizerRunner::new( - local_id, + local_device_id, rpath, + committee, tx.clone(), rx, store, @@ -63,7 +65,7 @@ impl DecStateSynchronizer { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateSynchronizerRaw { - local_id, + local_device_id, tx_dec_state_sync_message: tx, proposal_result_notifier: notifier, })) @@ -126,8 +128,9 @@ struct UpdateNotifyInfo { } struct DecStateSynchronizerRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, @@ -142,8 +145,9 @@ struct DecStateSynchronizerRunner { impl DecStateSynchronizerRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<( DecStateSynchronizerMessage, ObjectId, @@ -157,7 +161,7 @@ impl DecStateSynchronizerRunner { proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, tx_dec_state_sync_message, rx_dec_state_sync_message, @@ -167,6 +171,7 @@ impl DecStateSynchronizerRunner { update_notifies: None, non_driver, proposal_result_notifier, + committee, } } @@ -330,52 +335,29 @@ impl DecStateSynchronizerRunner { } } - let group = match self.update_notifies.as_ref() { - Some(n) => Some((n.group_chunk_id, n.group.clone())), - None => self - .check_cache() - .await - .as_ref() - .map(|c| (c.group_chunk_id, c.group.clone())), - } - .map_or(None, |(chunk_id, group)| { - if &chunk_id == header_block.group_chunk_id() { - Some((chunk_id, group)) - } else { - None - } - }); - - // group changed - let group = match group { - Some(group) => group, - None => { - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(header_block.group_chunk_id()), - Some(&remote), - ) - .await?; - (header_block.group_chunk_id().clone(), group) - } - }; - if header_block.check() - && verify_block( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - &group.1, - ) - .await? + && self + .committee + .verify_block_desc_with_qc( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + remote, + ) + .await + .is_ok() { + let group = self + .committee + .check_group(Some(header_block.group_chunk_id()), None) + .await?; + let group_chunk_id = header_block.group_chunk_id().clone(); + self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, remotes: HashSet::from([remote]), - group_chunk_id: group.0, - group: group.1, + group_chunk_id, + group, }); }; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 759bf2c4a..ef3e34495 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -5,24 +5,6 @@ use cyfs_core::{ use crate::GroupRPathStatus; -pub async fn verify_block( - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - let block_id = block_desc.object_id(); - if qc.round != block_desc.content().round() || qc.block_id != block_id { - log::error!( - "the qc-block({}) should be next block({})", - qc.round, - block_id - ); - return Ok(false); - } - - unimplemented!() -} - pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index f266d3dbd..858c37fff 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -13,7 +13,7 @@ pub struct GroupRPathStatus { } impl RawEncode for GroupRPathStatus { - fn raw_measure(&self, purpose: &Option) -> BuckyResult { + fn raw_measure(&self, _purpose: &Option) -> BuckyResult { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; let mut status_list = vec![]; @@ -33,7 +33,7 @@ impl RawEncode for GroupRPathStatus { fn raw_encode<'a>( &self, mut buf: &'a mut [u8], - purpose: &Option, + _purpose: &Option, ) -> BuckyResult<&'a mut [u8]> { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index cce00e736..de5a0fd4a 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -1,10 +1,14 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, + ObjectTypeCode, RawDecode, +}; use cyfs_core::GroupConsensusBlock; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::GroupRPathStatus; +use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; #[derive(Clone)] pub struct DecStorageCache { @@ -16,13 +20,15 @@ pub struct DecStorageCache { #[derive(Clone)] pub struct DecStorage { cache: Arc>>, + pub state_processor: GlobalStateRawProcessorRef, } impl DecStorage { - pub async fn load() -> BuckyResult { - unimplemented!(); + pub async fn load(state_processor: GlobalStateRawProcessorRef) -> BuckyResult { + // unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), + state_processor, }; Ok(obj) @@ -45,4 +51,64 @@ impl DecStorage { pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } + + pub async fn check_sub_path_value<'a>( + &self, + sub_path: &str, + verifiable_status: &'a GroupRPathStatus, + ) -> BuckyResult> { + let block_desc = &verifiable_status.block_desc; + let qc = &verifiable_status.certificate; + + let mut parent_state_id = match block_desc.content().result_state_id() { + Some(state_id) => state_id.clone(), + None => return Ok(None), + }; + + let root_cache = self.state_processor.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { + Some(state) => state, + None => return Ok(None), + }; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(None); + } + } + } + + Ok(verifiable_status.status_map.get(&parent_state_id)) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index c4803d6ff..eb0ede98f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -22,9 +22,9 @@ pub struct StorageCacheInfo { } impl StorageCacheInfo { - pub fn new(init_state_id: Option) -> Self { + pub fn new(dec_state_id: Option) -> Self { Self { - dec_state_id: init_state_id, + dec_state_id, last_vote_round: 0, last_qc: None, last_tc: None, diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index b3a01fd60..604e44744 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,10 +2,10 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, + ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -154,6 +154,19 @@ impl StorageEngineGroupState { None => 0, }; + let dec_state_id_in_header = cache + .header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); + + assert_eq!(dec_state_id, dec_state_id_in_header); + if dec_state_id != dec_state_id_in_header { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the state should same as it in header-block", + )); + } + let (prepare_blocks, pre_commit_blocks) = load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { @@ -179,6 +192,10 @@ impl StorageEngineGroupState { .await?, ) } + + pub fn root_cache(&self) -> &ObjectMapRootCacheRef { + self.state_mgr.root_cache() + } } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index ee2618cde..d233025ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -5,7 +5,7 @@ use std::{ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, + ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -15,7 +15,8 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ @@ -56,7 +57,6 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, @@ -84,7 +84,7 @@ impl GroupStorage { GroupStatePath::new(rpath.to_string()), ), local_device_id, - cache: StorageCacheInfo::new(init_state_id), + cache: StorageCacheInfo::new(None), }) } @@ -809,4 +809,100 @@ impl GroupStorage { ) } } + + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let (header_block, qc) = match self.cache.header_block.as_ref() { + Some(block) => { + let (_, qc_block) = self + .cache + .pre_commits + .iter() + .next() + .expect("pre-commit should not be empty"); + + assert_eq!( + qc_block.prev_block_id().unwrap(), + block.block_id().object_id(), + "the prev-block for all pre-commits should be the header" + ); + + (block, qc_block.qc().as_ref().unwrap()) + } + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "the header block is none", + )); + } + }; + + let mut parent_state_id = match header_block.result_state_id() { + Some(state_id) => state_id.clone(), + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map: HashMap::new(), + }) + } + }; + + let mut status_map = HashMap::new(); + + let root_cache = self.storage_engine.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + status_map.insert(parent_state_id, parent_state); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } + } + } + + let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + status_map.insert(parent_state_id, leaf_state); + + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } } diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 9fbc4eb4f..5d005a726 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), // init state + Yes, } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 2ba99716e..0401c55a0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -816,7 +816,7 @@ async fn main_run() { &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -845,7 +845,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -892,7 +892,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); From 176ac10cab36ffdb9c62ad16e9da609fc579ad71 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 17:03:44 +0800 Subject: [PATCH 219/553] Example for APP-State as tree --- .../src/consensus/hotstuff/hotstuff.rs | 9 +- .../cyfs-group/src/dec/delegate_factory.rs | 10 +- .../src/storage/engine/storage_engine.rs | 2 +- .../engine/storage_engine_group_state.rs | 23 ++- .../cyfs-group/src/storage/group_storage.rs | 18 +- src/tests/group-example/src/main.rs | 155 +++++++++++++++--- 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 667966a6c..d9773bd88 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,13 +9,13 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, @@ -499,7 +499,7 @@ impl HotstuffRunner { if self .delegate - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -851,6 +851,7 @@ impl HotstuffRunner { .on_commited( &proposal_obj, pre_state_id, + self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1528,7 +1529,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id).await { + match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index bdcb98f60..0b13d97ce 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -34,12 +34,14 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult; @@ -47,7 +49,13 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ); } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index eb0ede98f..cbb5d99df 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 604e44744..aae81394b 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -8,8 +8,8 @@ use cyfs_base::{ use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -672,3 +672,22 @@ fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult Self { + Self { + state_mgr: state_mgr.clone(), + } + } +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { + async fn create_single_op_env(&self) -> BuckyResult { + self.state_mgr.create_single_op_env(ACCESS) + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d233025ab..3a1c20f2a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,12 +15,15 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ - engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + engine::{ + GroupObjectMapProcessorGroupState, StorageCacheInfo, StorageEngineGroupState, + StorageEngineMock, + }, StorageEngine, }; @@ -50,6 +53,7 @@ pub struct GroupStorage { cache: StorageCacheInfo, storage_engine: StorageEngineGroupState, + object_map_processor: GroupObjectMapProcessorGroupState, } impl GroupStorage { @@ -71,6 +75,7 @@ impl GroupStorage { .expect("create group state failed."); let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -85,6 +90,7 @@ impl GroupStorage { ), local_device_id, cache: StorageCacheInfo::new(None), + object_map_processor, }) } @@ -129,6 +135,7 @@ impl GroupStorage { let state_path = GroupStatePath::new(rpath.to_string()); let cache = StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -140,6 +147,7 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, cache, + object_map_processor, }) } @@ -905,4 +913,8 @@ impl GroupStorage { status_map, }); } + + pub fn get_object_map_processor(&self) -> &dyn GroupObjectMapProcessor { + &self.object_map_processor + } } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0401c55a0..0fae6dd53 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -38,16 +38,18 @@ mod Common { CyfsStackNOCParams, CyfsStackParams, }; - lazy_static::lazy_static! { - // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + /** + * |--root + * |--folder1 + * |--folder2 + * |--value-->u64 + */ - // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); + pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } fn create_member( @@ -495,7 +497,7 @@ mod Client { } mod GroupDecService { - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, fmt::format, sync::Arc}; use async_std::sync::Mutex; use cyfs_base::*; @@ -503,9 +505,11 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; use cyfs_stack::CyfsStack; + use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; + pub struct DecService {} impl DecService { @@ -580,17 +584,78 @@ mod GroupDecService { } impl MyRPathDelegate { - pub fn execute( + pub async fn get_value_from_state_tree_with_single_op_envs( + pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<( + Option, + Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + )> { + let mut single_op_envs = vec![]; + let mut parent_map_id = pre_state_id; + for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + let single_op_env = object_map_processor.create_single_op_env().await.expect( + format!( + "create_single_op_env load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + parent_map_id = match parent_map_id { + Some(parent_map_id) => { + single_op_env.load(&parent_map_id).await.expect( + format!( + "load folder {} parent with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + single_op_env.get_by_key(folder).await.expect( + format!( + "load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ) + } + None => { + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!( + "create folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + None + } + }; + single_op_envs.push((single_op_env, folder, parent_map_id)); + } + + Ok((parent_map_id, single_op_envs)) + } + + pub async fn execute( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let result_state_id = { + let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await?; + + let result_value = { /** * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); + let pre_value = pre_value.map_or(0, |pre_value| { + let buf = pre_value.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -608,6 +673,32 @@ mod GroupDecService { .unwrap() }; + let result_state_id = { + let mut sub_folder_value = result_value; + for (parent_single_op_env, folder, sub_folder_prev_value) in + single_op_envs.into_iter().rev() + { + parent_single_op_env + .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + .await + .expect( + format!( + "update folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + sub_folder_value = parent_single_op_env.commit().await.expect( + format!( + "commit folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + } + sub_folder_value + }; + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? @@ -623,7 +714,7 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_state_id + proposal + context + * (result_state_id, return_object) = pre_value + proposal + context */ Ok(ExecuteResult { context, @@ -632,17 +723,20 @@ mod GroupDecService { }) } - pub fn verify( + pub async fn verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context */ - let result = self.execute(proposal, pre_state_id)?; + let result = self + .execute(proposal, pre_state_id, object_map_processor) + .await?; let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() @@ -658,23 +752,28 @@ mod GroupDecService { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id) + self.execute(proposal, pre_state_id, object_map_processor) + .await } async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) + self.verify(proposal, pre_state_id, object_map_processor, execute_result) + .await } async fn on_commited( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { @@ -685,14 +784,28 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let pre_value = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); - let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let result_value = Self::get_value_from_state_tree_with_single_op_envs( + execute_result.result_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); @@ -901,7 +1014,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } From ee5bae3f11b3a6f7088a2423812915ee3b6d157d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 19:51:46 +0800 Subject: [PATCH 220/553] Fix: Update the state structure, mount the template dec-state of blocks in prepare/pre-commit, to avoid it's recycled. --- .../cyfs-base/src/objects/object_map/mod.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 5 +- .../cyfs-group/src/statepath/design.md | 12 +- .../src/statepath/group_statepath.rs | 34 +++ .../src/storage/engine/storage_engine.rs | 20 +- .../engine/storage_engine_group_state.rs | 139 ++++++++-- .../src/storage/engine/storage_engine_mock.rs | 7 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 248 +++++++++++------- 9 files changed, 351 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index 3bbc5f131..75589834b 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -18,6 +18,7 @@ mod visitor; pub use access::*; pub use cache::*; pub use diff::*; +pub use isolate_path_env::*; pub use iterator::*; pub use object_map::*; pub use op_env::*; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 0b13d97ce..f5092dbfc 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,6 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -58,4 +60,5 @@ pub trait RPathDelegate: Sync + Send { #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; } diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index cb964e066..885888d5b 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -22,14 +22,20 @@ | |--users | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-vote-round-->u64 // 最后一次投票的 轮次 | |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block | | -| |--prepares->Set // Prepare状态的block -| |--pre-commits->Set // pre-commit状态的block +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 72f48e601..0ed0abd25 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -10,6 +10,8 @@ pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; @@ -164,10 +166,42 @@ impl GroupStatePath { self.prepares.as_str() } + pub fn prepares_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn prepares_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn pre_commits(&self) -> &str { self.pre_commits.as_str() } + pub fn pre_commits_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn finish_proposals(&self) -> &str { self.finish_proposals.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index cbb5d99df..e14445695 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -43,9 +43,19 @@ impl StorageCacheInfo { #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()>; + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + is_instead: bool, + ) -> BuckyResult<()>; + async fn push_commit( &mut self, height: u64, @@ -54,7 +64,9 @@ pub trait StorageWriter: Send + Sync { prev_result_state_id: &Option, min_height: u64, ) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( &mut self, proposal_ids: &[ObjectId], @@ -62,7 +74,9 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index aae81394b..8b8799207 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,14 +2,15 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, - ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -90,7 +91,8 @@ impl StorageEngineGroupState { None => None, }; - let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let prepare_block_ids = + load_object_ids_with_path_map_key(&op_env, state_path.prepares()).await?; if prepare_block_ids.len() == 0 && commit_range.is_none() { return Err(BuckyError::new( BuckyErrorCode::NotFound, @@ -99,7 +101,7 @@ impl StorageEngineGroupState { } let pre_commit_block_ids = - load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + load_object_ids_with_path_map_key(&op_env, state_path.pre_commits()).await?; let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { @@ -113,8 +115,10 @@ impl StorageEngineGroupState { n }); - let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; - let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + let adding_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.adding()).await?; + let over_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.recycle()).await?; let load_block_ids = [ first_header_block_ids.as_slice(), @@ -233,7 +237,7 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new(ObjectMapSimpleContentType::Map) .await?; None } else { @@ -253,20 +257,51 @@ impl StorageEngineGroupStateWriter { }) } - async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn create_block_result_object_map( + &self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult { + let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await?; + single_op_env + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + if let Some(state_id) = result_state_id.as_ref() { + single_op_env + .insert_with_key(GROUP_STATE_PATH_RESULT_STATE, state_id) + .await?; + } + + single_op_env.commit().await + } + + async fn insert_prepares_inner( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) + .await?; self.prepare_op_env - .insert(block_id) + .insert_with_key(block_id.to_string().as_str(), &block_result_pair) .await - .map(|is_changed| assert!(is_changed)) } async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); if is_instead { self.op_env @@ -274,12 +309,17 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self - .op_env - .insert(self.state_path.pre_commits(), block_id) + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) .await?; - assert!(is_changed); - Ok(()) + + self.op_env + .insert_with_key( + self.state_path.pre_commits(), + block_id.to_string().as_str(), + &block_result_pair, + ) + .await } async fn push_commit_inner( @@ -357,8 +397,11 @@ impl StorageEngineGroupStateWriter { async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); } Ok(()) } @@ -486,19 +529,26 @@ impl StorageEngineGroupStateWriter { #[async_trait::async_trait] impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result = self.insert_prepares_inner(block_id, result_state_id).await; self.write_result.clone() } async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result = self + .insert_pre_commit_inner(block_id, result_state_id, is_instead) + .await; self.write_result.clone() } @@ -614,7 +664,7 @@ fn parse_u64_obj(obj: &ObjectId) -> u64 { u64::from_le_bytes(buf) } -async fn load_object_ids_with_path( +async fn load_object_ids_with_path_set( op_env: &ObjectMapPathOpEnvRef, full_path: &str, ) -> BuckyResult> { @@ -647,6 +697,41 @@ async fn load_object_ids_with_path( Ok(object_ids) } +async fn load_object_ids_with_path_map_key( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Map((key_id_base58, _)) => { + object_ids.push(ObjectId::from_base58(key_id_base58)?) + } + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} + fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { match r { Ok(t) => Ok(Some(t)), @@ -690,4 +775,8 @@ impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { async fn create_single_op_env(&self) -> BuckyResult { self.state_mgr.create_single_op_env(ACCESS) } + + async fn create_sub_tree_op_env(&self) -> BuckyResult { + self.state_mgr.create_isolate_path_op_env(ACCESS) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index ebeedd7ca..fbc7cafdc 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -71,7 +71,11 @@ pub struct StorageEngineMockWriter<'a> { #[async_trait::async_trait] impl<'a> StorageWriter for StorageEngineMockWriter<'a> { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { if !self.engine.prepare_blocks.insert(block_id.clone()) { assert!(false); return Err(BuckyError::new( @@ -85,6 +89,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { if !self.engine.prepare_blocks.remove(block_id) { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a1c20f2a..491d029dd 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -291,10 +291,16 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(block_id.object_id()).await?; - if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_prepares(block_id.object_id(), block.result_state_id()) + .await?; + if let Some((new_pre_commit_id, new_pre_commit)) = new_pre_commit.as_ref() { writer - .insert_pre_commit(new_pre_commit, new_header.is_some()) + .insert_pre_commit( + new_pre_commit_id, + new_pre_commit.result_state_id(), + new_header.is_some(), + ) .await?; } if let Some(new_header) = new_header.as_ref() { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0fae6dd53..394b15acb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -584,59 +584,59 @@ mod GroupDecService { } impl MyRPathDelegate { - pub async fn get_value_from_state_tree_with_single_op_envs( - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, - ) -> BuckyResult<( - Option, - Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - )> { - let mut single_op_envs = vec![]; - let mut parent_map_id = pre_state_id; - for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - let single_op_env = object_map_processor.create_single_op_env().await.expect( - format!( - "create_single_op_env load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - parent_map_id = match parent_map_id { - Some(parent_map_id) => { - single_op_env.load(&parent_map_id).await.expect( - format!( - "load folder {} parent with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - single_op_env.get_by_key(folder).await.expect( - format!( - "load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ) - } - None => { - single_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await - .expect( - format!( - "create folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - None - } - }; - single_op_envs.push((single_op_env, folder, parent_map_id)); - } - - Ok((parent_map_id, single_op_envs)) - } + // pub async fn get_value_from_state_tree_with_single_op_envs( + // pre_state_id: Option, + // object_map_processor: &dyn GroupObjectMapProcessor, + // ) -> BuckyResult<( + // Option, + // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + // )> { + // let mut single_op_envs = vec![]; + // let mut parent_map_id = pre_state_id; + // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + // let single_op_env = object_map_processor.create_single_op_env().await.expect( + // format!( + // "create_single_op_env load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // parent_map_id = match parent_map_id { + // Some(parent_map_id) => { + // single_op_env.load(&parent_map_id).await.expect( + // format!( + // "load folder {} parent with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // single_op_env.get_by_key(folder).await.expect( + // format!( + // "load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ) + // } + // None => { + // single_op_env + // .create_new(ObjectMapSimpleContentType::Map) + // .await + // .expect( + // format!( + // "create folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // None + // } + // }; + // single_op_envs.push((single_op_env, folder, parent_map_id)); + // } + + // Ok((parent_map_id, single_op_envs)) + // } pub async fn execute( &self, @@ -644,11 +644,30 @@ mod GroupDecService { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await?; + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + let pre_value = match pre_state_id { + Some(pre_state_id) => { + state_op_env.load(&pre_state_id).await?; + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ) + } + None => { + state_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ); + None + } + }; let result_value = { /** @@ -674,29 +693,50 @@ mod GroupDecService { }; let result_state_id = { - let mut sub_folder_value = result_value; - for (parent_single_op_env, folder, sub_folder_prev_value) in - single_op_envs.into_iter().rev() - { - parent_single_op_env - .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - .await - .expect( - format!( - "update folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value - ) - .as_str(), - ); - sub_folder_value = parent_single_op_env.commit().await.expect( + state_op_env + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .await + .expect( format!( - "commit folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value + "set_with_path {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value ) .as_str(), ); - } - sub_folder_value + state_op_env.commit().await.expect( + format!( + "commit {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value + ) + .as_str(), + ) + // let mut sub_folder_value = result_value; + // for (parent_single_op_env, folder, sub_folder_prev_value) in + // single_op_envs.into_iter().rev() + // { + // parent_single_op_env + // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + // .await + // .expect( + // format!( + // "update folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // sub_folder_value = parent_single_op_env.commit().await.expect( + // format!( + // "commit folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // } + // sub_folder_value }; let receipt = { @@ -784,13 +824,26 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let pre_value = match pre_state_id { + Some(pre_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&pre_state_id) + .await + .expect(format!("load {} failed", pre_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; @@ -798,13 +851,26 @@ mod GroupDecService { u64::from_be_bytes(pre_value) }); - let result_value = Self::get_value_from_state_tree_with_single_op_envs( - execute_result.result_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let result_value = match execute_result.result_state_id { + Some(result_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&result_state_id) + .await + .expect(format!("load {} failed", result_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; From df51233c94aee6aa442bb93072274152fe44e05a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:00 +0800 Subject: [PATCH 221/553] Accept the invalid block with vote it. --- src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 138 +++++++++++++----- .../cyfs-group/src/storage/group_storage.rs | 102 +------------ 3 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index aaab4ed76..4a7aae6c2 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' +itertools = "0.10.3" cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d9773bd88..511b0b32e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -13,6 +13,7 @@ use cyfs_core::{ }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; +use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, @@ -365,7 +366,7 @@ impl HotstuffRunner { } } - let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, Err(err) => return err }; @@ -391,9 +392,6 @@ impl HotstuffRunner { self, block.block_id()); - self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await?; - self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -402,7 +400,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote, &proposals).await + self.process_block(block, remote, &HashMap::new()).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -574,7 +572,7 @@ impl HotstuffRunner { } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { match self.store.block_linked(block).await .map_err(|err| Err(err))? { @@ -585,16 +583,6 @@ impl HotstuffRunner { ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - Err (Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - ))) - } crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", @@ -605,7 +593,7 @@ impl HotstuffRunner { "duplicate block", ))) } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { + crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", self, @@ -614,7 +602,7 @@ impl HotstuffRunner { // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; - Ok((prev_block, proposals)) + Ok(prev_block) } crate::storage::BlockLinkState::Pending => { log::warn!( @@ -942,20 +930,6 @@ impl HotstuffRunner { return None; } - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 - let mut proposal_temp: HashMap = HashMap::new(); - if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { - Ok(_) => proposals = &proposal_temp, - Err(_) => return None - } - } else { - assert_eq!(proposals.len(), block.proposals().len()); - } - if !Self::check_timestamp_precision(block, proposals) { - return None; - } - // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -982,6 +956,22 @@ impl HotstuffRunner { return None; } + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block.clone()), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None + }, + }, + None => None + }; + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -993,6 +983,77 @@ impl HotstuffRunner { } } + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + return None + } + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + return None; + } + + if proposals.len() != block.proposals().len() { + let mut dup_proposals = block.proposals().clone(); + dup_proposals.sort_unstable_by_key(|p| p.proposal); + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + ); + return None; + } + + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + match block.prev_block_id() { + Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await.map(|is_finished| (is_finished, &proposal_result.proposal)), + None => Ok((false, &proposal_result.proposal)) + } + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok((is_finished, proposal_id)) => { + if is_finished { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + proposal_id + ); + return None; + } + }, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", + self, + block.block_id(), + err + ); + return None; + }, + } + } + + if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await.is_err() { + return None; + } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1021,12 +1082,23 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { false } else { + if let Some(prev_block) = prev_block { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { + if duration > TIME_PRECISION { + return false + } + } + } + for proposal in block.proposals() { let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 491d029dd..04e4c80fc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,22 +1,19 @@ -use std::{ - collections::{HashMap, HashSet}, - time::SystemTime, -}; +use std::collections::{HashMap, HashSet}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ @@ -31,11 +28,10 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, - DuplicateProposal, Duplicate, Link( Option, - HashMap, + // HashMap, ), // Pending, InvalidBranch, @@ -528,18 +524,6 @@ impl GroupStorage { return Ok(BlockLinkState::Duplicate); } - let now = SystemTime::now(); - let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); - - if let Ok(duration) = block_time.duration_since(now) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } - log::debug!( "[group storage] {} block_linked {} step2", self.local_device_id, @@ -554,17 +538,6 @@ impl GroupStorage { } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); - if let Ok(duration) = prev_block_time.duration_since(block_time) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } Some(prev_block) } } @@ -592,66 +565,7 @@ impl GroupStorage { block.block_id() ); - let mut proposals = HashMap::new(); - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? - { - return Ok(BlockLinkState::DuplicateProposal); - } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - - Ok(BlockLinkState::Link( - None, - HashMap::from([(proposal_result.proposal, proposal)]), - )) - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok(result) => match result { - BlockLinkState::Link(_, proposal) => { - let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); - if proposals.get(&proposal_id).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } - proposals.insert(proposal_id, proposal); - } - _ => return Ok(result), - }, - _ => return check_result, - } - } - - log::debug!( - "[group storage] {} block_linked {} step4", - self.local_device_id, - block.block_id() - ); - - Ok(BlockLinkState::Link(prev_block, proposals)) + Ok(BlockLinkState::Link(prev_block)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From 65dbec06d43f418e5bfa9808959cc1d63664ea8b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:55 +0800 Subject: [PATCH 222/553] Chore unused code --- src/component/cyfs-group/src/storage/group_storage.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 04e4c80fc..122ae72ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -29,10 +29,7 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, Duplicate, - Link( - Option, - // HashMap, - ), // + Link(Option), // Pending, InvalidBranch, } From 5ab8a6376a683692dffefd06eda220d712ebb800 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 12:20:23 +0800 Subject: [PATCH 223/553] get VerifiableState from the admin --- .../src/consensus/hotstuff/hotstuff.rs | 260 +++++++++++------- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 2 +- src/component/cyfs-group/src/constant.rs | 2 +- .../src/dec_state/dec_state_requestor.rs | 5 + .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../src/objects/group_rpath_status.rs | 21 +- .../cyfs-group/src/objects/protocol.rs | 11 +- .../cyfs-group/src/storage/dec_storage.rs | 6 + .../cyfs-group/src/storage/group_storage.rs | 27 +- src/tests/group-example/Cargo.toml | 3 +- src/tests/group-example/src/main.rs | 79 +++++- 11 files changed, 302 insertions(+), 116 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 511b0b32e..10c5d9635 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -4,7 +4,7 @@ use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, + RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -19,11 +19,13 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * + * synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -212,6 +214,7 @@ struct HotstuffRunner { round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, + max_quorum_round: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -311,6 +314,7 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, + max_quorum_round: round - 1, state_pusher, tx_block_gen, rx_block_gen, @@ -366,15 +370,6 @@ impl HotstuffRunner { } } - let prev_block = match self.check_block_linked(&block, remote).await { - Ok(link) => link, - Err(err) => return err - }; - - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", - self, - block.block_id()); - self.committee .verify_block(block, remote) .await @@ -388,6 +383,18 @@ impl HotstuffRunner { err })?; + let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); + self.update_max_quorum_round(quorum_round); + + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + + let prev_block = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err + }; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", self, block.block_id()); @@ -452,10 +459,19 @@ impl HotstuffRunner { block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, + remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = prev_block - .as_ref() - .map_or(None, |block| block.result_state_id().clone()); + let mut prev_state_id = match prev_block + .as_ref() { + Some(prev_block) => { + let result_state_id = block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; + } + result_state_id.clone() + }, + None => None + }; for proposal_exe_info in block.proposals() { // 去重 @@ -672,7 +688,7 @@ impl HotstuffRunner { err })?; - if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", self, header_block.block_id() @@ -696,29 +712,18 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(header_block.clone(), qc_block).await; + self.notify_block_committed(&header_block, &old_header_block, qc_block).await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", self, block.block_id() ); - let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self, self.round, err - ); - - err - }); - // notify by leader - if let Ok(leader) = leader { - if self.local_device_id == leader { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } + if &self.local_id == header_block.owner() { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; } log::debug!( @@ -733,7 +738,7 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, the qc of block {:?} has received before", self, block.block_id() ); - return self.process_block_qc(qc, block, remote).await; + return self.process_block_qc(qc, block).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( @@ -762,7 +767,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block, proposals).await { + if let Some(vote) = self.make_vote(block, proposals, &remote).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -791,22 +796,12 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - let mut pre_state_id = match new_header.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); + + let mut pre_state_id = old_header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); for proposal in new_header.proposals() { let proposal_obj = self @@ -900,6 +895,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_round(&mut self, quorum_round: u64) { + if quorum_round > self.max_quorum_round { + self.max_quorum_round = quorum_round; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -922,7 +923,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -930,6 +931,13 @@ impl HotstuffRunner { return None; } + if self.max_quorum_round >= self.round { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } + // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -1002,6 +1010,10 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + self, + block.block_id(), + ); return None; } @@ -1016,44 +1028,15 @@ impl HotstuffRunner { return None; } - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - match block.prev_block_id() { - Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await.map(|is_finished| (is_finished, &proposal_result.proposal)), - None => Ok((false, &proposal_result.proposal)) - } - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok((is_finished, proposal_id)) => { - if is_finished { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", - self, - block.block_id(), - proposal_id - ); - return None; - } - }, - Err(err) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", - self, - block.block_id(), - err - ); - return None; - }, - } + if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err + ); + return None; } - if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await.is_err() { - return None; - } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1075,7 +1058,12 @@ impl HotstuffRunner { } }; - if self.store.set_last_vote_round(block.round()).await.is_err() { + if let Err(err) = self.store.set_last_vote_round(block.round()).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for update last-vote-round failed {:?}", + self, + block.block_id(), + err + ); return None; } @@ -1086,23 +1074,39 @@ impl HotstuffRunner { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + block.block_id(), + block_timestamp, + now + ); + false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); + let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + block.block_id(), + block_timestamp, + prev_block_time + ); return false } } } for proposal in block.proposals() { - let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_id = proposal.proposal; + let proposal = proposals.get(&proposal_id).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + block.block_id(), + block_timestamp, + proposal_id, + proposal_timestamp + ); return false } } @@ -1174,7 +1178,7 @@ impl HotstuffRunner { if is_prev_none {"None"} else {"Some"} ); - self.process_block_qc(qc, &block, remote).await?; + self.process_block_qc(qc, &block).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1185,7 +1189,6 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, - remote: ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1334,7 +1337,10 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - + + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1453,6 +1459,9 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1501,8 +1510,7 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ) - .await.map_err(|err| { + ).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", self, err @@ -1541,7 +1549,13 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let prev_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), + Some(qc) => { + let prev_block = self.store.find_block_in_cache(&qc.block_id)?; + if let Some(result_state_id) = prev_block.result_state_id() { + self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + } + Some(prev_block) + }, None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1940,6 +1954,58 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } + async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 + let obj_map_processor = self.store.get_object_map_processor(); + + #[async_recursion::async_recursion] + async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if non_driver.get_object(&root_id, None).await.is_ok() { + // TODO: 可能有下级分支子树因为异常不齐全 + return Ok(()); + } + let obj = non_driver.get_object(root_id, Some(remote)).await?; + match obj.object.as_ref() { + Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { + let single_op_env = obj_map_processor.create_single_op_env().await?; + single_op_env.load(root_id).await?; + loop { + let branchs = single_op_env.next(16).await?; + for branch in branchs.list.iter() { + let branch_id = match branch { + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Map(map) => &map.1, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Set(set) => set, + }; + make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + } + + if branchs.list.len() < 16 { + return Ok(()) + } + } + }, + _ => return Ok(()) + } + } + + let mut result = Ok(()); + for remote in remotes { + result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + if result.is_ok() { + return result; + } + } + result + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 82f4017a0..f44260a04 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 1170176b2..77a652a7e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,7 +17,7 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; -pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(5000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 0a3544c09..790429c6c 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -154,6 +154,11 @@ impl DecStateRequestorRunner { .await .map(|r| r.cloned()); + log::debug!( + "handle_verifiable_state sub_path: {}, result: {:?}", + sub_path, + result + ); self.query_state_notifier.reply(&sub_path, result).await } Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cc0b4aff2..b1506a192 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -13,7 +13,7 @@ use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), - BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), // LastStateRequest(ObjectId), DelayBroadcast, } diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index 858c37fff..bfc9bc5d2 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -69,8 +69,25 @@ impl<'de> RawDecode<'de> for GroupRPathStatus { assert_eq!(remain.len(), 0); let mut status_map = HashMap::new(); for obj_buf in proto.status_list.iter() { - let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; - assert_eq!(remain.len(), 0); + log::debug!("will decode len: {}", obj_buf.len()); + // size + object_id + let status = if obj_buf.len() > OBJECT_ID_LEN + 1 { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status + } else if obj_buf.len() == OBJECT_ID_LEN + 1 { + NONObjectInfo::new( + ObjectId::clone_from_slice(&obj_buf.as_slice()[1..])?, + obj_buf.clone(), + None, + ) + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidData, + "expect NONObjectInfo", + )); + }; + status_map.insert(status.object_id, status); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 6c9f89e96..932e5cd46 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use itertools::Itertools; use sha2::Digest; use crate::GroupRPathStatus; @@ -185,12 +186,13 @@ impl std::fmt::Debug for HotstuffMessage { result.as_ref().map(|status| { let desc = status.block_desc.content(); format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ) }) ) @@ -315,12 +317,13 @@ impl std::fmt::Debug for HotstuffPackage { |status| { let desc = status.block_desc.content(); let ok = format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ); Ok(ok) } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index de5a0fd4a..60a45724f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -69,6 +69,10 @@ impl DecStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { Some(state) => state, None => return Ok(None), @@ -98,6 +102,8 @@ impl DecStorage { assert_eq!(remain.len(), 0); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 122ae72ab..966fa518a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, - ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, @@ -223,7 +223,13 @@ impl GroupStorage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - ) -> BuckyResult)>> { + ) -> BuckyResult< + Option<( + &GroupConsensusBlock, + Option, + Vec, + )>, + > { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); @@ -399,9 +405,10 @@ impl GroupStorage { } } - self.cache.header_block = Some(new_header); + let old_header_block = self.cache.header_block.replace(new_header); return Ok(Some(( self.cache.header_block.as_ref().unwrap(), + old_header_block, removed_blocks, ))); } @@ -736,6 +743,7 @@ impl GroupStorage { } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + // TODO: 需要一套通用的同步ObjectMap树的实现 let (header_block, qc) = match self.cache.header_block.as_ref() { Some(block) => { let (_, qc_block) = self @@ -778,6 +786,9 @@ impl GroupStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { @@ -806,6 +817,8 @@ impl GroupStorage { status_map.insert(parent_state_id, parent_state); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder @@ -821,7 +834,11 @@ impl GroupStorage { } } - let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + let leaf_state = if parent_state_id.is_data() { + NONObjectInfo::new(parent_state_id, parent_state_id.to_vec()?, None) + } else { + self.non_driver.get_object(&parent_state_id, None).await? + }; status_map.insert(parent_state_id, leaf_state); return Ok(GroupRPathStatus { diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 0053ccd5f..01094f12a 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -27,4 +27,5 @@ cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } -cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 394b15acb..618336df4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -14,7 +14,7 @@ use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; mod Common { use std::{fmt::format, io::ErrorKind, sync::Arc}; @@ -505,8 +505,15 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + use cyfs_group::{ + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, + }; + use cyfs_lib::{ + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, + }; use cyfs_stack::CyfsStack; + use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -522,10 +529,42 @@ mod GroupDecService { Box::new(GroupRPathDelegateFactory { local_name }), ) .await - .unwrap() + .unwrap(); + + // let source = RequestSourceInfo { + // protocol: todo!(), + // zone: todo!(), + // dec: todo!(), + // verified: todo!(), + // }; + + // cyfs_stack + // .router_handlers() + // .handlers(&RouterHandlerChain::PostRouter) + // .post_object() + // .add_handler(RouterHandler::new()); } } + // pub struct PostProposalRoutine { + // controller: RPathControl, + // } + + // #[async_trait::async_trait] + // impl EventListenerAsyncRoutine + // for PostProposalRoutine + // { + // async fn call( + // &self, + // param: &NONPostObjectInputRequest, + // ) -> BuckyResult { + // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // self.controller.push_proposal(proposal).await?; + // Ok(NONPostObjectInputResponse { object: None }) + // } + // } + pub struct GroupRPathDelegateFactory { local_name: String, } @@ -778,6 +817,16 @@ mod GroupDecService { .execute(proposal, pre_state_id, object_map_processor) .await?; + log::info!( + "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + execute_result.result_state_id, + execute_result.context.is_none(), + execute_result.receipt.is_none(), + result.result_state_id, + result.context.is_none(), + result.receipt.is_none() + ); + let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() && execute_result.receipt.is_none(); @@ -1007,7 +1056,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 1000usize; + let PROPOSAL_COUNT = 5usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1085,6 +1134,28 @@ async fn main_run() { log::info!("will push new proposals, i: {}", i); } } + + let client = admin_stacks + .get(0) + .unwrap() + .group_mgr() + .rpath_client( + &group.desc().object_id(), + dec_app_id.object_id(), + &EXAMPLE_RPATH, + ) + .await + .unwrap(); + + let value_obj = client + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .unwrap(); + let buf = value_obj.as_ref().unwrap().object_id.data(); + let mut value = [0u8; 8]; + value.copy_from_slice(&buf[..8]); + + log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From e535601ac4c1e782a41dc77bdf2859b386e220ab Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 15:46:00 +0800 Subject: [PATCH 224/553] Fix: result-state verify failed --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++++++++++++++---- src/tests/group-example/src/main.rs | 3 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 10c5d9635..e142d4069 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -464,7 +464,7 @@ impl HotstuffRunner { let mut prev_state_id = match prev_block .as_ref() { Some(prev_block) => { - let result_state_id = block.result_state_id(); + let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; } @@ -520,14 +520,24 @@ impl HotstuffRunner { err })? { + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); + prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", self, proposal_exe_info.proposal, - prev_state_id, - proposal_exe_info.result_state + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); @@ -966,7 +976,7 @@ impl HotstuffRunner { let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block.clone()), + Ok(block) => Some(block), Err(_) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", self, @@ -1960,11 +1970,18 @@ impl HotstuffRunner { #[async_recursion::async_recursion] async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if root_id.is_data() { + return Ok(()); + } + if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await?; + let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { + log::warn!("get branch {} failed {:?}", root_id, err); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { let single_op_env = obj_map_processor.create_single_op_env().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 618336df4..4daa0d4f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -818,7 +818,8 @@ mod GroupDecService { .await?; log::info!( - "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + pre_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), From a3a62f2f932efb0cbbe0378f404b65b4bec49256 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 28 Feb 2023 20:27:49 +0800 Subject: [PATCH 225/553] Redefine the Group object for Permission --- .../protos/standard_objects-permission.proto | 203 ++++++++++++++++++ src/tests/group-example/src/main.rs | 8 +- 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto new file mode 100644 index 000000000..b2ec61f60 --- /dev/null +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -0,0 +1,203 @@ +syntax="proto3"; + +// contract +message ContractBodyContent { + bytes data = 1; +} + +// device +message DeviceBodyContent { + repeated bytes endpoints = 1; + repeated bytes sn_list = 2; + repeated bytes passive_pn_list = 3; + optional string name = 4; + optional uint32 bdt_version = 5; +} + +// dir +message DirBodyContent { + enum Type { + Chunk = 0; + ObjList = 1; + } + Type type = 1; + optional bytes chunk_id = 2; + + // 使用list编码hash_map + message ObjItem { + bytes obj_id = 1; + bytes value = 2; + } + repeated ObjItem obj_list = 3; +} + +// file +message ChunkList { + enum Type { + ChunkInList = 0; + ChunkInFile = 1; + ChunkInBundle = 2; + } + enum HashMethod { + Serial = 0; + } + + Type type = 1; + repeated bytes chunk_id_list = 2; + bytes file_id = 3; + optional HashMethod hash_method = 4; +} + +message FileBodyContent { + ChunkList chunk_list = 1; +} + +// people +message PeopleBodyContent { + repeated bytes ood_list = 1; + optional string name = 2; + optional bytes icon = 3; + optional string ood_work_mode = 4; +} + +message GroupRPathPermissionWeight { + string rpath = 1; + GroupFunctionPermissionWeight weight = 2; +} + +message GroupDecPermissionWeight { + bytes dec_id = 1; + optional GroupRPathPermissionWeight default_dec_weight = 2; + repeated GroupRPathPermissionWeight rpath_weight = 3; +} + +message GroupMember { + bytes id = 1; + string title = 2; + // uint64 shares = 3; delay + optional GroupGlobalPermissionWeight global_weight = 4; + optional GroupDecPermissionWeight weight = 5; +} + +/** +admin 修改管理员列表 +member 修改成员列表 +display-${scope} 修改展示信息 + ${scope}=g: 修改group信息 + ${scope}=s: 修改自身信息 + ${scope}=m: 修改任意member信息 + ${scope}=a: 修改任意admin信息 +property 修改资产信息 +conclusion 修改决议类别列表 +conclusion-${category} 修改决议类别配置 +it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) +c-${any} 其他自定义(custom)权限 +*/ + +message GroupGlobalPermissionWeight { + optional uint32 admin = 1; + optional uint32 member = 2; + optional uint32 display_group = 3; + optional uint32 display_self = 4; + optional uint32 display_member = 5; + optional uint32 display_admin = 6; + optional uint32 property = 7; +} + +message GroupCommonPermissionWeight { + string category = 1; + uint32 weight = 2; +} + +message GroupFunctionPermissionWeight { + optional uint32 it = 1; + optional uint32 conclusion = 2; + repeated GroupCommonPermissionWeight conclusion_category = 3; + repeated GroupCommonPermissionWeight custom = 4; +} + +message GroupITConfig { + repeated bytes ood_list = 8; + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms +} + +message GroupConclusionConfig { + string category = 1; + uint64 lifespan = 2; // ms +} + +message GroupConfigItem { + optional GroupITConfig it = 1; + repeated GroupConclusionConfig conclusions = 2; + optional GroupFunctionPermissionWeight weight_threshold = 3; +} + +message GroupRPathConfig { + string rpath = 1; + GroupConfigItem config = 2; +} + +message GroupDecConfig { + bytes dec_id = 1; + optional GroupConfigItem default_dec_config = 2; + repeated GroupRPathConfig rpath_configs = 3; +} + +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; + + repeated GroupMember members = 4; + + // uint64 total_equity = 5; // delay + + repeated bytes revoked_conclusions = 6; + + GroupConfigItem default_config = 7; + repeated GroupDecConfig dec_configs = 8; + + GroupGlobalPermissionWeight global_weight_threshold = 9; + GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + + uint64 version = 11; +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} + +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} + +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; +} + +// tx +message TxBodyContent { + bytes data = 1; +} + +// proof_of_service +message ProofData { + bytes data = 1; +} + +message ProofOfServiceBodyContent { + ProofData data = 1; +} \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 4daa0d4f1..ef2366de0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1051,13 +1051,13 @@ async fn main_run() { .unwrap(); } - async_std::task::sleep(Duration::from_millis(30000)).await; + async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 5usize; + let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1130,12 +1130,14 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } + async_std::task::sleep(Duration::from_millis(10000)).await; + let client = admin_stacks .get(0) .unwrap() From 497520700b28cebe6afda8c43b3fe154c320be74 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 14:41:55 +0800 Subject: [PATCH 226/553] Simplify group definition --- .../protos/standard_objects-permission.proto | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto index b2ec61f60..09f9e3684 100644 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -60,89 +60,9 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } -message GroupRPathPermissionWeight { - string rpath = 1; - GroupFunctionPermissionWeight weight = 2; -} - -message GroupDecPermissionWeight { - bytes dec_id = 1; - optional GroupRPathPermissionWeight default_dec_weight = 2; - repeated GroupRPathPermissionWeight rpath_weight = 3; -} - message GroupMember { bytes id = 1; string title = 2; - // uint64 shares = 3; delay - optional GroupGlobalPermissionWeight global_weight = 4; - optional GroupDecPermissionWeight weight = 5; -} - -/** -admin 修改管理员列表 -member 修改成员列表 -display-${scope} 修改展示信息 - ${scope}=g: 修改group信息 - ${scope}=s: 修改自身信息 - ${scope}=m: 修改任意member信息 - ${scope}=a: 修改任意admin信息 -property 修改资产信息 -conclusion 修改决议类别列表 -conclusion-${category} 修改决议类别配置 -it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) -c-${any} 其他自定义(custom)权限 -*/ - -message GroupGlobalPermissionWeight { - optional uint32 admin = 1; - optional uint32 member = 2; - optional uint32 display_group = 3; - optional uint32 display_self = 4; - optional uint32 display_member = 5; - optional uint32 display_admin = 6; - optional uint32 property = 7; -} - -message GroupCommonPermissionWeight { - string category = 1; - uint32 weight = 2; -} - -message GroupFunctionPermissionWeight { - optional uint32 it = 1; - optional uint32 conclusion = 2; - repeated GroupCommonPermissionWeight conclusion_category = 3; - repeated GroupCommonPermissionWeight custom = 4; -} - -message GroupITConfig { - repeated bytes ood_list = 8; - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms -} - -message GroupConclusionConfig { - string category = 1; - uint64 lifespan = 2; // ms -} - -message GroupConfigItem { - optional GroupITConfig it = 1; - repeated GroupConclusionConfig conclusions = 2; - optional GroupFunctionPermissionWeight weight_threshold = 3; -} - -message GroupRPathConfig { - string rpath = 1; - GroupConfigItem config = 2; -} - -message GroupDecConfig { - bytes dec_id = 1; - optional GroupConfigItem default_dec_config = 2; - repeated GroupRPathConfig rpath_configs = 3; } message CommonGroupBodyContent { @@ -152,17 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - // uint64 total_equity = 5; // delay - - repeated bytes revoked_conclusions = 6; - - GroupConfigItem default_config = 7; - repeated GroupDecConfig dec_configs = 8; - - GroupGlobalPermissionWeight global_weight_threshold = 9; - GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + repeated bytes ood_list = 5; - uint64 version = 11; + optional bytes prev_version = 6; + uint64 version_num = 7; } // simple_group @@ -184,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx From d0416c8766501af3542d7cb4c65b7fba1ffb3678 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 20:16:27 +0800 Subject: [PATCH 227/553] Move the interface to cyfs-lib --- .../src/consensus/hotstuff/hotstuff.rs | 8 +++--- .../cyfs-group/src/dec/group_manager.rs | 6 ++--- src/component/cyfs-group/src/dec/mod.rs | 6 ++--- .../cyfs-group/src/dec/rpath_control.rs | 3 ++- .../engine/storage_engine_group_state.rs | 6 ++--- .../cyfs-group/src/storage/group_storage.rs | 6 ++--- .../src/group}/delegate_factory.rs | 2 +- .../cyfs-lib/src/group/group_manager.rs | 20 ++++++++++++++ src/component/cyfs-lib/src/group/mod.rs | 7 +++++ .../cyfs-lib/src/group/rpath_client.rs | 27 +++++++++++++++++++ src/component/cyfs-lib/src/lib.rs | 6 +++-- src/tests/group-example/src/main.rs | 8 +++--- 12 files changed, 79 insertions(+), 26 deletions(-) rename src/component/{cyfs-group/src/dec => cyfs-lib/src/group}/delegate_factory.rs (98%) create mode 100644 src/component/cyfs-lib/src/group/group_manager.rs create mode 100644 src/component/cyfs-lib/src/group/mod.rs create mode 100644 src/component/cyfs-lib/src/group/rpath_client.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e142d4069..52dcdd650 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,15 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, + GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7b7fbbbe..60ddba1fb 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,11 +6,11 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; use crate::{ - storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, + NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index b4e753a27..8a43844b2 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,11 +1,9 @@ // dec framework -mod delegate_factory; +mod group_manager; mod rpath_client; mod rpath_control; -mod group_manager; -pub use delegate_factory::*; +pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 7abff1ec1..c3a25b060 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,10 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathDelegate, + PendingProposalHandler, PendingProposalMgr, }; struct RPathControlRaw { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 8b8799207..adf11c7e4 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,11 +6,11 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_lib::GroupObjectMapProcessor; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, - GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, - GROUP_STATE_PATH_RESULT_STATE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 966fa518a..fa6f4930f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,11 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-lib/src/group/delegate_factory.rs similarity index 98% rename from src/component/cyfs-group/src/dec/delegate_factory.rs rename to src/component/cyfs-lib/src/group/delegate_factory.rs index f5092dbfc..9e55ff8f4 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-lib/src/group/delegate_factory.rs @@ -1,8 +1,8 @@ +use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-lib/src/group/group_manager.rs new file mode 100644 index 000000000..7d836ae49 --- /dev/null +++ b/src/component/cyfs-lib/src/group/group_manager.rs @@ -0,0 +1,20 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +use crate::{DelegateFactory, RPathClient}; + +#[derive(Clone)] +pub struct GroupManager; + +impl GroupManager { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self) { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-lib/src/group/mod.rs new file mode 100644 index 000000000..482d9ea0d --- /dev/null +++ b/src/component/cyfs-lib/src/group/mod.rs @@ -0,0 +1,7 @@ +mod delegate_factory; +mod group_manager; +mod rpath_client; + +pub use delegate_factory::*; +pub use group_manager::*; +pub use rpath_client::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-lib/src/group/rpath_client.rs new file mode 100644 index 000000000..4162abe68 --- /dev/null +++ b/src/component/cyfs-lib/src/group/rpath_client.rs @@ -0,0 +1,27 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{GroupProposal, GroupRPath}; + +use crate::NONObjectInfo; + +struct RPathClientRaw {} + +#[derive(Clone)] +pub struct RPathClient(Arc); + +impl RPathClient { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index f74e62985..d2f02315a 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,9 +4,11 @@ mod base; mod crypto; mod default_app; mod events; +mod group; mod ndn; mod non; mod prelude; +mod requestor; mod rmeta; mod root_state; mod router_handler; @@ -17,7 +19,6 @@ mod trans; mod util; mod ws; mod zone; -mod requestor; pub use crate::util::*; pub use acl::*; @@ -26,9 +27,11 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; +pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; +pub use requestor::*; pub use rmeta::*; pub use root_state::*; pub use router_handler::*; @@ -38,7 +41,6 @@ pub use sync::*; pub use trans::*; pub use ws::*; pub use zone::*; -pub use requestor::*; // 重新导出cache相关接口,由于bdt层的依赖关系,只能放在util工程 pub use cyfs_util::cache::*; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ef2366de0..42544e51c 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,12 +505,10 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, - }; + use cyfs_group::RPathControl; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, + NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, }; use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; From c19e44794e12f74e71f2b9a0a60eee3bdc7fd2c1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 12:20:30 +0800 Subject: [PATCH 228/553] Remove the `decide` from proposal, It seems unuseful --- .../cyfs-core/protos/core_objects.proto | 9 +- .../cyfs-core/src/group/group_proposal.rs | 415 +++++++++--------- src/component/cyfs-core/src/group/mod.rs | 10 +- 3 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 487ece4bd..abd299e9d 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -352,7 +352,7 @@ message GroupProposalDescContent { message GroupProposalBodyContent { optional bytes payload = 1; - +/* message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; @@ -360,8 +360,10 @@ message GroupProposalBodyContent { } repeated Signature decide_signatures = 2; +*/ } +/* message GroupUpdateGroupPropsalParam { repeated bytes target_dec_id = 1; // the proccesor decs optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) @@ -373,6 +375,7 @@ message GroupPropsalDecideParam { bytes proposal_id = 2; bytes decide = 3; } +*/ message HotstuffBlockQc { bytes block_id = 1; @@ -431,6 +434,7 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } +/* message GroupActionDescContent { // target GroupRPath r_path = 1; @@ -441,4 +445,5 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 10aeed798..bf28aafb2 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,4 +1,4 @@ -use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; +use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use sha2::Digest; @@ -34,45 +34,44 @@ impl DescContent for GroupProposalDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone)] -pub struct GroupProposalSignature { - signature: Signature, - proponent_id: ObjectId, - decide: Vec, -} - -impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> - for GroupProposalSignature -{ - fn transform( - value: &crate::codec::protos::group_proposal_body_content::Signature, - ) -> BuckyResult { - Ok(Self { - signature: Signature::raw_decode(value.signature.as_slice())?.0, - proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, - decide: value.decide.clone(), - }) - } -} - -impl ProtobufTransform<&GroupProposalSignature> - for crate::codec::protos::group_proposal_body_content::Signature -{ - fn transform(value: &GroupProposalSignature) -> BuckyResult { - Ok(Self { - signature: value.signature.to_vec()?, - proponent_id: value.proponent_id.to_vec()?, - decide: value.decide.clone(), - }) - } -} +// #[derive(Clone)] +// pub struct GroupProposalSignature { +// signature: Signature, +// proponent_id: ObjectId, +// decide: Vec, +// } + +// impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> +// for GroupProposalSignature +// { +// fn transform( +// value: &crate::codec::protos::group_proposal_body_content::Signature, +// ) -> BuckyResult { +// Ok(Self { +// signature: Signature::raw_decode(value.signature.as_slice())?.0, +// proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, +// decide: value.decide.clone(), +// }) +// } +// } + +// impl ProtobufTransform<&GroupProposalSignature> +// for crate::codec::protos::group_proposal_body_content::Signature +// { +// fn transform(value: &GroupProposalSignature) -> BuckyResult { +// Ok(Self { +// signature: value.signature.to_vec()?, +// proponent_id: value.proponent_id.to_vec()?, +// decide: value.decide.clone(), +// }) +// } +// } #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] pub struct GroupProposalBodyContent { payload: Option>, - - decide_signatures: Vec, + // decide_signatures: Vec, } impl BodyContent for GroupProposalBodyContent { @@ -85,14 +84,14 @@ impl ProtobufTransform for GroupProposalBodyContent { fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push(GroupProposalSignature::transform(sign)?); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push(GroupProposalSignature::transform(sign)?); + // } Ok(Self { payload: value.payload, - decide_signatures, + // decide_signatures, }) } } @@ -101,16 +100,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> for crate::codec::protos::GroupProposalBodyContent { fn transform(value: &GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push( - crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, - ); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push( + // crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + // ); + // } Ok(Self { payload: value.payload.clone(), - decide_signatures, + // decide_signatures, }) } } @@ -143,17 +142,17 @@ impl GroupProposalDescContent { } impl GroupProposalBodyContent { - fn hash_decide_signature( - proposal_id: &ObjectId, - proponent_id: &ObjectId, - decide: &[u8], - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(proposal_id.as_slice()); - sha256.input(proponent_id.as_slice()); - sha256.input(decide); - sha256.result().into() - } + // fn hash_decide_signature( + // proposal_id: &ObjectId, + // proponent_id: &ObjectId, + // decide: &[u8], + // ) -> HashValue { + // let mut sha256 = sha2::Sha256::new(); + // sha256.input(proposal_id.as_slice()); + // sha256.input(proponent_id.as_slice()); + // sha256.input(decide); + // sha256.result().into() + // } } #[async_trait] @@ -182,27 +181,27 @@ pub trait GroupProposalObject { fn payload(&self) -> &Option>; fn set_payload(&mut self, payload: Option>); - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult>; - - fn decided_members_no_verify(&self) -> &Vec; - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult; - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()>; + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult>; + + // fn decided_members_no_verify(&self) -> &Vec; + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult; + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()>; } #[async_trait] @@ -231,7 +230,7 @@ impl GroupProposalObject for GroupProposal { desc, GroupProposalBodyContent { payload, - decide_signatures: vec![], + // decide_signatures: vec![], }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) @@ -252,9 +251,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { - Some(params) => { - HashValue::try_from(params.as_slice()).map(|h| Some(h)) - } + Some(params) => HashValue::try_from(params.as_slice()).map(|h| Some(h)), None => Ok(None), } } @@ -298,134 +295,130 @@ impl GroupProposalObject for GroupProposal { self.body_mut().as_mut().unwrap().content_mut().payload = payload; } - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult> { - let signs = self - .body() - .as_ref() - .unwrap() - .content() - .decide_signatures - .as_slice(); - - let proposal_id = self.desc().object_id(); - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - - let mut decides = vec![]; - - for sign in signs { - if &sign.proponent_id == member_id { - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &sign.proponent_id, - sign.decide.as_slice(), - ); - - if verifier.verify(hash.as_slice(), &sign.signature).await { - decides.push(sign.decide.as_slice()); - } else { - return Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )); - } - } - } - - Ok(decides) - } - - fn decided_members_no_verify(&self) -> &Vec { - &self.body().as_ref().unwrap().content().decide_signatures - } - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult { - let signs = &self.body().as_ref().unwrap().content().decide_signatures; - - if signs.iter().find(|s| s.proponent_id == member_id).is_some() { - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicated decide", - )); - } - - let proposal_id = self.desc().object_id(); - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.as_slice(), - ); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - let sign = signer - .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) - .await?; - - Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) - } - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()> { - let proposal_id = self.desc().object_id(); - - if decide.proposal_id() != &proposal_id { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - format!( - "proposal id not match for decide signature: {}/{}", - proposal_id, - decide.proposal_id() - ), - )); - } - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.decide(), - ); - - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - if verifier.verify(hash.as_slice(), decide.signature()).await { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - for exist in signs.iter() { - if &exist.proponent_id == &member_id && exist.decide == decide.decide() { - return Ok(()); - } - } - - signs.push(GroupProposalSignature { - signature: decide.signature().clone(), - proponent_id: member_id, - decide: Vec::from(decide.decide()), - }); - - Ok(()) - } else { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )) - } - } + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult> { + // let signs = self + // .body() + // .as_ref() + // .unwrap() + // .content() + // .decide_signatures + // .as_slice(); + + // let proposal_id = self.desc().object_id(); + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + // let mut decides = vec![]; + + // for sign in signs { + // if &sign.proponent_id == member_id { + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &sign.proponent_id, + // sign.decide.as_slice(), + // ); + + // if verifier.verify(hash.as_slice(), &sign.signature).await { + // decides.push(sign.decide.as_slice()); + // } else { + // return Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )); + // } + // } + // } + + // Ok(decides) + // } + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult { + // let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + // if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + // return Err(BuckyError::new( + // BuckyErrorCode::AlreadyExists, + // "duplicated decide", + // )); + // } + + // let proposal_id = self.desc().object_id(); + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.as_slice(), + // ); + + // let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + // let sign = signer + // .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + // .await?; + + // Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) + // } + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()> { + // let proposal_id = self.desc().object_id(); + + // if decide.proposal_id() != &proposal_id { + // return Err(BuckyError::new( + // BuckyErrorCode::NotMatch, + // format!( + // "proposal id not match for decide signature: {}/{}", + // proposal_id, + // decide.proposal_id() + // ), + // )); + // } + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.decide(), + // ); + + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + // if verifier.verify(hash.as_slice(), decide.signature()).await { + // let signs = &mut self + // .body_mut() + // .as_mut() + // .unwrap() + // .content_mut() + // .decide_signatures; + // for exist in signs.iter() { + // if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + // return Ok(()); + // } + // } + + // signs.push(GroupProposalSignature { + // signature: decide.signature().clone(), + // proponent_id: member_id, + // decide: Vec::from(decide.decide()), + // }); + + // Ok(()) + // } else { + // Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )) + // } + // } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b2885d637..4310f48a5 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,13 +1,15 @@ mod group_consensus_block; mod group_proposal; -mod group_proposal_decide_param; +// mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_update_group_proposal_param; +// mod group_update_group_proposal_param; +mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; -pub use group_proposal_decide_param::*; +// pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_update_group_proposal_param::*; +// pub use group_update_group_proposal_param::*; +pub use group_protocol::*; From 9aff2a3b3ba4baba55215f3859a923142d2f6777 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 20:52:45 +0800 Subject: [PATCH 229/553] Prepare for export interface to SDK --- .../cyfs-core/protos/core_objects.proto | 2 +- src/component/cyfs-core/src/coreobj.rs | 1 + src/component/cyfs-core/src/group/mod.rs | 2 - src/component/cyfs-group-lib/Cargo.toml | 34 ++ .../{cyfs-group => cyfs-group-lib}/build.rs | 27 +- .../protos/group_bft_protocol.proto | 63 +++ src/component/cyfs-group-lib/readme.md | 14 + .../src/delegate.rs} | 18 +- .../src}/group_manager.rs | 6 +- .../mod.rs => cyfs-group-lib/src/lib.rs} | 6 +- .../cyfs-group-lib/src/objects/certificate.rs | 190 ++++++++ .../cyfs-group-lib/src/objects/codec/mod.rs | 3 + .../src/objects/group_command.rs | 428 ++++++++++++++++++ .../src/objects/group_decide_proposal.rs | 0 .../src/objects/group_rpath_status.rs | 6 +- .../src/objects/group_update_proposal.rs | 0 .../cyfs-group-lib/src/objects/mod.rs | 12 + .../src}/rpath_client.rs | 3 +- src/component/cyfs-group/Cargo.toml | 3 +- .../protos/group_bft_protocol.proto | 23 - .../src/consensus/hotstuff/hotstuff.rs | 60 +-- .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 7 +- .../cyfs-group/src/dec/group_events.rs | 42 ++ .../cyfs-group/src/dec/group_manager.rs | 94 ++-- src/component/cyfs-group/src/dec/mod.rs | 2 + .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec/rpath_control.rs | 8 +- .../src/dec_state/dec_state_requestor.rs | 6 +- .../src/dec_state/dec_state_synchronizer.rs | 64 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/helper/mod.rs | 2 - src/component/cyfs-group/src/helper/verify.rs | 16 - src/component/cyfs-group/src/lib.rs | 4 - src/component/cyfs-group/src/network/mod.rs | 2 + .../src/{objects => network}/protocol.rs | 306 +++---------- src/component/cyfs-group/src/objects/mod.rs | 9 - .../cyfs-group/src/storage/dec_storage.rs | 9 +- .../engine/storage_engine_group_state.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 7 +- src/component/cyfs-group/src/utils.rs | 8 - src/component/cyfs-lib/src/lib.rs | 2 - 42 files changed, 977 insertions(+), 529 deletions(-) create mode 100644 src/component/cyfs-group-lib/Cargo.toml rename src/component/{cyfs-group => cyfs-group-lib}/build.rs (66%) create mode 100644 src/component/cyfs-group-lib/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group-lib/readme.md rename src/component/{cyfs-lib/src/group/delegate_factory.rs => cyfs-group-lib/src/delegate.rs} (81%) rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/group_manager.rs (100%) rename src/component/{cyfs-lib/src/group/mod.rs => cyfs-group-lib/src/lib.rs} (56%) create mode 100644 src/component/cyfs-group-lib/src/objects/certificate.rs create mode 100644 src/component/cyfs-group-lib/src/objects/codec/mod.rs create mode 100644 src/component/cyfs-group-lib/src/objects/group_command.rs rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_decide_proposal.rs (100%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_rpath_status.rs (93%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_update_proposal.rs (100%) create mode 100644 src/component/cyfs-group-lib/src/objects/mod.rs rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/rpath_client.rs (94%) delete mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group/src/dec/group_events.rs delete mode 100644 src/component/cyfs-group/src/helper/verify.rs rename src/component/cyfs-group/src/{objects => network}/protocol.rs (70%) delete mode 100644 src/component/cyfs-group/src/objects/mod.rs delete mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index abd299e9d..742c14904 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -446,4 +446,4 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; } -*/ \ No newline at end of file +*/ diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3d53a082f..8eb96a930 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupAction = 704, GroupQuorumCertificate = 705, + GroupCommand = 706, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4310f48a5..d7134a3c0 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,7 +4,6 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; @@ -12,4 +11,3 @@ pub use group_proposal::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; -pub use group_protocol::*; diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml new file mode 100644 index 000000000..e7cfda851 --- /dev/null +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -0,0 +1,34 @@ + +[package] +name = 'cyfs-group-lib' +version = '0.1.1' +authors = ['zhangzhen '] +edition = '2021' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +prost-build = { version = '0.9.0' } +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +itertools = "0.10.3" +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group-lib/build.rs similarity index 66% rename from src/component/cyfs-group/build.rs rename to src/component/cyfs-group-lib/build.rs index 8d4efe9c9..206d6bc6f 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group-lib/build.rs @@ -37,28 +37,13 @@ fn gen_protos() { } fn main() { - println!("cargo:rerun-if-env-changed=VERSION"); - println!("cargo:rerun-if-env-changed=CHANNEL"); - println!("cargo:rerun-if-env-changed=TARGET"); - println!( - "cargo:rustc-env=VERSION={}", - std::env::var("VERSION").unwrap_or("0".to_owned()) - ); - println!( - "cargo:rustc-env=CHANNEL={}", - std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) - ); - println!( - "cargo:rustc-env=TARGET={}", - std::env::var("TARGET").unwrap() - ); - + println!("cargo:rerun-if-changed=protos"); println!( - "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + "cargo:warning={}", + format!( + "cyfs-core run build script, OUT_DIR={}", + std::env::var("OUT_DIR").unwrap() + ) ); - - println!("cargo:rerun-if-changed=protos"); - gen_protos(); } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto new file mode 100644 index 000000000..2bfdd8d21 --- /dev/null +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -0,0 +1,63 @@ + +syntax = "proto3"; + +message HotstuffBlockQCVote { + bytes block_id = 1; + optional bytes prev_block_id = 2; + uint64 round = 3; + bytes voter = 4; + bytes signature = 5; +} + +message HotstuffTimeoutVote { + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; +} + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} + +// GroupCommand + +message GroupCommandDescContent { + +} + +message GroupCommandNewRPath { + bytes group_id = 1; + string rpath = 2; + optional bytes with_block = 3; // Block.to_vec() +} + +message GroupCommandExecute { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId +} + +message GroupCommandExecuteResult { + optional bytes result_state_id = 1; // ObjectId + optional bytes receipt = 2; // NONObjectInfo.to_vec() + optional bytes context = 3; // Vec +} + +message GroupCommandVerify { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec +} + +message GroupCommandCommited { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec + bytes block = 6; // Block.to_vec() +} diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group-lib/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-lib/src/group/delegate_factory.rs b/src/component/cyfs-group-lib/src/delegate.rs similarity index 81% rename from src/component/cyfs-lib/src/group/delegate_factory.rs rename to src/component/cyfs-group-lib/src/delegate.rs index 9e55ff8f4..21b1e6346 100644 --- a/src/component/cyfs-lib/src/group/delegate_factory.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,25 +1,17 @@ -use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult>; - - async fn on_state_changed( &self, group_id: &ObjectId, rpath: &str, - state_id: Option, - pre_state_id: Option, - ); + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()>; } pub struct ExecuteResult { @@ -30,8 +22,6 @@ pub struct ExecuteResult { #[async_trait::async_trait] pub trait RPathDelegate: Sync + Send { - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; - async fn on_execute( &self, proposal: &GroupProposal, @@ -45,7 +35,7 @@ pub trait RPathDelegate: Sync + Send { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult; + ) -> BuckyResult<()>; async fn on_commited( &self, diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs similarity index 100% rename from src/component/cyfs-lib/src/group/group_manager.rs rename to src/component/cyfs-group-lib/src/group_manager.rs index 7d836ae49..8c82bc9e1 100644 --- a/src/component/cyfs-lib/src/group/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -6,15 +6,15 @@ use crate::{DelegateFactory, RPathClient}; pub struct GroupManager; impl GroupManager { - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { unimplemented!() } - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn unregister(&self) { unimplemented!() } } diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-group-lib/src/lib.rs similarity index 56% rename from src/component/cyfs-lib/src/group/mod.rs rename to src/component/cyfs-group-lib/src/lib.rs index 482d9ea0d..199307bcc 100644 --- a/src/component/cyfs-lib/src/group/mod.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,7 +1,9 @@ -mod delegate_factory; +mod delegate; mod group_manager; +mod objects; mod rpath_client; -pub use delegate_factory::*; +pub use delegate::*; pub use group_manager::*; +pub use objects::*; pub use rpath_client::*; diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs new file mode 100644 index 000000000..32b1b53c8 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -0,0 +1,190 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, HashValue, ObjectId, ObjectLink, ProtobufDecode, + ProtobufEncode, ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, + RawEncodePurpose, RsaCPUObjectSigner, Signature, SignatureSource, Signer, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffBlockQcVote)] +pub struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub prev_block_id: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.block_id().object_id(); + let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let signature = signer + .sign( + hash.as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + block_id: block_id.clone(), + round, + voter: local_device_id, + signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) + } + + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: super::codec::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for super::codec::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffTimeoutVote)] +pub struct HotstuffTimeoutVote { + pub high_qc: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: Option, + round: u64, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_device_id, + signature, + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + } + + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: super::codec::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffTimeoutVote { + high_qc: match value.high_qc.as_ref() { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} diff --git a/src/component/cyfs-group-lib/src/objects/codec/mod.rs b/src/component/cyfs-group-lib/src/objects/codec/mod.rs new file mode 100644 index 000000000..66df9053f --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/codec/mod.rs @@ -0,0 +1,3 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs new file mode 100644 index 000000000..912ced438 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -0,0 +1,428 @@ +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, NamedObjType, NamedObject, + NamedObjectBase, NamedObjectBuilder, NamedObjectId, ObjectId, ProtobufDecode, ProtobufEncode, + ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, RawEncode, RawEncodePurpose, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, +}; + +use cyfs_core::{CoreObjectType, GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandDescContent)] +pub struct GroupCommandDescContent {} + +impl DescContent for GroupCommandDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupCommand as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupCommandDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Debug)] +pub enum GroupCommandType { + NewRPath, + Execute, + ExecuteResult, + Verify, + Commited, +} + +#[derive(Clone, RawEncode, RawDecode)] +pub enum GroupCommandBodyContent { + NewRPath(GroupCommandNewRPath), + Execute(GroupCommandExecute), + ExecuteResult(GroupCommandExecuteResult), + Verify(GroupCommandVerify), + Commited(GroupCommandCommited), +} + +pub type GroupCommandObjectType = NamedObjType; +pub type GroupCommandBuilder = NamedObjectBuilder; + +pub type GroupCommandId = NamedObjectId; +pub type GroupCommand = NamedObjectBase; + +impl GroupCommandBodyContent { + pub fn cmd_type(&self) -> GroupCommandType { + match self { + GroupCommandBodyContent::NewRPath(_) => GroupCommandType::NewRPath, + GroupCommandBodyContent::Execute(_) => GroupCommandType::Execute, + GroupCommandBodyContent::ExecuteResult(_) => GroupCommandType::ExecuteResult, + GroupCommandBodyContent::Verify(_) => GroupCommandType::Verify, + GroupCommandBodyContent::Commited(_) => GroupCommandType::Commited, + } + } +} + +pub trait GroupCommandObject { + fn cmd_type(&self) -> GroupCommandType; + fn into_cmd(self) -> GroupCommandBodyContent; +} + +impl GroupCommandObject for GroupCommand { + fn cmd_type(&self) -> GroupCommandType { + self.body().as_ref().unwrap().content().cmd_type() + } + + fn into_cmd(self) -> GroupCommandBodyContent { + self.into_body().unwrap().into_content() + } +} + +impl BodyContent for GroupCommandBodyContent { + fn version(&self) -> u8 { + 0 + } + + fn format(&self) -> u8 { + cyfs_base::OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupCommandBodyContent") + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandNewRPath)] +pub struct GroupCommandNewRPath { + pub group_id: ObjectId, + pub rpath: String, + pub with_block: Option, +} + +impl ProtobufTransform for GroupCommandNewRPath { + fn transform(value: super::codec::protos::GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: ObjectId::raw_decode(value.group_id.as_slice())?.0, + with_block: match value.with_block.as_ref() { + Some(buf) => Some(GroupConsensusBlock::raw_decode(buf.as_slice())?.0), + None => None, + }, + rpath: value.rpath, + }) + } +} + +impl ProtobufTransform<&GroupCommandNewRPath> for super::codec::protos::GroupCommandNewRPath { + fn transform(value: &GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: value.group_id.to_vec()?, + rpath: value.rpath.clone(), + with_block: match value.with_block.as_ref() { + Some(block) => Some(block.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecute)] +pub struct GroupCommandExecute { + pub proposal: GroupProposal, + pub prev_state_id: Option, +} + +impl ProtobufTransform for GroupCommandExecute { + fn transform(value: super::codec::protos::GroupCommandExecute) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecute> for super::codec::protos::GroupCommandExecute { + fn transform(value: &GroupCommandExecute) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecuteResult)] +pub struct GroupCommandExecuteResult { + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform + for GroupCommandExecuteResult +{ + fn transform(value: super::codec::protos::GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecuteResult> + for super::codec::protos::GroupCommandExecuteResult +{ + fn transform(value: &GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandVerify)] +pub struct GroupCommandVerify { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform for GroupCommandVerify { + fn transform(value: super::codec::protos::GroupCommandVerify) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + receipt: match value.receipt { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupCommandVerify { + fn transform(value: &GroupCommandVerify) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] +pub struct GroupCommandCommited { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, + pub block: GroupConsensusBlock, +} + +impl ProtobufTransform for GroupCommandCommited { + fn transform(value: super::codec::protos::GroupCommandCommited) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, + }, + block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { + fn transform(value: &GroupCommandCommited) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + block: value.block.to_vec()?, + }) + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandNewRPath) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::NewRPath(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecute) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Execute(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecuteResult) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::ExecuteResult(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandVerify) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Verify(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandCommited) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Commited(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::NewRPath(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect NewRPath", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Execute(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Execute", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::ExecuteResult(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect ExecuteResult", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Verify(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Verify", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Commited(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Commited", cmd_type), + )), + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_decide_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs similarity index 93% rename from src/component/cyfs-group/src/objects/group_rpath_status.rs rename to src/component/cyfs-group-lib/src/objects/group_rpath_status.rs index bfc9bc5d2..ae656b5ad 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs @@ -21,7 +21,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -42,7 +42,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -56,7 +56,7 @@ impl RawEncode for GroupRPathStatus { impl<'de> RawDecode<'de> for GroupRPathStatus { fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let proto = super::codec::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::Failed, msg) diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_update_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_update_proposal.rs diff --git a/src/component/cyfs-group-lib/src/objects/mod.rs b/src/component/cyfs-group-lib/src/objects/mod.rs new file mode 100644 index 000000000..668afe8cf --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/mod.rs @@ -0,0 +1,12 @@ +mod group_command; +// mod group_decide_proposal; +mod group_rpath_status; +// mod group_update_proposal; +mod certificate; +mod codec; + +pub use group_command::*; +// pub use group_decide_proposal::*; +pub use group_rpath_status::*; +// pub use group_update_proposal::*; +pub use certificate::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs similarity index 94% rename from src/component/cyfs-lib/src/group/rpath_client.rs rename to src/component/cyfs-group-lib/src/rpath_client.rs index 4162abe68..2fea6dcf7 100644 --- a/src/component/cyfs-lib/src/group/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -5,8 +5,7 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupProposal, GroupRPath}; - -use crate::NONObjectInfo; +use cyfs_lib::NONObjectInfo; struct RPathClientRaw {} diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 4a7aae6c2..1caf5b9a4 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,5 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto deleted file mode 100644 index 621186522..000000000 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ /dev/null @@ -1,23 +0,0 @@ - -syntax = "proto3"; - -message HotstuffBlockQCVote { - bytes block_id = 1; - optional bytes prev_block_id = 2; - uint64 round = 3; - bytes voter = 4; - bytes signature = 5; -} - -message HotstuffTimeoutVote { - optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) - uint64 round = 2; - bytes voter = 3; - bytes signature = 4; -} - -message GroupRPathStatus { - bytes block_desc = 1; // GroupConsensusBlockDescContent - bytes certificate = 2; // HotstuffBlockQC for block - repeated bytes status_list = 4; // Array> -} \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52dcdd650..cc555298b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,16 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; +use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, }; /** @@ -51,7 +52,7 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -81,7 +82,7 @@ impl Hotstuff { rx_message, proposal_consumer, state_pusher_runner, - delegate, + event_notifier, rpath2, ) .run() @@ -224,7 +225,7 @@ struct HotstuffRunner { tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, synchronizer: Synchronizer, rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, @@ -251,7 +252,7 @@ impl HotstuffRunner { rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, state_pusher: StatePusher, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); @@ -307,7 +308,7 @@ impl HotstuffRunner { network_sender, tx_message, rx_message, - delegate, + event_notifier, synchronizer, non_driver, rpath, @@ -511,37 +512,25 @@ impl HotstuffRunner { context: proposal_exe_info.context.clone(), }; - if self - .delegate - .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) + self + .event_notifier + .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); err - })? - { - log::debug!( - "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + })?; - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); - return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); - } + prev_state_id = proposal_exe_info.result_state; } assert_eq!( @@ -840,11 +829,10 @@ impl HotstuffRunner { None => None, }; - self.delegate + self.event_notifier .on_commited( &proposal_obj, pre_state_id, - self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1625,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { + match self.event_notifier.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ad3a21e35..398274723 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -14,9 +14,10 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::network::NONDriverHelper; #[derive(Clone)] pub(crate) struct Committee { diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index f44260a04..6a9735a7f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,13 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, -}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, HotstuffTimeout, HotstuffTimeoutSign, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::Committee; pub(crate) struct VoteMgr { committee: Committee, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs new file mode 100644 index 000000000..67f79cfdd --- /dev/null +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -0,0 +1,42 @@ +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_group_lib::ExecuteResult; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone)] +pub(crate) struct RPathEventNotifier {} + +impl RPathEventNotifier { + pub fn new() -> Self { + unimplemented!() + } + + pub async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 60ddba1fb..95bdbcd17 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,15 +2,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, - NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, + RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -22,7 +22,6 @@ type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - delegate_by_dec: HashMap>, control_by_group: ControlByGroup, client_by_group: ClientByGroup, } @@ -33,6 +32,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,12 +54,12 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { control_by_group: ControlByGroup::default(), client_by_group: ClientByGroup::default(), - delegate_by_dec: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -69,29 +69,12 @@ impl GroupManager { Ok(mgr) } - pub async fn register( - &self, - dec_id: DecAppId, - delegate_factory: Box, - ) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec - .insert(dec_id.object_id().clone(), delegate_factory); - Ok(()) - } - - pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec.remove(dec_id.object_id()); - Ok(()) - } - pub async fn find_rpath_control( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -204,7 +187,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, Some(&block), Some(&remote), ) @@ -220,7 +203,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -236,7 +219,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -252,7 +235,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -268,7 +251,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -284,7 +267,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -331,7 +314,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::No, + false, None, Some(&remote), ) @@ -378,7 +361,7 @@ impl GroupManager { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -398,7 +381,6 @@ impl GroupManager { { // write - let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); @@ -411,6 +393,7 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -424,40 +407,25 @@ impl GroupManager { let store = match store { Ok(store) => Some(store), Err(e) => { - if let IsCreateRPath::No = is_auto_create { - return Err(e); - } if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - None + + self.on_new_rpath_request(group_id, dec_id, rpath, block) + .await?; + + if !is_auto_create { + return Err(e); + } else { + None + } } else { return Err(e); } } }; - // TODO: query group - let group = non_driver - .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) - .await?; - let mut raw = self.write().await; - let delegate = { - let delegate_factory = raw.delegate_by_dec.get(dec_id); - if delegate_factory.is_none() { - return Err(BuckyError::new( - BuckyErrorCode::DecNotRunning, - "dec not running for the rpath-control", - )); - } - let delegate_factory = delegate_factory.unwrap(); - - delegate_factory - .create_rpath_delegate(&group, rpath, block) - .await? - }; - let store = match store { Some(store) => store, None => { @@ -489,7 +457,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - Arc::new(delegate), + event_notifier, network_sender, non_driver, store, @@ -501,4 +469,14 @@ impl GroupManager { } } } + + async fn on_new_rpath_request( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 8a43844b2..2ad717514 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,9 +1,11 @@ // dec framework +mod group_events; mod group_manager; mod rpath_client; mod rpath_control; +pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 8a1dd34a7..08be0f5a0 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -224,10 +224,10 @@ impl RPathClient { HotstuffMessage::Timeout(tc) => unreachable!(), HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), HotstuffMessage::LastStateRequest => unreachable!(), - HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffMessage::StateChangeNotify(header_block, qc) => { self.0 .state_sync - .on_state_change(header_block, qc_block, remote) + .on_state_change(header_block, qc, remote) .await } HotstuffMessage::ProposalResult(proposal_id, result) => { diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c3a25b060..593d82db4 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::RPathDelegate; +use cyfs_group_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, + PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; struct RPathControlRaw { @@ -26,7 +26,7 @@ impl RPathControl { local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, - delegate: Arc>, + event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, store: GroupStorage, @@ -46,7 +46,7 @@ impl RPathControl { network_sender.clone(), non_driver, pending_proposal_consumer, - delegate, + event_notifier, rpath.clone(), ); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 790429c6c..8fd67496b 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,13 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, - CHANNEL_CAPACITY, -}; +use crate::{storage::DecStorage, Committee, HotstuffMessage, CHANNEL_CAPACITY}; use super::{CallReplyNotifier, CallReplyWaiter}; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 7272b3882..e019db892 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -2,15 +2,12 @@ use std::{collections::HashSet, sync::Arc}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, -}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, Committee, CHANNEL_CAPACITY, @@ -21,13 +18,9 @@ use super::{CallReplyNotifier, CallReplyWaiter}; enum DecStateSynchronizerMessage { ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, ), - StateChange(GroupConsensusBlock, GroupConsensusBlock), + StateChange(GroupConsensusBlock, HotstuffBlockQC), DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } @@ -81,11 +74,7 @@ impl DecStateSynchronizer { pub async fn on_proposal_complete( &self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { self.0 @@ -100,13 +89,13 @@ impl DecStateSynchronizer { pub async fn on_state_change( &self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { self.0 .tx_dec_state_sync_message .send(( - DecStateSynchronizerMessage::StateChange(header_block, qc_block), + DecStateSynchronizerMessage::StateChange(header_block, qc), remote, )) .await; @@ -121,7 +110,7 @@ struct DecStateSynchronizerCache { struct UpdateNotifyInfo { header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remotes: HashSet, group_chunk_id: ObjectId, group: Group, @@ -178,15 +167,11 @@ impl DecStateSynchronizerRunner { async fn handle_proposal_complete( &mut self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { match result { - Ok((result, header_block, qc_block)) => { + Ok((result, header_block, qc)) => { if header_block .proposals() .iter() @@ -200,7 +185,7 @@ impl DecStateSynchronizerRunner { } if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_err() { @@ -226,11 +211,11 @@ impl DecStateSynchronizerRunner { async fn handle_state_change( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_ok() { @@ -251,11 +236,7 @@ impl DecStateSynchronizerRunner { for remote in notify_info.remotes.iter() { match self .store - .sync( - ¬ify_info.header_block, - ¬ify_info.qc_block, - remote.clone(), - ) + .sync(¬ify_info.header_block, ¬ify_info.qc, remote.clone()) .await { Ok(_) => { @@ -264,7 +245,7 @@ impl DecStateSynchronizerRunner { state_cache: DecStorageCache { state: notify_info.header_block.result_state_id().clone(), header_block: notify_info.header_block.clone(), - qc_block: notify_info.qc_block.clone(), + qc: notify_info.qc.clone(), }, group_chunk_id: notify_info.group_chunk_id, group: notify_info.group.clone(), @@ -316,14 +297,9 @@ impl DecStateSynchronizerRunner { async fn push_update_notify( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { - if qc_block.qc().is_none() { - log::warn!("the qc is none for qc-block({})", qc_block.block_id()); - return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); - } - if let Some(notify) = self.update_notifies.as_mut() { match notify.header_block.height().cmp(&header_block.height()) { std::cmp::Ordering::Less => {} @@ -338,11 +314,7 @@ impl DecStateSynchronizerRunner { if header_block.check() && self .committee - .verify_block_desc_with_qc( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - remote, - ) + .verify_block_desc_with_qc(header_block.named_object().desc(), &qc, remote) .await .is_ok() { @@ -354,7 +326,7 @@ impl DecStateSynchronizerRunner { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, - qc_block: qc_block, + qc: qc, remotes: HashSet::from([remote]), group_chunk_id, group, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b1506a192..571c1ca13 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -194,7 +194,11 @@ impl StateChanggeRunner { .post_message( HotstuffMessage::ProposalResult( exe_info.proposal, - Ok((receipt, block.clone(), qc_block.clone())), + Ok(( + receipt, + block.clone(), + qc_block.qc().as_ref().unwrap().clone(), + )), ), rpath.clone(), &proposer, @@ -320,7 +324,7 @@ impl StateChanggeRunner { let msg = HotstuffMessage::StateChangeNotify( progress.header_block.clone(), - progress.qc_block.clone(), + progress.qc_block.qc().as_ref().unwrap().clone(), ); if notify_targets.len() > 0 { diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index ce36043a3..4d3f1b1c6 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,5 +1,3 @@ mod timer; -mod verify; pub use timer::*; -pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs deleted file mode 100644 index ef3e34495..000000000 --- a/src/component/cyfs-group/src/helper/verify.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, -}; - -use crate::GroupRPathStatus; - -pub async fn verify_rpath_value( - value: &GroupRPathStatus, - sub_path: &str, - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - unimplemented!() -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index ba8e83569..c493f13c5 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -4,10 +4,8 @@ mod dec; mod dec_state; mod helper; mod network; -mod objects; mod statepath; mod storage; -mod utils; pub use consensus::*; pub use constant::*; @@ -15,7 +13,5 @@ pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; pub use network::*; -pub use objects::*; pub use statepath::*; pub(crate) use storage::*; -pub use utils::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index f79e67dd4..096bd0950 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,7 +1,9 @@ mod listener; mod non_driver; +mod protocol; mod sender; pub(crate) use listener::*; pub use non_driver::*; +pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs similarity index 70% rename from src/component/cyfs-group/src/objects/protocol.rs rename to src/component/cyfs-group/src/network/protocol.rs index 932e5cd46..7e32fdc4d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -1,16 +1,8 @@ -pub mod protos { - include!(concat!(env!("OUT_DIR"), "/mod.rs")); -} - use cyfs_base::*; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_group_lib::{GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; use itertools::Itertools; -use sha2::Digest; - -use crate::GroupRPathStatus; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { @@ -96,15 +88,11 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, - ), // (proposal-id, (ExecuteResult, block, qc-block)) + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, + ), // (proposal-id, (ExecuteResult, block, qc)) QueryState(String), VerifiableState(String, BuckyResult), } @@ -151,8 +139,8 @@ impl std::fmt::Debug for HotstuffMessage { "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest => { @@ -169,8 +157,8 @@ impl std::fmt::Debug for HotstuffMessage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) }) ) @@ -214,16 +202,12 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) LastStateRequest(ProtocolAddress), ProposalResult( ObjectId, Result< - ( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - ), + (Option, GroupConsensusBlock, HotstuffBlockQC), (BuckyError, ProtocolAddress), >, ), // (proposal-id, ExecuteResult) @@ -276,8 +260,8 @@ impl std::fmt::Debug for HotstuffPackage { "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest(_) => { @@ -296,8 +280,8 @@ impl std::fmt::Debug for HotstuffPackage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ); Ok(ok) } @@ -394,23 +378,25 @@ fn decode_with_length<'de, O: RawDecode<'de>>( impl RawEncode for HotstuffPackage { fn raw_measure(&self, purpose: &Option) -> BuckyResult { let len = match self { - HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::Block(b) => 3 + b.raw_measure(purpose)?, HotstuffPackage::BlockVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::TimeoutVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::Timeout(addr, tc) => { - 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + tc.raw_measure(purpose)? } HotstuffPackage::SyncRequest(addr, min, max) => { - addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + + min.raw_measure(purpose)? + + max.raw_measure(purpose)? } HotstuffPackage::StateChangeNotify(block, qc) => { - 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + 3 + qc.raw_measure(purpose)? } - HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::LastStateRequest(addr) => 2 + addr.raw_measure(purpose)?, HotstuffPackage::ProposalResult(id, result) => { id.raw_measure(purpose)? + match result { @@ -418,22 +404,23 @@ impl RawEncode for HotstuffPackage { non.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + + 3 + block_qc.raw_measure(purpose)? } Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } HotstuffPackage::QueryState(addr, sub_path) => { - addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } HotstuffPackage::VerifiableState(sub_path, result) => { sub_path.raw_measure(purpose)? + match result { - Ok(status) => status.raw_measure(purpose)?, + Ok(status) => 3 + status.raw_measure(purpose)?, Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } @@ -451,43 +438,43 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::Block(b) => { buf[0] = 0; let buf = &mut buf[1..]; - b.raw_encode(buf, purpose) + encode_with_length(buf, b, purpose, 3) } HotstuffPackage::BlockVote(addr, vote) => { buf[0] = 1; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::TimeoutVote(addr, vote) => { buf[0] = 2; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::Timeout(addr, tc) => { buf[0] = 3; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - tc.raw_encode(buf, purpose) + encode_with_length(buf, tc, purpose, 3) } HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; + encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; - let buf = max.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + max.raw_encode(buf, purpose) } HotstuffPackage::StateChangeNotify(block, qc) => { buf[0] = 5; let buf = &mut buf[1..]; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } HotstuffPackage::LastStateRequest(addr) => { buf[0] = 6; let buf = &mut buf[1..]; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; @@ -501,19 +488,19 @@ impl RawEncode for HotstuffPackage { Ok((non, block, qc)) => { let buf = non.raw_encode(buf, purpose)?; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } HotstuffPackage::QueryState(addr, sub_path) => { buf[0] = 8; let buf = &mut buf[1..]; - let buf = sub_path.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2)?; + sub_path.raw_encode(buf, purpose) } HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; @@ -523,10 +510,10 @@ impl RawEncode for HotstuffPackage { let buf = &mut buf[1..]; let buf = sub_path.raw_encode(buf, purpose)?; match result { - Ok(status) => status.raw_encode(buf, purpose), + Ok(status) => encode_with_length(buf, status, purpose, 3), Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } @@ -542,49 +529,49 @@ impl<'de> RawDecode<'de> for HotstuffPackage { match pkg_type { 0 => { let buf = &buf[1..]; - let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (b, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } @@ -596,7 +583,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { true => { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), @@ -605,7 +592,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } @@ -613,8 +600,8 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } 8 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } @@ -624,13 +611,13 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (sub_path, buf) = String::raw_decode(buf)?; match is_ok { true => { - let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + let (status, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), @@ -698,188 +685,5 @@ impl ProtocolAddress { } } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] -pub(crate) struct HotstuffBlockQCVote { - pub block_id: ObjectId, - pub prev_block_id: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let block_id = block.block_id().object_id(); - let round = block.round(); - - log::debug!( - "[block vote] local: {:?}, vote hash {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let hash = Self::hash_content(block_id, block.prev_block_id(), round); - - log::debug!( - "[block vote] local: {:?}, vote sign {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let signature = signer - .sign( - hash.as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - block_id: block_id.clone(), - round, - voter: local_device_id, - signature, - prev_block_id: block.prev_block_id().map(|id| id.clone()), - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) - } - - fn hash_content( - block_id: &ObjectId, - prev_block_id: Option<&ObjectId>, - round: u64, - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(block_id.as_slice()); - sha256.input(round.to_le_bytes()); - if let Some(prev_block_id) = prev_block_id { - sha256.input(prev_block_id.as_slice()); - } - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffBlockQCVote { - fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, - round: value.round, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), - None => None, - }, - }) - } -} - -impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { - fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { - let ret = crate::protos::HotstuffBlockQcVote { - block_id: value.block_id.to_vec()?, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(id.to_vec()?), - None => None, - }, - }; - - Ok(ret) - } -} - -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] -pub(crate) struct HotstuffTimeoutVote { - pub high_qc: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffTimeoutVote { - pub async fn new( - high_qc: Option, - round: u64, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let signature = signer - .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - high_qc, - round, - voter: local_device_id, - signature, - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) - } - - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(high_qc_round.to_le_bytes()); - sha256.input(round.to_le_bytes()); - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffTimeoutVote { - fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { - let high_qc = if value.high_qc().len() == 0 { - None - } else { - Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) - }; - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - round: value.round, - high_qc, - }) - } -} - -impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { - fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { - let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc.as_ref() { - Some(qc) => Some(qc.to_vec()?), - None => None, - }, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - }; - - Ok(ret) - } -} - #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs deleted file mode 100644 index 5d1a8b13f..000000000 --- a/src/component/cyfs-group/src/objects/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod group_decide_proposal; -mod group_rpath_status; -mod group_update_proposal; -mod protocol; - -pub use group_decide_proposal::*; -pub use group_rpath_status::*; -pub use group_update_proposal::*; -pub use protocol::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 60a45724f..0d937487c 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -5,16 +5,17 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; +use crate::STATE_PATH_SEPARATOR; #[derive(Clone)] pub struct DecStorageCache { pub state: Option, pub header_block: GroupConsensusBlock, - pub qc_block: GroupConsensusBlock, + pub qc: HotstuffBlockQC, } #[derive(Clone)] @@ -42,7 +43,7 @@ impl DecStorage { pub async fn sync( &self, header_block: &GroupConsensusBlock, - qc_block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index adf11c7e4..63158a865 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_lib::GroupObjectMapProcessor; +use cyfs_group_lib::GroupObjectMapProcessor; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index fa6f4930f..a1a681259 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; +use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, + STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs deleted file mode 100644 index 5d005a726..000000000 --- a/src/component/cyfs-group/src/utils.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cyfs_base::ObjectId; - -pub type Round = u64; - -pub enum IsCreateRPath { - No, - Yes, -} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index d2f02315a..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,7 +4,6 @@ mod base; mod crypto; mod default_app; mod events; -mod group; mod ndn; mod non; mod prelude; @@ -27,7 +26,6 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; -pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; From 6e8b288b6b6107a1cb1527ff14129160cc89fef8 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 12:15:59 +0800 Subject: [PATCH 230/553] Implement the events with post_object --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- .../cyfs-group/src/dec/group_events.rs | 120 +++++++++++++++--- .../cyfs-group/src/dec/group_manager.rs | 50 ++++++-- .../cyfs-group/src/dec/rpath_client.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 19 ++- .../cyfs-stack/src/stack/group_non_driver.rs | 8 +- 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index cc555298b..eaaaed06e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -514,7 +514,7 @@ impl HotstuffRunner { self .event_notifier - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal.clone(), prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -831,14 +831,14 @@ impl HotstuffRunner { self.event_notifier .on_commited( - &proposal_obj, + proposal_obj, pre_state_id, &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, - &new_header, + new_header.clone(), ) .await; @@ -1613,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.event_notifier.on_execute(&proposal, result_state_id).await { + match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 67f79cfdd..fc3d12c63 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,42 +1,132 @@ use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_group_lib::ExecuteResult; +use cyfs_group_lib::{ + ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandVerify, +}; use cyfs_lib::NONObjectInfo; +use crate::NONDriverHelper; + #[derive(Clone)] -pub(crate) struct RPathEventNotifier {} +pub(crate) struct RPathEventNotifier { + non_driver: NONDriverHelper, +} impl RPathEventNotifier { - pub fn new() -> Self { - unimplemented!() + pub fn new(driver: NONDriverHelper) -> Self { + Self { non_driver: driver } } pub async fn on_execute( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, ) -> BuckyResult { - unimplemented!() + let cmd = GroupCommandExecute { + proposal, + prev_state_id, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_some()); + match result.as_ref() { + Some(result) => { + let (cmd, _remain) = GroupCommand::raw_decode(result.object_raw.as_slice())?; + assert_eq!(_remain.len(), 0); + let mut cmd = TryInto::::try_into(cmd)?; + Ok(ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }) + } + None => Err(BuckyError::new( + BuckyErrorCode::Unknown, + "expect some result from dec-app", + )), + } } pub async fn on_verify( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandVerify { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } pub async fn on_commited( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, - block: &GroupConsensusBlock, + block: GroupConsensusBlock, ) { - unimplemented!() + let cmd = GroupCommandCommited { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec().expect( + format!("on_commited {} failed for encode", self.non_driver.dec_id()) + .as_str(), + ), + object: None, + }, + None, + ) + .await + .map_err(|err| log::warn!("on_commited {} failed {:?}", self.non_driver.dec_id(), err)); + + assert!(result.is_err() || result.unwrap().is_none()); } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95bdbcd17..346e75d02 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,11 +2,13 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -32,7 +34,6 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, - event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,7 +55,6 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, - event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { @@ -393,7 +393,6 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -410,8 +409,13 @@ impl GroupManager { if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - self.on_new_rpath_request(group_id, dec_id, rpath, block) - .await?; + self.on_new_rpath_request( + group_id.clone(), + dec_id, + rpath.to_string(), + block.cloned(), + ) + .await?; if !is_auto_create { return Err(e); @@ -457,7 +461,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - event_notifier, + RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, store, @@ -472,11 +476,33 @@ impl GroupManager { async fn on_new_rpath_request( &self, - group_id: &ObjectId, + group_id: ObjectId, dec_id: &ObjectId, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, + rpath: String, + with_block: Option, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandNewRPath { + group_id, + rpath, + with_block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .local_info() + .non_driver + .post_object( + dec_id, + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 08be0f5a0..41db0c25c 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -100,7 +100,7 @@ impl RPathClient { match self .0 .non_driver - .post_object(non_proposal.clone(), ood) + .post_object(non_proposal.clone(), Some(ood)) .await { Ok(r) => post_result = Some(Ok(())), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 979451b79..c7f9e7d93 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, }; @@ -29,8 +29,8 @@ pub trait NONDriver: Send + Sync { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()>; + to: Option<&ObjectId>, + ) -> BuckyResult>; } #[derive(Clone)] @@ -49,6 +49,10 @@ impl NONDriverHelper { } } + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id + } + pub async fn get_object( &self, object_id: &ObjectId, @@ -74,12 +78,17 @@ impl NONDriverHelper { self.driver.put_object(&self.dec_id, obj).await } - pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object( + &self, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { self.driver.post_object(&self.dec_id, obj, to).await } pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { - futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), Some(to)))) + .await; } pub async fn get_block( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fcb0dd6da..f7f305a83 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -88,8 +88,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()> { + to: Option<&ObjectId>, + ) -> BuckyResult> { self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { @@ -107,12 +107,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { level: NONAPILevel::Router, - target: Some(to.clone()), + target: to.cloned(), flags: 0, }, object: obj, }) .await - .map(|_| ()) + .map(|resp| resp.object) } } From bd334c0ea9dd74a617bc0a3595019ff2e0a94310 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 14:56:29 +0800 Subject: [PATCH 231/553] Rename `control` into `Service` --- .../cyfs-group/src/dec/group_manager.rs | 80 +++++++++---------- src/component/cyfs-group/src/dec/mod.rs | 4 +- .../{rpath_control.rs => rpath_service.rs} | 8 +- src/tests/group-example/src/main.rs | 20 ++--- 4 files changed, 56 insertions(+), 56 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_control.rs => rpath_service.rs} (96%) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 346e75d02..23202fddf 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,19 +12,19 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, + RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, }; -type ControlByRPath = HashMap; -type ControlByDec = HashMap; -type ControlByGroup = HashMap; +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; type ClientByRPath = HashMap; type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - control_by_group: ControlByGroup, + service_by_group: ServiceByGroup, client_by_group: ClientByGroup, } @@ -58,7 +58,7 @@ impl GroupManager { }; let raw = GroupRPathMgrRaw { - control_by_group: ControlByGroup::default(), + service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), }; @@ -69,14 +69,14 @@ impl GroupManager { Ok(mgr) } - pub async fn find_rpath_control( + pub async fn find_rpath_service( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, is_auto_create: bool, - ) -> BuckyResult { - self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + ) -> BuckyResult { + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -155,7 +155,7 @@ impl GroupManager { } // return - pub async fn enum_rpath_control( + pub async fn enum_rpath_service( &self, group_id: &ObjectId, ) -> BuckyResult> { @@ -182,8 +182,8 @@ impl GroupManager { match msg { HotstuffPackage::Block(block) => { let rpath = block.r_path(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -192,14 +192,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Block(block), remote) .await; } HotstuffPackage::BlockVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -208,14 +208,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; } HotstuffPackage::TimeoutVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -224,14 +224,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; } HotstuffPackage::Timeout(target, tc) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -240,14 +240,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Timeout(tc), remote) .await; } HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -256,14 +256,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; } HotstuffPackage::LastStateRequest(target) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -272,7 +272,7 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::LastStateRequest, remote) .await; } @@ -309,8 +309,8 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -320,9 +320,9 @@ impl GroupManager { ) .await; - match control { - Ok(control) => { - control + match service { + Ok(service) => { + service .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } @@ -356,7 +356,7 @@ impl GroupManager { Ok(()) } - async fn find_rpath_control_inner( + async fn find_rpath_service_inner( &self, group_id: &ObjectId, dec_id: &ObjectId, @@ -364,12 +364,12 @@ impl GroupManager { is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, - ) -> BuckyResult { + ) -> BuckyResult { { // read let raw = self.read().await; let found = raw - .control_by_group + .service_by_group .get(group_id) .map_or(None, |by_dec| by_dec.get(dec_id)) .map_or(None, |by_rpath| by_rpath.get(rpath)); @@ -446,7 +446,7 @@ impl GroupManager { }; let found = raw - .control_by_group + .service_by_group .entry(group_id.clone()) .or_insert_with(HashMap::new) .entry(dec_id.clone()) @@ -456,7 +456,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let control = RPathControl::load( + let service = RPathService::load( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -467,8 +467,8 @@ impl GroupManager { store, ) .await?; - entry.insert(control.clone()); - Ok(control) + entry.insert(service.clone()); + Ok(service) } } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 2ad717514..f881db19c 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod group_events; mod group_manager; mod rpath_client; -mod rpath_control; +mod rpath_service; pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; -pub use rpath_control::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_service.rs similarity index 96% rename from src/component/cyfs-group/src/dec/rpath_control.rs rename to src/component/cyfs-group/src/dec/rpath_service.rs index 593d82db4..b4b90972f 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -9,7 +9,7 @@ use crate::{ PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; -struct RPathControlRaw { +struct RPathServiceRaw { local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, @@ -18,9 +18,9 @@ struct RPathControlRaw { } #[derive(Clone)] -pub struct RPathControl(Arc); +pub struct RPathService(Arc); -impl RPathControl { +impl RPathService { pub(crate) async fn load( local_id: ObjectId, local_device_id: ObjectId, @@ -50,7 +50,7 @@ impl RPathControl { rpath.clone(), ); - let raw = RPathControlRaw { + let raw = RPathServiceRaw { network_sender, pending_proposal_handle, local_id, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 42544e51c..88450ac1b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,7 +505,7 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathControl; + use cyfs_group::RPathService; use cyfs_lib::{ DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, @@ -545,7 +545,7 @@ mod GroupDecService { } // pub struct PostProposalRoutine { - // controller: RPathControl, + // service: RPathService, // } // #[async_trait::async_trait] @@ -558,7 +558,7 @@ mod GroupDecService { // ) -> BuckyResult { // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // self.controller.push_proposal(proposal).await?; + // self.service.push_proposal(proposal).await?; // Ok(NONPostObjectInputResponse { object: None }) // } // } @@ -1037,9 +1037,9 @@ async fn main_run() { ) .await; - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1066,9 +1066,9 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1113,9 +1113,9 @@ async fn main_run() { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1125,7 +1125,7 @@ async fn main_run() { .unwrap(); async_std::task::spawn(async move { - control.push_proposal(proposal).await.unwrap(); + service.push_proposal(proposal).await.unwrap(); }); if i % 10 == 0 { From 259803f7830ef9981dd8e3fe5b35293964408dcc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 15:34:34 +0800 Subject: [PATCH 232/553] Interface in client for DecAPP --- src/component/cyfs-group-lib/src/delegate.rs | 6 +-- .../cyfs-group-lib/src/group_manager.rs | 37 ++++++++++++++++--- src/component/cyfs-group-lib/src/lib.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 23 ++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/rpath_service.rs diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 21b1e6346..645cd0656 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,4 @@ -use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, -}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -11,7 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()>; + ) -> BuckyResult>; } pub struct ExecuteResult { diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 8c82bc9e1..103807446 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,20 +1,47 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::DecAppId; +use cyfs_lib::SharedCyfsStack; -use crate::{DelegateFactory, RPathClient}; +use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; #[derive(Clone)] pub struct GroupManager; impl GroupManager { - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn open( + stack: SharedCyfsStack, + delegate_factory: Box, + ) -> BuckyResult { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn start_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + delegate: Box, + ) -> BuckyResult { + Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + } + + pub async fn find_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client( + &self, + group_id: ObjectId, + dec_id: DecAppId, + rpath: String, + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 199307bcc..34473bf07 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -2,8 +2,10 @@ mod delegate; mod group_manager; mod objects; mod rpath_client; +mod rpath_service; pub use delegate::*; pub use group_manager::*; pub use objects::*; pub use rpath_client::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs new file mode 100644 index 000000000..81225ed72 --- /dev/null +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupProposal, GroupRPath}; + +struct RPathServiceRaw {} + +#[derive(Clone)] +pub struct RPathService(Arc); + +impl RPathService { + pub(crate) async fn load() -> BuckyResult { + unimplemented!() + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + unimplemented!() + } +} From 0ac81b9566a94ac6d92a57d582f947af3e909dbb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 21:21:44 +0800 Subject: [PATCH 233/553] Interface in client for DecAPP events --- .../cyfs-base/protos/standard_objects.proto | 4 +- src/component/cyfs-base/src/objects/group.rs | 20 +- .../cyfs-core/protos/core_objects.proto | 8 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 18 +- .../cyfs-core/src/group/group_rpath.rs | 14 +- src/component/cyfs-group-lib/Cargo.toml | 3 +- src/component/cyfs-group-lib/src/delegate.rs | 24 +- .../cyfs-group-lib/src/group_manager.rs | 442 +++++++++++++++++- .../cyfs-group-lib/src/rpath_client.rs | 45 +- .../cyfs-group-lib/src/rpath_service.rs | 122 ++++- .../src/consensus/hotstuff/hotstuff.rs | 4 +- .../cyfs-group/src/dec/group_events.rs | 10 +- .../cyfs-group/src/dec/group_manager.rs | 28 +- .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec_state/state_pusher.rs | 4 +- .../cyfs-group/src/network/protocol.rs | 6 +- .../engine/storage_engine_group_state.rs | 8 +- .../cyfs-group/src/storage/group_storage.rs | 6 +- src/component/cyfs-lib/src/stack/stack.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- 21 files changed, 689 insertions(+), 115 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index cfb722c62..4a9714958 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -72,7 +72,7 @@ message GroupMethodACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; double min_support_percent = 4; string permissions = 5; // ACL-String @@ -83,7 +83,7 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; string method = 4; double right_percent = 5; diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ed7686157..5c8cda714 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -436,7 +436,7 @@ impl TryFrom<&GroupMember> for protos::GroupMember { pub struct GroupMethodACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub min_support_percent: f64, pub permissions: String, // ACL-String } @@ -452,8 +452,8 @@ impl TryFrom for GroupMethodACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -475,8 +475,8 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.min_support_percent = value.min_support_percent; ret.permissions = value.permissions.clone(); @@ -489,7 +489,7 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { pub struct GroupRoleACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub method: String, pub right_percent: f64, @@ -508,8 +508,8 @@ impl TryFrom for GroupRoleACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -533,8 +533,8 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.method = value.method.clone(); ret.right_percent = value.right_percent; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 742c14904..8048b3951 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -333,12 +333,12 @@ message SyncResponseObjectMetaInfo { message GroupRPath { bytes group_id = 1; bytes dec_id = 2; - string r_path = 3; + string rpath = 3; } message GroupProposalDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; @@ -404,7 +404,7 @@ message HotstuffTimeout { message GroupConsensusBlockDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // input bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) @@ -437,7 +437,7 @@ message GroupConsensusBlockBodyContent { /* message GroupActionDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 35c418552..7d447ad15 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -10,7 +10,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path: GroupRPath, + rpath: GroupRPath, body_hash: HashValue, result_state_id: Option, height: u64, @@ -40,7 +40,7 @@ impl DescContent for GroupConsensusBlockDescContent { impl GroupConsensusBlockDescContent { pub fn rpath(&self) -> &GroupRPath { - &self.r_path + &self.rpath } pub fn result_state_id(&self) -> &Option { @@ -236,7 +236,7 @@ impl GroupConsensusBlockBodyContent { pub trait GroupConsensusBlockObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -248,7 +248,7 @@ pub trait GroupConsensusBlockObject { owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; @@ -266,7 +266,7 @@ pub trait GroupConsensusBlockObject { impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -280,7 +280,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { - r_path, + rpath, result_state_id, height, @@ -319,9 +319,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path(&self) -> &GroupRPath { + fn rpath(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path + &desc.rpath } fn proposals(&self) -> &Vec { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index bf28aafb2..508418f7b 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -6,7 +6,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, @@ -123,7 +123,7 @@ pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, meta_block_id: Option, @@ -131,7 +131,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path, + rpath, method, params, meta_block_id, @@ -158,7 +158,7 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -169,7 +169,7 @@ pub trait GroupProposalObject { effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -207,7 +207,7 @@ pub trait GroupProposalObject { #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -218,7 +218,7 @@ impl GroupProposalObject for GroupProposal { effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path, + rpath, method, params, meta_block_id, @@ -237,8 +237,8 @@ impl GroupProposalObject for GroupProposal { .owner(owner) } - fn r_path(&self) -> &GroupRPath { - &self.desc().content().r_path + fn rpath(&self) -> &GroupRPath { + &self.desc().content().rpath } fn method(&self) -> &str { diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 3b86fbc57..f177015bf 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,25 +1,25 @@ use cyfs_base::*; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq, Hash)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, - r_path: String, + rpath: String, } impl std::fmt::Debug for GroupRPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.rpath) } } impl GroupRPath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { Self { group_id, dec_id, - r_path, + rpath, } } @@ -31,7 +31,7 @@ impl GroupRPath { &self.dec_id } - pub fn r_path(&self) -> &str { - self.r_path.as_str() + pub fn rpath(&self) -> &str { + self.rpath.as_str() } } diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index e7cfda851..bad3d3112 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -31,4 +31,5 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 645cd0656..3cc99902b 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,6 @@ -use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SingleOpEnvStub}; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { @@ -23,30 +23,36 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult<()>; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ); } #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { - async fn create_single_op_env(&self) -> BuckyResult; - async fn create_sub_tree_op_env(&self) -> BuckyResult; + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult; + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 103807446..f93be45f0 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,37 +1,132 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::DecAppId; -use cyfs_lib::SharedCyfsStack; +use std::{collections::HashMap, sync::Arc}; -use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RawDecode, +}; +use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, + SharedCyfsStack, +}; +use cyfs_util::EventListenerAsyncRoutine; + +use crate::{ + DelegateFactory, ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandNewRPath, GroupCommandObject, GroupCommandType, + GroupCommandVerify, RPathClient, RPathDelegate, RPathService, +}; + +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupManagerRaw { + stack: SharedCyfsStack, + requestor: HttpRequestorRef, + delegate_factory: Option>, + clients: RwLock, + services: RwLock, + local_zone: Option, +} #[derive(Clone)] -pub struct GroupManager; +pub struct GroupManager(Arc); impl GroupManager { pub async fn open( stack: SharedCyfsStack, delegate_factory: Box, + requestor_type: &CyfsStackRequestorType, ) -> BuckyResult { - unimplemented!() + if stack.dec_id().is_none() { + let msg = "the stack should be opened with dec-id"; + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let dec_id = stack.dec_id().unwrap().clone(); + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + let router_handler_manager = stack.router_handlers().clone(); + + let mgr = Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: Some(delegate_factory), + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + })); + + // TODO: other filters? only local zone + let filter = format!( + "obj_type == {} && dec_id == {}", + CoreObjectType::GroupCommand as u16, + dec_id, + ); + + router_handler_manager + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-cmd-{}", dec_id).as_str(), + 0, + Some(filter), + None, + RouterHandlerAction::Pass, + Some(Box::new(mgr.clone())), + ) + .await?; + + Ok(mgr) } - pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { + pub async fn open_as_client( + stack: SharedCyfsStack, + requestor_type: &CyfsStackRequestorType, + ) -> BuckyResult { + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + + Ok(Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: None, + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + }))) + } + + pub async fn stop(&self) { unimplemented!() } + pub fn stack(&self) -> &SharedCyfsStack { + &self.0.stack + } + pub async fn start_rpath_service( &self, group_id: ObjectId, rpath: String, delegate: Box, ) -> BuckyResult { - Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + unimplemented!() } pub async fn find_rpath_service( &self, - group_id: ObjectId, - rpath: String, + group_id: &ObjectId, + rpath: &str, ) -> BuckyResult { unimplemented!() } @@ -40,8 +135,329 @@ impl GroupManager { &self, group_id: ObjectId, dec_id: DecAppId, - rpath: String, - ) -> BuckyResult { - unimplemented!() + rpath: &str, + ) -> RPathClient { + { + let clients = self.0.clients.read().await; + let found = clients + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id.object_id())) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return found.clone(); + } + } + + { + let client = RPathClient::new( + GroupRPath::new(group_id, dec_id.object_id().clone(), rpath.to_string()), + self.0.stack.dec_id().cloned(), + self.0.stack.non_service().clone(), + ); + + let mut clients = self.0.clients.write().await; + let client = clients + .entry(group_id) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert(client); + client.clone() + } + } + + async fn on_command( + &self, + cmd: GroupCommand, + ) -> BuckyResult> { + match cmd.into_cmd() { + crate::GroupCommandBodyContent::NewRPath(cmd) => { + self.on_new_rpath(cmd).await.map(|_| None) + } + crate::GroupCommandBodyContent::Execute(cmd) => { + self.on_execute(cmd).await.map(|r| Some(r)) + } + crate::GroupCommandBodyContent::ExecuteResult(_) => { + let msg = format!( + "should not get the cmd({:?}) in sdk", + GroupCommandType::ExecuteResult + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)) + } + crate::GroupCommandBodyContent::Verify(cmd) => self.on_verify(cmd).await.map(|_| None), + crate::GroupCommandBodyContent::Commited(cmd) => { + self.on_commited(cmd).await.map(|_| None) + } + } + } + + async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let group_id = &cmd.group_id; + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.rpath.as_str(); + + { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if found.is_some() { + return Ok(()); + } + } + + let delegate = factory + .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) + .await?; + + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(()); + } + }; + + new_service.start().await; + Ok(()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } + } + + async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try execute proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try execute proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let mut result = service + .on_execute(&cmd.proposal, &cmd.prev_state_id) + .await?; + + Ok(GroupCommandExecuteResult { + result_state_id: result.result_state_id.take(), + receipt: result.receipt.take(), + context: result.context.take(), + }) + } + + async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try verify proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try verify proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) + .await + } + + async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try commited proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try commited proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } +} + +#[async_trait::async_trait] +impl EventListenerAsyncRoutine + for GroupManager +{ + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + let req_common = ¶m.request.common; + if req_common.level != NONAPILevel::NOC + || req_common.source.zone.zone != self.0.local_zone + || self.0.local_zone.is_none() + || self.0.stack.dec_id().is_none() + { + log::warn!( + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id() + ); + + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let obj = ¶m.request.object; + match obj.object.as_ref() { + None => { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }) + } + Some(any_obj) => { + assert_eq!(any_obj.obj_type(), CoreObjectType::GroupCommand as u16); + if any_obj.obj_type() != CoreObjectType::GroupCommand as u16 { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let (cmd, remain) = GroupCommand::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + let resp_obj = self.on_command(cmd).await; + + let resp_cmd = resp_obj.map_or_else( + |err| Err(err), + |resp_obj| { + resp_obj.map_or(Ok(None), |resp_cmd| { + let resp_cmd = GroupCommand::from(resp_cmd); + resp_cmd.to_vec().map(|buf| { + Some(NONObjectInfo::new(resp_cmd.desc().object_id(), buf, None)) + }) + }) + }, + ); + + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: Some(resp_cmd.map(|cmd| NONPostObjectInputResponse { object: cmd })), + }) + } + } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 2fea6dcf7..ea032715b 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -1,26 +1,55 @@ use std::sync::Arc; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, - RawConvertTo, +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, }; -use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::NONObjectInfo; -struct RPathClientRaw {} +struct RPathClientRaw { + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, +} #[derive(Clone)] pub struct RPathClient(Arc); impl RPathClient { + pub(crate) fn new( + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, + ) -> Self { + Self(Arc::new(RPathClientRaw { + requestor, + rpath, + local_dec_id, + })) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + self.0 + .requestor + .post_object(NONPostObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: self.0.local_dec_id.clone(), + level: NONAPILevel::Router, + target: Some(proposal.rpath().group_id().clone()), + flags: 0, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), proposal.to_vec()?, None), + }) + .await + .map(|resp| resp.object) } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 81225ed72..cebe445dd 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,23 +1,133 @@ use std::sync::Arc; -use cyfs_base::BuckyResult; -use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, +}; -struct RPathServiceRaw {} +use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + +struct RPathServiceRaw { + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, +} #[derive(Clone)] pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load() -> BuckyResult { + pub fn rpath(&self) -> &GroupRPath { unimplemented!() } - pub fn rpath(&self) -> &GroupRPath { + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + // post http unimplemented!() } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub(crate) fn new( + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, + ) -> Self { + Self(Arc::new(RPathServiceRaw { + rpath, + requestor, + delegate, + stack, + })) + } + + pub(crate) async fn start(&self) -> BuckyResult { + // post create command unimplemented!() } + + pub(crate) async fn on_execute( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + ) -> BuckyResult { + self.0 + .delegate + .on_execute( + proposal, + prev_state_id, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_verify( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + self.0 + .delegate + .on_verify( + proposal, + prev_state_id, + execute_result, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_commited( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + self.0 + .delegate + .on_commited( + proposal, + prev_state_id, + execute_result, + block, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } +} + +struct GroupObjectMapProcessorImpl { + stack: SharedCyfsStack, +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorImpl { + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_single_op_env_with_access(access) + .await + } + + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_isolate_path_op_env_with_access(access) + .await + } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index eaaaed06e..d2dbcc517 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,7 +11,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; @@ -20,7 +20,7 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, }; /** diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index fc3d12c63..9bda7e340 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,6 @@ use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -130,3 +130,9 @@ impl RPathEventNotifier { assert!(result.is_err() || result.unwrap().is_none()); } } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 23202fddf..7a9708ccc 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -181,12 +181,12 @@ impl GroupManager { ) -> BuckyResult<()> { match msg { HotstuffPackage::Block(block) => { - let rpath = block.r_path(); + let rpath = block.rpath(); let service = self .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, Some(&block), Some(&remote), @@ -202,7 +202,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -218,7 +218,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -234,7 +234,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -250,7 +250,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -266,7 +266,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -278,9 +278,9 @@ impl GroupManager { } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { // TODO: unimplemented - // let rpath = header_block.r_path(); + // let rpath = header_block.rpath(); // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) // .await?; // client // .on_message( @@ -292,10 +292,10 @@ impl GroupManager { HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( @@ -313,7 +313,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -328,7 +328,7 @@ impl GroupManager { } _ => { let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) @@ -342,7 +342,7 @@ impl GroupManager { |status| status.block_desc.content().rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 41db0c25c..43fb8e559 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -78,13 +78,13 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.0.rpath); + assert_eq!(proposal.rpath(), &self.0.rpath); // TODO: signature let group = self .0 .non_driver - .get_group(proposal.r_path().group_id(), None, None) + .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 571c1ca13..99c3fed62 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -222,7 +222,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) @@ -248,7 +248,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 7e32fdc4d..1f2a46a73 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -321,16 +321,16 @@ impl std::fmt::Debug for HotstuffPackage { impl HotstuffPackage { pub(crate) fn rpath(&self) -> &GroupRPath { match self { - HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::Block(block) => block.rpath(), HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), - HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::StateChangeNotify(block, _) => block.rpath(), HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( |(_, addr)| addr.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 63158a865..029b09e78 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,12 +5,12 @@ use cyfs_base::{ ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_group_lib::GroupObjectMapProcessor; +use cyfs_core::GroupConsensusBlockObject; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a1a681259..3a762c1b6 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,12 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, - STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 2f162c331..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -94,7 +94,7 @@ pub struct SharedCyfsStack { // uni_stack uni_stack: Arc>, - requestor_holder: RequestorHolder, + requestor_holder: Arc>, } #[derive(Debug, Clone)] @@ -493,14 +493,15 @@ impl SharedCyfsStack { device_info: Arc::new(RwLock::new(None)), uni_stack: Arc::new(OnceCell::new()), - requestor_holder, + requestor_holder: Arc::new(RwLock::new(requestor_holder)), }; Ok(ret) } pub async fn stop(&self) { - self.requestor_holder.stop().await; + let requestor_holder = self.requestor_holder.read().unwrap(); + requestor_holder.stop().await; self.router_handlers.stop().await; @@ -744,6 +745,11 @@ impl SharedCyfsStack { pub fn uni_stack(&self) -> &UniCyfsStackRef { self.uni_stack.get_or_init(|| self.create_uni_stack()) } + + pub fn select_requestor(&self, requestor_type: &CyfsStackRequestorType) -> HttpRequestorRef { + let mut requestor_holder = self.requestor_holder.write().unwrap(); + requestor_holder.select_requestor(&self.param, requestor_type) + } } impl UniCyfsStack for SharedCyfsStack { diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index f7f305a83..431915a96 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: None, flags: 0, @@ -105,7 +105,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, From fe5e9e9d84a309109250b4aae5159ea273efc875 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 16:49:16 +0800 Subject: [PATCH 234/553] Interface for client --- src/component/cyfs-group-lib/Cargo.toml | 1 + src/component/cyfs-group-lib/src/delegate.rs | 1 + .../cyfs-group-lib/src/group_manager.rs | 255 ++++++++---------- .../cyfs-group-lib/src/input_request.rs | 0 src/component/cyfs-group-lib/src/lib.rs | 12 + .../cyfs-group-lib/src/output_request.rs | 7 + src/component/cyfs-group-lib/src/processor.rs | 6 + src/component/cyfs-group-lib/src/request.rs | 0 .../cyfs-group-lib/src/request_codec.rs | 21 ++ src/component/cyfs-group-lib/src/requestor.rs | 210 +++++++++++++++ .../cyfs-group-lib/src/rpath_client.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 14 +- .../cyfs-lib/src/non/output_request.rs | 20 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- 14 files changed, 391 insertions(+), 162 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/input_request.rs create mode 100644 src/component/cyfs-group-lib/src/output_request.rs create mode 100644 src/component/cyfs-group-lib/src/processor.rs create mode 100644 src/component/cyfs-group-lib/src/request.rs create mode 100644 src/component/cyfs-group-lib/src/request_codec.rs create mode 100644 src/component/cyfs-group-lib/src/requestor.rs diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index bad3d3112..740b303cd 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' itertools = "0.10.3" +http-types = '2.12' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 3cc99902b..d678438c3 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -9,6 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult>; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f93be45f0..f442d5c55 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,7 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, @@ -195,98 +195,28 @@ impl GroupManager { } async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { - match self.0.delegate_factory.as_ref() { - Some(factory) => { - let group_id = &cmd.group_id; - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.rpath.as_str(); - - { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - if found.is_some() { - return Ok(()); - } - } - - let delegate = factory - .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) - .await?; - - let new_service = { - let mut is_new = false; - - let mut services = self.0.services.write().await; - let service = services - .entry(group_id.clone()) - .or_insert_with(HashMap::new) - .entry(dec_id.clone()) - .or_insert_with(HashMap::new) - .entry(rpath.to_string()) - .or_insert_with(|| { - is_new = true; - - RPathService::new( - GroupRPath::new( - group_id.clone(), - dec_id.clone(), - rpath.to_string(), - ), - self.0.requestor.clone(), - delegate, - self.0.stack.clone(), - ) - }); - - if is_new { - service.clone() - } else { - return Ok(()); - } - }; - - new_service.start().await; - Ok(()) - } - None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), - } + self.find_or_restart_service( + &cmd.group_id, + self.0.stack.dec_id().unwrap(), + cmd.rpath.as_str(), + &cmd.with_block, + true, + ) + .await + .map(|_| ()) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try execute proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try execute proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) @@ -300,36 +230,16 @@ impl GroupManager { } async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try verify proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try verify proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -343,47 +253,102 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; - if cmd.proposal.rpath().dec_id() != dec_id { + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } + + async fn find_or_restart_service( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: &Option, + is_new: bool, + ) -> BuckyResult { + if dec_id != self.0.stack.dec_id().unwrap() { let msg = format!( - "try commited proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id + "try find proposal in different dec {:?}, expected: {:?}", + dec_id, + self.0.stack.dec_id().unwrap() ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - let service = { + { let services = self.0.services.read().await; let found = services .get(group_id) .and_then(|by_dec| by_dec.get(dec_id)) .and_then(|by_rpath| by_rpath.get(rpath)); - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try commited proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } + if let Some(found) = found { + return Ok(found.clone()); } - }; + } - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let delegate = factory + .create_rpath_delegate(group_id, rpath, with_block.as_ref(), is_new) + .await?; - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; - Ok(()) + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(service.clone()); + } + }; + + new_service.start().await; + Ok(new_service.clone()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } } } diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 34473bf07..519a64040 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,11 +1,23 @@ mod delegate; mod group_manager; +mod input_request; mod objects; +mod output_request; +mod processor; +mod request; +mod request_codec; +mod requestor; mod rpath_client; mod rpath_service; pub use delegate::*; pub use group_manager::*; +pub use input_request::*; pub use objects::*; +pub use output_request::*; +pub use processor::*; +pub(crate) use request::*; +pub use request_codec::*; +pub use requestor::*; pub use rpath_client::*; pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs new file mode 100644 index 000000000..c847668df --- /dev/null +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -0,0 +1,7 @@ +use cyfs_base::ObjectId; + +#[derive(Debug)] +pub struct GroupStartServiceOutputRequest { + pub group_id: ObjectId, + pub rpath: String, +} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs new file mode 100644 index 000000000..925061f3e --- /dev/null +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +#[async_trait::async_trait] +pub trait GroupOutputProcessor: Send + Sync {} + +pub type GroupOutputProcessorRef = Arc; diff --git a/src/component/cyfs-group-lib/src/request.rs b/src/component/cyfs-group-lib/src/request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs new file mode 100644 index 000000000..c4f330efc --- /dev/null +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -0,0 +1,21 @@ +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use serde_json::{Map, Value}; + +use crate::output_request::GroupStartServiceOutputRequest; + +impl JsonCodec for GroupStartServiceOutputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs new file mode 100644 index 000000000..437a01184 --- /dev/null +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + CYFS_API_LEVEL, +}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, +}; +use http_types::{Method, Request, Url}; + +use crate::{ + output_request::GroupStartServiceOutputRequest, + processor::{GroupOutputProcessor, GroupOutputProcessorRef}, +}; + +#[derive(Clone)] +pub struct GroupRequestor { + dec_id: ObjectId, + requestor: HttpRequestorRef, + service_url: Url, +} + +impl GroupRequestor { + pub fn new(dec_id: ObjectId, requestor: HttpRequestorRef) -> Self { + let addr = requestor.remote_addr(); + + let url = format!("http://{}/group/", addr); + let url = Url::parse(&url).unwrap(); + + Self { + dec_id, + requestor, + service_url: url, + } + } + + pub fn clone_processor(&self) -> GroupOutputProcessorRef { + Arc::new(self.clone()) + } + + fn encode_common_headers( + &self, + // action: NONAction, + com_req: &NONOutputRequestCommon, + http_req: &mut Request, + ) { + let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); + http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); + + RequestorHelper::encode_opt_header_with_encoding( + http_req, + cyfs_base::CYFS_REQ_PATH, + com_req.req_path.as_deref(), + ); + + // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + + http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); + + if let Some(target) = &com_req.target { + http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); + } + + if let Some(source) = &com_req.source { + http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); + } + + http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); + } + + fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(dec_id), + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, + } + } + + pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + log::info!("will start group service: {:?}", rpath); + + let url = self.service_url.join("start-service").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + let req = GroupStartServiceOutputRequest { + group_id: rpath.group_id().clone(), + rpath: rpath.rpath().to_string(), + }; + + self.encode_common_headers( + &Self::make_default_common(rpath.dec_id().clone()), + &mut http_req, + ); + let body = req.encode_string(); + http_req.set_body(body); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group start service failed, read body string error! req={:?} {}", + req, e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!("group start service success"); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group start service failed: rpath={:?}, status={}, {}", + rpath, + code, + e + ); + Err(e) + } + } + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + let proposal_id = proposal.desc().object_id(); + log::info!( + "will push proposal: {:?}, {}", + proposal.rpath(), + proposal_id + ); + + let url = self.service_url.join("push-proposal").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + self.encode_common_headers( + &Self::make_default_common(proposal.rpath().dec_id().clone()), + &mut http_req, + ); + + NONRequestorHelper::encode_object_info( + &mut http_req, + NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + ); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group push proposal failed, read body string error! req={:?}/{} {}", + proposal.rpath(), + proposal_id, + e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!( + "group push proposal success, req={:?}/{}", + proposal.rpath(), + proposal_id + ); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group push proposal failed: rpath={:?}/{}, status={}, {}", + proposal.rpath(), + proposal_id, + code, + e + ); + Err(e) + } + } + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupRequestor {} diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index ea032715b..7d7c9a613 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -32,6 +32,8 @@ impl RPathClient { &self.0.rpath } + // post proposal to the admins, it's same as calling to non.post_object with default parameters; + // and you can call the non.post_object with more parameters. pub async fn post_proposal( &self, proposal: &GroupProposal, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index cebe445dd..95811e339 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -6,11 +6,11 @@ use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; +use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; struct RPathServiceRaw { rpath: GroupRPath, - requestor: HttpRequestorRef, + requestor: GroupRequestor, delegate: Box, stack: SharedCyfsStack, } @@ -20,12 +20,12 @@ pub struct RPathService(Arc); impl RPathService { pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - unimplemented!() + self.0.requestor.push_proposal(proposal).await } pub(crate) fn new( @@ -35,16 +35,16 @@ impl RPathService { stack: SharedCyfsStack, ) -> Self { Self(Arc::new(RPathServiceRaw { + requestor: GroupRequestor::new(rpath.dec_id().clone(), requestor), rpath, - requestor, delegate, stack, })) } - pub(crate) async fn start(&self) -> BuckyResult { + pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - unimplemented!() + self.0.requestor.start_group_service(self.rpath()).await } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-lib/src/non/output_request.rs b/src/component/cyfs-lib/src/non/output_request.rs index d4950ce33..b6e96dcb3 100644 --- a/src/component/cyfs-lib/src/non/output_request.rs +++ b/src/component/cyfs-lib/src/non/output_request.rs @@ -4,7 +4,7 @@ use cyfs_base::*; use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NONOutputRequestCommon { // 请求路径,可为空 pub req_path: Option, @@ -130,14 +130,22 @@ impl NONUpdateObjectMetaOutputRequest { Self::new(NONAPILevel::NOC, object_id, access) } - pub fn new_non(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_non( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::NON, object_id, access); ret.common.target = target.map(|v| v.into()); ret } - pub fn new_router(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_router( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::Router, object_id, access); ret.common.target = target; @@ -243,7 +251,6 @@ impl NONGetObjectOutputRequest { } } - impl fmt::Display for NONGetObjectOutputRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "common: {}", self.common)?; @@ -338,7 +345,6 @@ impl fmt::Display for NONPostObjectOutputResponse { } } - // select #[derive(Clone)] pub struct NONSelectObjectOutputRequest { @@ -392,7 +398,6 @@ impl fmt::Display for NONSelectObjectOutputRequest { } } - #[derive(Clone)] pub struct NONSelectObjectOutputResponse { pub objects: Vec, @@ -470,7 +475,6 @@ impl fmt::Display for NONDeleteObjectOutputRequest { } } - #[derive(Clone)] pub struct NONDeleteObjectOutputResponse { pub object: Option, @@ -479,7 +483,7 @@ pub struct NONDeleteObjectOutputResponse { impl fmt::Display for NONDeleteObjectOutputResponse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "object: {:?}", self.object)?; - + Ok(()) } } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 431915a96..9333e7981 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::NOC, target: None, flags: 0, From e2a7912a36ad189021c9cfaa9d6015a2357bfaff Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 21:35:56 +0800 Subject: [PATCH 235/553] Export to SDK --- .../cyfs-group-lib/src/input_request.rs | 10 + .../cyfs-group-lib/src/output_request.rs | 4 + src/component/cyfs-group-lib/src/processor.rs | 24 ++- .../cyfs-group-lib/src/request_codec.rs | 19 +- src/component/cyfs-group-lib/src/requestor.rs | 54 +++-- .../cyfs-group-lib/src/rpath_service.rs | 21 +- src/component/cyfs-stack/Cargo.toml | 1 + src/component/cyfs-stack/src/group/mod.rs | 5 + .../cyfs-stack/src/group/processor.rs | 25 +++ .../cyfs-stack/src/group/transform.rs | 190 ++++++++++++++++++ .../cyfs-stack/src/group_api/acl/group_acl.rs | 61 ++++++ .../cyfs-stack/src/group_api/acl/mod.rs | 3 + src/component/cyfs-stack/src/group_api/mod.rs | 7 + .../group_api/router/group_service_router.rs | 133 ++++++++++++ .../src/group_api/router/local_service.rs | 113 +++++++++++ .../cyfs-stack/src/group_api/router/mod.rs | 5 + .../src/group_api/service/group_handler.rs | 125 ++++++++++++ .../src/group_api/service/group_listener.rs | 77 +++++++ .../src/group_api/service/group_service.rs | 35 ++++ .../cyfs-stack/src/group_api/service/mod.rs | 7 + .../cyfs-stack/src/interface/http_listener.rs | 11 + .../src/interface/listener_manager.rs | 14 +- src/component/cyfs-stack/src/lib.rs | 2 + .../cyfs-stack/src/stack/cyfs_stack.rs | 12 +- 24 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/component/cyfs-stack/src/group/mod.rs create mode 100644 src/component/cyfs-stack/src/group/processor.rs create mode 100644 src/component/cyfs-stack/src/group/transform.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/group_acl.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/group_service_router.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/local_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_handler.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_listener.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/mod.rs diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index e69de29bb..0f861ea3c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -0,0 +1,10 @@ +use cyfs_base::ObjectId; + +pub struct GroupStartServiceInputRequest { + pub group_id: ObjectId, + pub rpath: String, +} + +pub struct GroupStartServiceInputResponse {} + +pub struct GroupPushProposalInputResponse {} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index c847668df..f65e02e3e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -5,3 +5,7 @@ pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, pub rpath: String, } + +pub struct GroupStartServiceOutputResponse {} + +pub struct GroupPushProposalOutputResponse {} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 925061f3e..9aec5a354 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -1,6 +1,26 @@ use std::sync::Arc; +use cyfs_base::BuckyResult; +use cyfs_core::GroupProposal; +use cyfs_lib::NONOutputRequestCommon; + +use crate::{ + GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, +}; + #[async_trait::async_trait] -pub trait GroupOutputProcessor: Send + Sync {} +pub trait GroupOutputProcessor: Send + Sync { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult; + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} -pub type GroupOutputProcessorRef = Arc; +pub type GroupOutputProcessorRef = Arc>; diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index c4f330efc..58404d6b0 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::output_request::GroupStartServiceOutputRequest; +use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { @@ -19,3 +19,20 @@ impl JsonCodec for GroupStartServiceOutputReques }) } } + +impl JsonCodec for GroupStartServiceInputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 437a01184..462b1df85 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -13,6 +13,7 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, + GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -37,7 +38,7 @@ impl GroupRequestor { } pub fn clone_processor(&self) -> GroupOutputProcessorRef { - Arc::new(self.clone()) + Arc::new(Box::new(self.clone())) } fn encode_common_headers( @@ -70,7 +71,7 @@ impl GroupRequestor { http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { NONOutputRequestCommon { req_path: None, source: None, @@ -81,21 +82,23 @@ impl GroupRequestor { } } - pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + pub async fn start_service( + &self, + req_common: NONOutputRequestCommon, + group_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); let url = self.service_url.join("start-service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { - group_id: rpath.group_id().clone(), - rpath: rpath.rpath().to_string(), + group_id: group_id.clone(), + rpath: rpath.to_string(), }; - self.encode_common_headers( - &Self::make_default_common(rpath.dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -123,7 +126,7 @@ impl GroupRequestor { log::debug!("group start service success"); - Ok(()) + Ok(GroupStartServiceOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -138,7 +141,11 @@ impl GroupRequestor { } } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + proposal: &GroupProposal, + ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", @@ -149,10 +156,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers( - &Self::make_default_common(proposal.rpath().dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, @@ -189,7 +193,7 @@ impl GroupRequestor { proposal_id ); - Ok(()) + Ok(GroupPushProposalOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -207,4 +211,20 @@ impl GroupRequestor { } #[async_trait::async_trait] -impl GroupOutputProcessor for GroupRequestor {} +impl GroupOutputProcessor for GroupRequestor { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupRequestor::push_proposal(self, req_common, &req).await + } +} diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 95811e339..66d0d83f4 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; @@ -25,7 +25,14 @@ impl RPathService { pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - self.0.requestor.push_proposal(proposal).await + self.0 + .requestor + .push_proposal( + GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal, + ) + .await + .map(|_| {}) } pub(crate) fn new( @@ -44,7 +51,15 @@ impl RPathService { pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - self.0.requestor.start_group_service(self.rpath()).await + self.0 + .requestor + .start_service( + GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + self.rpath().group_id(), + self.rpath().rpath(), + ) + .await + .map(|_| {}) } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 76148a72e..12e2b186f 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -16,6 +16,7 @@ cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-group = { path = "../../component/cyfs-group" } +cyfs-group-lib = { path = "../../component/cyfs-group-lib" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } diff --git a/src/component/cyfs-stack/src/group/mod.rs b/src/component/cyfs-stack/src/group/mod.rs new file mode 100644 index 000000000..da7603e40 --- /dev/null +++ b/src/component/cyfs-stack/src/group/mod.rs @@ -0,0 +1,5 @@ +mod processor; +mod transform; + +pub(crate) use processor::*; +pub(crate) use transform::*; \ No newline at end of file diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs new file mode 100644 index 000000000..b6fe1544b --- /dev/null +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -0,0 +1,25 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +#[async_trait::async_trait] +pub(crate) trait GroupInputProcessor: Sync + Send { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult; + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} + +pub(crate) type GroupInputProcessorRef = Arc; diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs new file mode 100644 index 000000000..50abe1afb --- /dev/null +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -0,0 +1,190 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, + GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +use super::{GroupInputProcessor, GroupInputProcessorRef}; + +// 实现从input到output的转换 +pub(crate) struct GroupInputTransformer { + processor: GroupOutputProcessorRef, +} + +impl GroupInputTransformer { + pub fn new(processor: GroupOutputProcessorRef) -> GroupInputProcessorRef { + let ret = Self { processor }; + Arc::new(ret) + } + + fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { + NONOutputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 来源DEC + dec_id: common.source.get_opt_dec().cloned(), + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source: common.source.zone.device, + } + } + + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let out_req = GroupStartServiceOutputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let out_resp = self + .processor + .start_service(Self::convert_common(req_common), out_req) + .await?; + + let resp = GroupStartServiceInputResponse {}; + + Ok(resp) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let out_resp = self + .processor + .push_proposal(Self::convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalInputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupInputTransformer { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + GroupInputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupInputTransformer::push_proposal(self, req_common, req).await + } +} + +// 实现从output到input的转换 +pub(crate) struct GroupOutputTransformer { + processor: GroupInputProcessorRef, + source: RequestSourceInfo, +} + +impl GroupOutputTransformer { + fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + let mut source = self.source.clone(); + if let Some(dec_id) = common.dec_id { + source.set_dec(dec_id); + } + + NONInputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source, + } + } + + pub fn new( + processor: GroupInputProcessorRef, + source: RequestSourceInfo, + ) -> GroupOutputProcessorRef { + let ret = Self { processor, source }; + Arc::new(Box::new(ret)) + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let in_resp = self + .processor + .push_proposal(self.convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalOutputResponse {}; + + Ok(resp) + } + + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + let in_req = GroupStartServiceInputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let in_resp = self + .processor + .start_service(self.convert_common(req_common), in_req) + .await?; + + let resp = GroupStartServiceOutputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupOutputTransformer { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupOutputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupOutputTransformer::push_proposal(self, req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs new file mode 100644 index 000000000..0e789c023 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -0,0 +1,61 @@ +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +pub struct GroupAclInnerInputProcessor { + next: GroupInputProcessorRef, +} + +impl GroupAclInnerInputProcessor { + pub(crate) fn new(next: GroupInputProcessorRef) -> GroupInputProcessorRef { + Arc::new(Self { next }) + } + + fn check_local_zone_permit( + &self, + service: &str, + source: &RequestSourceInfo, + ) -> BuckyResult<()> { + // TODO + // if !source.is_current_zone() { + // let msg = format!( + // "{} service valid only in current zone! source={:?}, category={}", + // service, + // source.zone.device, + // source.zone.zone_category.as_str() + // ); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, msg)); + // } + + Ok(()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupAclInnerInputProcessor { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.next.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.next.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/mod.rs b/src/component/cyfs-stack/src/group_api/acl/mod.rs new file mode 100644 index 000000000..53dad00b3 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/mod.rs @@ -0,0 +1,3 @@ +mod group_acl; + +pub use group_acl::*; diff --git a/src/component/cyfs-stack/src/group_api/mod.rs b/src/component/cyfs-stack/src/group_api/mod.rs new file mode 100644 index 000000000..29e257330 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/mod.rs @@ -0,0 +1,7 @@ +mod acl; +mod router; +mod service; + +pub(crate) use acl::*; +pub(crate) use router::*; +pub(crate) use service::*; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs new file mode 100644 index 000000000..2c1a2841f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyResult, DeviceId, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::{ + forward::ForwardProcessorManager, + group::{GroupInputProcessor, GroupInputProcessorRef, GroupInputTransformer}, + group_api::GroupAclInnerInputProcessor, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupServiceRouter { + processor: GroupInputProcessorRef, + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, +} + +impl GroupServiceRouter { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + processor: GroupInputProcessorRef, + ) -> GroupInputProcessorRef { + let processor = GroupAclInnerInputProcessor::new(processor); + let ret = Self { + processor, + zone_manager, + forward, + }; + Arc::new(ret) + } + + async fn get_forward( + &self, + dec_id: ObjectId, + target: DeviceId, + ) -> BuckyResult { + let requestor = self.forward.get(&target).await?; + let group_requestor = GroupRequestor::new(dec_id, requestor); + Ok(GroupInputTransformer::new( + group_requestor.clone_processor(), + )) + } + + // 不同于non/ndn的router,如果target为空,那么表示本地device + async fn get_target(&self, target: Option<&ObjectId>) -> BuckyResult> { + let ret = match target { + Some(object_id) => { + let info = self + .zone_manager + .target_zone_manager() + .resolve_target(Some(object_id)) + .await?; + if info.target_device == *self.zone_manager.get_current_device_id() { + None + } else { + Some(info.target_device) + } + } + None => None, + }; + + Ok(ret) + } + + async fn get_processor( + &self, + dec_id: ObjectId, + target: Option<&ObjectId>, + ) -> BuckyResult { + if let Some(device_id) = self.get_target(target).await? { + debug!("group target resolved: {:?} -> {}", target, device_id); + let processor = self.get_forward(dec_id, device_id).await?; + Ok(processor) + } else { + Ok(self.processor.clone()) + } + } + + pub async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + pub async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupServiceRouter { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs new file mode 100644 index 000000000..e14691b5e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc}; +use cyfs_core::{GroupProposal, GroupProposalObject}; +use cyfs_group::GroupManager; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; + +#[derive(Clone)] +pub(crate) struct LocalGroupService { + group_manager: GroupManager, +} + +impl LocalGroupService { + pub(crate) fn new(group_manager: GroupManager) -> Self { + Self { group_manager } + } + + pub fn clone_processor(&self) -> GroupInputProcessorRef { + Arc::new(self.clone()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for LocalGroupService { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.group_manager + .find_rpath_service( + &req.group_id, + &req_common.source.dec, + req.rpath.as_str(), + true, + ) + .await + .map(|_| GroupStartServiceInputResponse {}) + .map_err(|err| { + log::error!( + "group start service {}-{}-{} failed {:?}", + req.group_id, + req_common.source.dec, + req.rpath, + err + ); + err + }) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let proposal_id = req.desc().object_id(); + let rpath = req.rpath().clone(); + if &req_common.source.dec != rpath.dec_id() { + let msg = format!( + "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + req_common.source.dec + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let service = self + .group_manager + .find_rpath_service( + req.rpath().group_id(), + &req_common.source.dec, + rpath.rpath(), + true, + ) + .await + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed when find the service {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + })?; + + service + .push_proposal(req) + .await + .map(|_| GroupPushProposalInputResponse {}) + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + }) + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/mod.rs b/src/component/cyfs-stack/src/group_api/router/mod.rs new file mode 100644 index 000000000..877b4eff6 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/mod.rs @@ -0,0 +1,5 @@ +mod group_service_router; +mod local_service; + +pub use group_service_router::*; +pub(crate) use local_service::*; diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs new file mode 100644 index 000000000..f01f2eaa5 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -0,0 +1,125 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; + +use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; + +#[derive(Clone)] +pub(crate) struct GroupRequestHandler { + processor: GroupInputProcessorRef, +} + +impl GroupRequestHandler { + pub fn new(processor: GroupInputProcessorRef) -> Self { + Self { processor } + } + + // 解析通用header字段 + fn decode_common_headers( + req: &NONInputHttpRequest, + ) -> BuckyResult { + // req_path + let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( + &req.request, + cyfs_base::CYFS_REQ_PATH, + )?; + + // 尝试提取flags + let flags: Option = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; + + // 尝试提取default_action字段 + let level = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; + + // 尝试提取target字段 + let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; + + let ret = NONInputRequestCommon { + req_path, + source: req.source.clone(), + level: level.unwrap_or_default(), + target, + flags: flags.unwrap_or(0), + }; + + Ok(ret) + } + + // group/start-service + pub async fn process_start_service( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_start_service(req).await { + Ok(_resp) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_start_service( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + let common = Self::decode_common_headers(&req)?; + + // 提取body里面的object对象,如果有的话 + let body = req.request.body_json().await.map_err(|e| { + let msg = format!("group start service failed, read body bytes error! {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidParam, msg) + })?; + + let req = GroupStartServiceInputRequest::decode_json(&body)?; + + self.processor.start_service(common, req).await + } + + pub async fn process_push_proposal( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_push_proposal(req).await { + Ok(_) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_push_proposal( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + // 检查action + // let action = Self::decode_action(&req, NONAction::PutObject)?; + // if action != NONAction::PutObject { + // let msg = format!("invalid non put_object action! {:?}", action); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + // } + + let common = Self::decode_common_headers(&req)?; + let object = NONRequestorHelper::decode_object_info(&mut req.request).await?; + let (proposal, remain) = GroupProposal::raw_decode(object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + // let access: Option = + // RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_ACCESS)?; + // let access = access.map(|v| AccessString::new(v)); + + info!("recv push proposal: {}", object.object_id); + + self.processor.push_proposal(common, proposal).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs new file mode 100644 index 000000000..163228d1f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -0,0 +1,77 @@ +use cyfs_lib::RequestProtocol; +use tide::Response; + +use crate::{non::NONInputHttpRequest, ZoneManagerRef}; + +use super::GroupRequestHandler; + +enum GroupRequestType { + StartService, + PushProposal, +} + +pub(crate) struct GroupRequestHandlerEndpoint { + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, +} + +impl GroupRequestHandlerEndpoint { + fn new( + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, + ) -> Self { + Self { + zone_manager, + protocol, + req_type, + handler, + } + } + + async fn process_request(&self, req: tide::Request) -> Response { + let req = match NONInputHttpRequest::new(&self.zone_manager, &self.protocol, req).await { + Ok(v) => v, + Err(resp) => return resp, + }; + match self.req_type { + GroupRequestType::StartService => self.handler.process_start_service(req).await, + GroupRequestType::PushProposal => self.handler.process_push_proposal(req).await, + } + } + + pub fn register_server( + zone_manager: &ZoneManagerRef, + protocol: &RequestProtocol, + handler: &GroupRequestHandler, + server: &mut tide::Server<()>, + ) { + server.at("/group/start-service").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::StartService, + handler.clone(), + )); + + server.at("group/push-proposal").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::PushProposal, + handler.clone(), + )); + } +} + +#[async_trait::async_trait] +impl tide::Endpoint for GroupRequestHandlerEndpoint +where + State: Clone + Send + Sync + 'static, +{ + async fn call(&self, req: tide::Request) -> tide::Result { + let resp = self.process_request(req).await; + Ok(resp) + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_service.rs b/src/component/cyfs-stack/src/group_api/service/group_service.rs new file mode 100644 index 000000000..3a25e282e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_service.rs @@ -0,0 +1,35 @@ +use cyfs_group::GroupManager; + +use crate::{ + forward::ForwardProcessorManager, + group::GroupInputProcessorRef, + group_api::{GroupServiceRouter, LocalGroupService}, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupService { + router: GroupInputProcessorRef, + local_service: LocalGroupService, +} + +impl GroupService { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + group_manager: GroupManager, + ) -> Self { + let local_service = LocalGroupService::new(group_manager); + let router = + GroupServiceRouter::new(forward, zone_manager, local_service.clone_processor()); + + Self { + router, + local_service, + } + } + + pub(crate) fn clone_processor(&self) -> GroupInputProcessorRef { + self.router.clone() + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/mod.rs b/src/component/cyfs-stack/src/group_api/service/mod.rs new file mode 100644 index 000000000..1140a741d --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/mod.rs @@ -0,0 +1,7 @@ +mod group_service; +mod group_listener; +mod group_handler; + +pub(crate) use group_service::*; +pub(crate) use group_listener::*; +pub(crate) use group_handler::*; diff --git a/src/component/cyfs-stack/src/interface/http_listener.rs b/src/component/cyfs-stack/src/interface/http_listener.rs index 21b6e86e3..e9ef12523 100644 --- a/src/component/cyfs-stack/src/interface/http_listener.rs +++ b/src/component/cyfs-stack/src/interface/http_listener.rs @@ -1,6 +1,7 @@ use crate::acl::AclManagerRef; use crate::crypto_api::*; use crate::front::{FrontProtocolHandler, FrontRequestHandlerEndpoint}; +use crate::group_api::{GroupRequestHandler, GroupRequestHandlerEndpoint, GroupService}; use crate::name::NameResolver; use crate::ndn_api::*; use crate::non_api::*; @@ -75,6 +76,7 @@ impl ObjectHttpListener { global_state_meta: &GlobalStateMetaService, name_resolver: &NameResolver, zone_manager: &ZoneManagerRef, + group_service: &GroupService, ) -> Self { let mut server = new_server(); @@ -225,6 +227,15 @@ impl ObjectHttpListener { &mut server, ); + // group manager + let handler = GroupRequestHandler::new(group_service.clone_processor()); + GroupRequestHandlerEndpoint::register_server( + zone_manager, + &protocol, + &handler, + &mut server, + ); + Self { server } } diff --git a/src/component/cyfs-stack/src/interface/listener_manager.rs b/src/component/cyfs-stack/src/interface/listener_manager.rs index c6b5510be..76d3c4e9d 100644 --- a/src/component/cyfs-stack/src/interface/listener_manager.rs +++ b/src/component/cyfs-stack/src/interface/listener_manager.rs @@ -9,6 +9,7 @@ use crate::acl::AclManagerRef; use crate::app::AuthenticatedAppList; use crate::config::StackGlobalConfig; use crate::events::RouterEventsManager; +use crate::group_api::GroupService; use crate::interface::http_ws_listener::ObjectHttpWSService; use crate::name::NameResolver; use crate::rmeta_api::GlobalStateMetaService; @@ -18,7 +19,7 @@ use crate::stack::ObjectServices; use crate::zone::ZoneRoleManager; use cyfs_base::*; use cyfs_bdt::StackGuard; -use cyfs_lib::{RequestProtocol, BrowserSanboxMode}; +use cyfs_lib::{BrowserSanboxMode, RequestProtocol}; use cyfs_debug::Mutex; use std::net::SocketAddr; @@ -131,6 +132,7 @@ impl ObjectListenerManager { root_state: &GlobalStateService, local_cache: &GlobalStateLocalService, global_state_meta: &GlobalStateMetaService, + group_service: &GroupService, ) { assert!(self.listeners.is_empty()); @@ -151,6 +153,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); @@ -172,18 +175,14 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); let http_server = DefaultHttpServer::new(raw_handler.into(), default_handler.clone()); let http_server = match config.get_stack_params().front.browser_mode { BrowserSanboxMode::None => http_server.into(), - mode @ _ => { - BrowserSanboxHttpServer::new( - http_server.into(), - mode, - ).into() - } + mode @ _ => BrowserSanboxHttpServer::new(http_server.into(), mode).into(), }; self.http_tcp_server = Some(http_server); } @@ -202,6 +201,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); diff --git a/src/component/cyfs-stack/src/lib.rs b/src/component/cyfs-stack/src/lib.rs index c180fe861..832029d33 100644 --- a/src/component/cyfs-stack/src/lib.rs +++ b/src/component/cyfs-stack/src/lib.rs @@ -29,6 +29,8 @@ mod config; mod front; mod rmeta_api; mod rmeta; +mod group; +mod group_api; pub use stack::*; pub use storage::*; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 4c91fe145..f03d529e9 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -10,6 +10,7 @@ use crate::crypto_api::{CryptoService, ObjectCrypto, ObjectVerifier}; use crate::events::RouterEventsManager; use crate::forward::ForwardProcessorManager; use crate::front::FrontService; +use crate::group_api::GroupService; use crate::interface::{ ObjectListenerManager, ObjectListenerManagerParams, ObjectListenerManagerRef, }; @@ -105,7 +106,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupManager, + group_service: GroupService, } impl CyfsStackImpl { @@ -434,6 +435,8 @@ impl CyfsStackImpl { bdt_stack.clone(), global_state_manager.clone_processor(), )?; + let group_service = + GroupService::new(forward_manager.clone(), zone_manager.clone(), group_manager); let mut stack = Self { config, @@ -471,7 +474,7 @@ impl CyfsStackImpl { acl_manager, - group_manager, + group_service, }; // init an system-dec router-handler processor for later use @@ -561,6 +564,7 @@ impl CyfsStackImpl { &stack.root_state, &stack.local_cache, &stack.global_state_meta, + &stack.group_service, ); let interface = Arc::new(interface); @@ -1160,8 +1164,8 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupManager { - &self.stack.group_manager + pub fn group_service(&self) -> &GroupService { + &self.stack.group_service } // use system dec as default dec From 20507d5638dda4cb5b8975dea1033aca67d28c3b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Mar 2023 17:39:29 +0800 Subject: [PATCH 236/553] Remove several unused import --- src/component/cyfs-group-lib/src/request_codec.rs | 2 +- src/component/cyfs-group-lib/src/requestor.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 58404d6b0..4c7ddfe88 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 462b1df85..341bff3e3 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -4,7 +4,7 @@ use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, CYFS_API_LEVEL, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, }; @@ -116,7 +116,7 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupStartServiceOutputResponse::decode_string(&body).map_err(|e| { // error!( // "decode group start service resp from body string error: body={} {}", // body, e, @@ -179,9 +179,9 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { // error!( - // "decode group start service resp from body string error: body={} {}", + // "decode group push proposal resp from body string error: body={} {}", // body, e, // ); // e From dfe2962d364e94a66fd9684b0030623c4edc9492 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 19:19:00 +0800 Subject: [PATCH 237/553] Debug --- src/component/cyfs-group-lib/Cargo.toml | 1 - .../cyfs-group-lib/src/group_manager.rs | 138 +++++- src/component/cyfs-group-lib/src/requestor.rs | 11 +- .../cyfs-group/src/dec/group_events.rs | 43 +- .../cyfs-group/src/dec/group_manager.rs | 10 +- .../cyfs-group/src/dec/rpath_service.rs | 7 +- .../src/group_api/service/group_listener.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 21 +- .../cyfs-stack/src/zone/zone_manager.rs | 20 +- src/tests/group-example/Cargo.toml | 4 +- src/tests/group-example/src/main.rs | 436 ++++++++---------- 11 files changed, 407 insertions(+), 288 deletions(-) diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index 740b303cd..68931728c 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -32,5 +32,4 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f442d5c55..61a11698d 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -7,7 +7,7 @@ use cyfs_base::{ }; use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -68,11 +68,14 @@ impl GroupManager { // TODO: other filters? only local zone let filter = format!( - "obj_type == {} && dec_id == {}", + "obj_type == {} && source.dec_id == {} && source.zone_category == {}", CoreObjectType::GroupCommand as u16, dec_id, + DeviceZoneCategory::CurrentZone.to_string(), ); + // let filter = "*".to_string(); + router_handler_manager .post_object() .add_handler( @@ -80,7 +83,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - None, + Some("group-inner".to_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) @@ -120,7 +123,38 @@ impl GroupManager { rpath: String, delegate: Box, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap().clone(); + + { + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(&dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath.as_str())); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + RPathService::new( + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + Ok(service.clone()) + } } pub async fn find_rpath_service( @@ -128,7 +162,20 @@ impl GroupManager { group_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap(); + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + found.map_or( + Err(BuckyError::new( + BuckyErrorCode::NotFound, + "please start the service first", + )), + |service| Ok(service.clone()), + ) } pub async fn rpath_client( @@ -204,6 +251,16 @@ impl GroupManager { ) .await .map(|_| ()) + .map_err(|err| { + log::warn!( + "group on_new_rpath {}-{:?}-{} failed, err: {:?}", + cmd.group_id, + self.0.stack.dec_id(), + cmd.rpath, + err + ); + err + }) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { @@ -216,11 +273,27 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; Ok(GroupCommandExecuteResult { result_state_id: result.result_state_id.take(), @@ -239,7 +312,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_verify find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -250,6 +331,14 @@ impl GroupManager { service .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) .await + .map_err(|err| { + log::warn!( + "group on_verify {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + }) } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { @@ -262,7 +351,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_commited find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -361,27 +458,38 @@ impl EventListenerAsyncRoutine BuckyResult { let req_common = ¶m.request.common; - if req_common.level != NONAPILevel::NOC - || req_common.source.zone.zone != self.0.local_zone + let obj = ¶m.request.object; + + log::debug!( + "group-command handle, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) + ); + + if !req_common.source.zone.is_current_zone() || self.0.local_zone.is_none() + // || req_common.source.zone.zone != self.0.local_zone || self.0.stack.dec_id().is_none() { log::warn!( - "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", req_common.level, req_common.source.zone, self.0.local_zone, - self.0.stack.dec_id() + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) ); return Ok(RouterHandlerPostObjectResult { - action: RouterHandlerAction::Reject, + action: RouterHandlerAction::Pass, request: None, response: None, }); } - let obj = ¶m.request.object; match obj.object.as_ref() { None => { return Ok(RouterHandlerPostObjectResult { diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 341bff3e3..b77f93dad 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -6,7 +6,8 @@ use cyfs_base::{ }; use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ - HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, + HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, + RequestorHelper, }; use http_types::{Method, Request, Url}; @@ -43,7 +44,7 @@ impl GroupRequestor { fn encode_common_headers( &self, - // action: NONAction, + action: NONAction, com_req: &NONOutputRequestCommon, http_req: &mut Request, ) { @@ -56,7 +57,7 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); @@ -98,7 +99,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -156,7 +157,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 9bda7e340..a25accb19 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,9 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -32,13 +35,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -78,13 +86,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -111,16 +124,26 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd + .to_vec() + .expect(format!("on_commited {} failed for encode", self.non_driver.dec_id()).as_str()); + let any_obj = cyfs_base::AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(object_raw_buf.as_slice()).expect( + format!( + "on_commited {} failed for convert to any", + self.non_driver.dec_id() + ) + .as_str(), + ), + ); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec().expect( - format!("on_commited {} failed for encode", self.non_driver.dec_id()) - .as_str(), - ), - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7a9708ccc..579f63831 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawConvertTo, RsaCPUObjectSigner, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; @@ -488,6 +488,10 @@ impl GroupManager { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); let result = self .local_info() .non_driver @@ -495,8 +499,8 @@ impl GroupManager { dec_id, NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index b4b90972f..1f2e836a1 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -66,6 +66,11 @@ impl RPathService { } pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + log::info!( + "group({:?}) push proposal {}", + self.rpath(), + proposal.desc().object_id() + ); self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 163228d1f..47be52927 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").post(Self::new( + server.at("/group/start-service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").post(Self::new( + server.at("group/push-proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9333e7981..fa136b3fa 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::NOC, + level: NONAPILevel::Router, target: None, flags: 0, @@ -90,10 +90,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { obj: NONObjectInfo, to: Option<&ObjectId>, ) -> BuckyResult> { + let obj_type_code = obj.object_id.obj_type_code(); + let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some("group-inner".to_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -105,7 +108,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, @@ -114,5 +117,15 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) .await .map(|resp| resp.object) + .map_err(|err| { + log::warn!( + "group post object(type={:?}/{:?}) to {:?} failed {:?}", + obj_type_code, + obj_type, + to, + err + ); + err + }) } } diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 6819b991d..61f284bc4 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -652,7 +652,25 @@ impl ZoneManager { owner_id, work_mode, list ); - return Ok((work_mode, list.to_owned())); + if obj_type == ObjectTypeCode::People { + return Ok((work_mode, list.to_owned())); + } else if obj_type == ObjectTypeCode::Group { + let group = owner_object.into_group(); + // TODO: 先简单处理,找最近的OOD,后面可能要依据具体操作向不同身份发起请求; + // 比如:读操作向任意member请求即可 + let list = group + .ood_list_with_distance( + self.get_current_device_id().object_id(), + ) + .into_iter() + .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) + .map(|id| DeviceId::try_from(id).unwrap()) + .collect(); + return Ok((work_mode, list)); + } else { + unreachable!() + } + /* let ood_device_id = list[0].clone(); let obj_type = ood_device_id.object_id().obj_type_code(); diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 01094f12a..2cf31aba9 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -23,9 +23,9 @@ cyfs-core = { path = '../../component/cyfs-core' } cyfs-bdt = { path = '../../component/cyfs-bdt' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } -cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 88450ac1b..e74f3c5d6 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,36 +1,43 @@ -use std::{clone, sync::Arc, time::Duration}; +use std::{clone, collections::HashSet, sync::Arc, time::Duration}; +use async_std::sync::Mutex; use cyfs_base::{ AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_group::IsCreateRPath; +use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, - NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, + NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, + RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; +use crate::{ + Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}, + GroupDecService::MyRPathDelegate, +}; mod Common { - use std::{fmt::format, io::ErrorKind, sync::Arc}; + use std::{ + fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, + }; - use async_std::{fs, stream::StreamExt}; + use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId, DecAppObj}; - use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_core::{DecApp, DecAppId}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, @@ -348,6 +355,8 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, + rpc_port: u16, + ws_port: u16, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -369,13 +378,19 @@ mod Common { config: CyfsStackConfigParams { isolate: Some(device.desc().object_id().to_string()), sync_service: false, - shared_stack: false, + shared_stack: true, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], - tcp_listeners: vec![], - ws_listener: None, + tcp_listeners: vec![SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + rpc_port, + ))], + ws_listener: Some(SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + ws_port, + ))), }, meta: CyfsStackMetaParams { target: MetaMinerTarget::Dev, @@ -454,9 +469,20 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, - ) -> CyfsStack { - let params = - init_stack_params(people, private_key, device, admins, members, group, dec_app); + rpc_port: u16, + ws_port: u16, + ) -> (CyfsStack, SharedCyfsStack) { + let params = init_stack_params( + people, + private_key, + device, + admins, + members, + group, + dec_app, + rpc_port, + ws_port, + ); log::info!("cyfs-stack.open"); @@ -468,14 +494,23 @@ mod Common { }) .unwrap(); - stack + async_std::task::sleep(Duration::from_millis(1000)).await; + + let shared_stack = + SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) + .await + .unwrap(); + + shared_stack.wait_online(None).await.unwrap(); + + (stack, shared_stack) } } mod Client { // use cyfs_base::ObjectId; // use cyfs_core::GroupProposal; - // use cyfs_group::RPathClient; + // use cyfs_group_lib::RPathClient; // pub struct DecClient {} @@ -505,12 +540,14 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathService; + use cyfs_group_lib::{ + DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, + RPathService, + }; use cyfs_lib::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, - NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, SharedCyfsStack, }; - use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -518,16 +555,18 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { - let group_mgr = cyfs_stack.group_mgr(); - - group_mgr - .register( - dec_app_id.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), - ) - .await - .unwrap(); + pub async fn run( + cyfs_stack: &SharedCyfsStack, + local_name: String, + dec_app_id: DecAppId, + ) -> GroupManager { + let group_mgr = GroupManager::open( + cyfs_stack.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + &cyfs_lib::CyfsStackRequestorType::Http, + ) + .await + .unwrap(); // let source = RequestSourceInfo { // protocol: todo!(), @@ -541,6 +580,8 @@ mod GroupDecService { // .handlers(&RouterHandlerChain::PostRouter) // .post_object() // .add_handler(RouterHandler::new()); + + group_mgr } } @@ -570,7 +611,7 @@ mod GroupDecService { impl GroupRPathDelegateFactory { pub fn is_accept( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, ) -> bool { @@ -583,27 +624,18 @@ mod GroupDecService { impl DelegateFactory for GroupRPathDelegateFactory { async fn create_rpath_delegate( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { + if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } } pub struct MyRPathDelegate { @@ -621,73 +653,19 @@ mod GroupDecService { } impl MyRPathDelegate { - // pub async fn get_value_from_state_tree_with_single_op_envs( - // pre_state_id: Option, - // object_map_processor: &dyn GroupObjectMapProcessor, - // ) -> BuckyResult<( - // Option, - // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - // )> { - // let mut single_op_envs = vec![]; - // let mut parent_map_id = pre_state_id; - // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - // let single_op_env = object_map_processor.create_single_op_env().await.expect( - // format!( - // "create_single_op_env load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // parent_map_id = match parent_map_id { - // Some(parent_map_id) => { - // single_op_env.load(&parent_map_id).await.expect( - // format!( - // "load folder {} parent with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // single_op_env.get_by_key(folder).await.expect( - // format!( - // "load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ) - // } - // None => { - // single_op_env - // .create_new(ObjectMapSimpleContentType::Map) - // .await - // .expect( - // format!( - // "create folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // None - // } - // }; - // single_op_envs.push((single_op_env, folder, parent_map_id)); - // } - - // Ok((parent_map_id, single_op_envs)) - // } - pub async fn execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); - let pre_value = match pre_state_id { - Some(pre_state_id) => { - state_op_env.load(&pre_state_id).await?; + let prev_value = match prev_state_id { + Some(prev_state_id) => { + state_op_env.load(prev_state_id.to_owned()).await?; state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -708,13 +686,13 @@ mod GroupDecService { let result_value = { /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_value.map_or(0, |pre_value| { - let buf = pre_value.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + let prev_value = prev_value.map_or(0, |prev_value| { + let buf = prev_value.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let delta_buf = proposal.params().as_ref().unwrap().as_slice(); @@ -722,7 +700,7 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let value = pre_value + delta; + let value = prev_value + delta; ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() @@ -731,13 +709,13 @@ mod GroupDecService { let result_state_id = { state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) .await .expect( format!( "set_with_path {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), @@ -746,34 +724,11 @@ mod GroupDecService { format!( "commit {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), ) - // let mut sub_folder_value = result_value; - // for (parent_single_op_env, folder, sub_folder_prev_value) in - // single_op_envs.into_iter().rev() - // { - // parent_single_op_env - // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - // .await - // .expect( - // format!( - // "update folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // sub_folder_value = parent_single_op_env.commit().await.expect( - // format!( - // "commit folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // } - // sub_folder_value }; let receipt = { @@ -791,11 +746,11 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_value + proposal + context + * (result_state_id, return_object) = prev_value + proposal + context */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id), + result_state_id: Some(result_state_id.root), receipt, }) } @@ -803,21 +758,21 @@ mod GroupDecService { pub async fn verify( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult { + ) -> BuckyResult<()> { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context + * == prev_state_id + proposal + execute_result.context */ let result = self - .execute(proposal, pre_state_id, object_map_processor) + .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", - pre_state_id, + prev_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), @@ -830,7 +785,11 @@ mod GroupDecService { && execute_result.context.is_none() && execute_result.receipt.is_none(); - Ok(is_ok) + if is_ok { + Ok(()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "result unmatch")) + } } } @@ -839,31 +798,36 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id, object_map_processor) + self.execute(proposal, prev_state_id, object_map_processor) .await } async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, object_map_processor, execute_result) - .await + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<()> { + self.verify( + proposal, + prev_state_id, + object_map_processor, + execute_result, + ) + .await } async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 @@ -872,16 +836,16 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = match pre_state_id { - Some(pre_state_id) => { + let prev_value = match prev_state_id { + Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&pre_state_id) + .load(*prev_state_id) .await - .expect(format!("load {} failed", pre_state_id).as_str()); + .expect(format!("load {} failed", prev_state_id).as_str()); state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -892,21 +856,21 @@ mod GroupDecService { } None => None, } - .map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + .map_or(0, |prev_state_id| { + let buf = prev_state_id.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let result_value = match execute_result.result_state_id { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&result_state_id) + .load(result_state_id) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -932,7 +896,7 @@ mod GroupDecService { "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, - pre_value, + prev_value, result_value, proposal_id, block.block_id(), @@ -942,10 +906,6 @@ mod GroupDecService { let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); assert!(is_new_finished); } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() - } } } @@ -982,6 +942,7 @@ async fn main_run() { cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) .exit_on_panic(true) + .dingtalk_bug_report("any value to disable") .build() .start(); @@ -1004,9 +965,12 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec = vec![]; + let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; + let mut group_mgrs: Vec = vec![]; + let mut rpc_port = 32217_u16; + let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { - let cyfs_stack = create_stack( + let (cyfs_stack, shared_stack) = create_stack( admin, private_key, device, @@ -1020,33 +984,34 @@ async fn main_run() { .collect(), &group, &dec_app, + rpc_port, + ws_port, ) .await; - admin_stacks.push(cyfs_stack); + admin_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; } async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { - let stack = admin_stacks.get(i).unwrap(); + let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); - DecService::run( - &stack, - admin.name().unwrap().to_string(), - dec_app_id.clone(), - ) - .await; - - let service = stack - .group_mgr() - .find_rpath_service( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, + let local_name = admin.name().unwrap(); + let group_mgr = + DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; + + let service = group_mgr + .start_rpath_service( + group.desc().object_id(), + EXAMPLE_RPATH.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), ) .await .unwrap(); + + group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1057,7 +1022,8 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, @@ -1066,42 +1032,31 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); - let noc = stack.noc_manager().clone(); + let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); let proposal_any = Arc::new(AnyNamedObject::Core( TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), )); - let req = NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: dec_app_id.object_id().clone(), - verified: None, + let req = NONPutObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: None, + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: Some(AccessString::full().value()), + access: Some(AccessString::full()), }; - noc.put_object(&req).await; + noc.put_object(req).await; proposals.push(proposal); } @@ -1112,20 +1067,15 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); async_std::task::spawn(async move { - service.push_proposal(proposal).await.unwrap(); + service.push_proposal(&proposal).await.unwrap(); }); if i % 10 == 0 { @@ -1136,27 +1086,25 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - let client = admin_stacks - .get(0) - .unwrap() - .group_mgr() - .rpath_client( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - ) - .await - .unwrap(); - - let value_obj = client - .get_by_path(EXAMPLE_VALUE_PATH.as_str()) - .await - .unwrap(); - let buf = value_obj.as_ref().unwrap().object_id.data(); - let mut value = [0u8; 8]; - value.copy_from_slice(&buf[..8]); - - log::info!("value from client is: {}", u64::from_be_bytes(value)); + // let client = group_mgrs + // .get(0) + // .unwrap() + // .rpath_client( + // &group.desc().object_id(), + // dec_app_id.object_id(), + // &EXAMPLE_RPATH, + // ) + // .await; + + // let value_obj = client + // .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + // .await + // .unwrap(); + // let buf = value_obj.as_ref().unwrap().object_id.data(); + // let mut value = [0u8; 8]; + // value.copy_from_slice(&buf[..8]); + + // log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From 0195f26d09192cae85d2115a5c10c67539ab07ed Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 238/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/service/ood-daemon/src/config/system_config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index ceb3344e9..670ea5832 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -62,6 +62,13 @@ impl SystemConfig { let node = Self::load_as_toml(&config_file)?; + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) + } + self.parse_config(node).await } @@ -206,4 +213,3 @@ pub async fn reload_system_config() -> BuckyResult { pub fn get_system_config() -> Arc { SYSTEM_CONFIG.lock().unwrap().clone().unwrap() -} \ No newline at end of file From 642cb523af187ab98eb03241f4eef4b5e3c4ee74 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 239/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/service/ood-daemon/src/config/system_config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 670ea5832..e27890656 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -3,6 +3,7 @@ use super::version::{ServiceListVersion, ServiceVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -64,8 +65,6 @@ impl SystemConfig { self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } From 902f7bb794dc981debe2bc41e60d541361dd29a2 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 240/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index e11695ad5..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1811,6 +1811,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1824,6 +1825,7 @@ dependencies = [ "semver 1.0.16", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1873,6 +1875,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.1" @@ -2226,6 +2287,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -3314,6 +3377,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.15" From 78fdb2e37cfa122532b03fee7de41c97a53eae48 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 241/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From df387df631252505e2a6061240e994b3ab62bce3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 11:13:13 +0800 Subject: [PATCH 242/553] Fix merge --- src/component/cyfs-stack/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 12e2b186f..48f201a85 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -29,7 +29,6 @@ cyfs-util = { path = "../cyfs-util" } cyfs-meta-lib = { path = "../cyfs-meta-lib" } cyfs-perf-client = { path = "../cyfs-perf/cyfs-perf-client" } #dsg-client = { path = "../dsg/dsg-client" } -cyfs-group = { path = "../../component/cyfs-group" } log = "0.4" serde = "1.0" async-h1 = "2.3.3" From 66984fdd4c86f3f3df00afc25ba91006cb930f2e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 14:48:12 +0800 Subject: [PATCH 243/553] Adapte to the buckyos --- .../engine/storage_engine_group_state.rs | 44 ++++++++++++++++--- .../cyfs-group/src/storage/group_storage.rs | 9 +++- src/meta/cyfs-meta/src/executor/view.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 029b09e78..cf04e93ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -19,6 +19,8 @@ const ACCESS: Option = None; #[derive(Clone)] pub struct StorageEngineGroupState { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, state_path: Arc, } @@ -183,18 +185,28 @@ impl StorageEngineGroupState { Ok(cache) } - pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + pub fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: GroupStatePath, + group_id: ObjectId, + dec_id: ObjectId, + ) -> Self { Self { state_mgr, state_path: Arc::new(state_path), + group_id, + dec_id, } } pub async fn create_writer(&self) -> BuckyResult { - Ok( - StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) - .await?, + Ok(StorageEngineGroupStateWriter::new( + self.state_mgr.clone(), + self.state_path.clone(), + self.group_id, + self.dec_id, ) + .await?) } pub fn root_cache(&self) -> &ObjectMapRootCacheRef { @@ -218,6 +230,8 @@ impl StorageEngine for StorageEngineGroupState { #[derive(Clone)] pub struct StorageEngineGroupStateWriter { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, op_env: ObjectMapPathOpEnvRef, prepare_op_env: ObjectMapSingleOpEnvRef, @@ -230,6 +244,8 @@ impl StorageEngineGroupStateWriter { async fn new( state_mgr: ObjectMapRootManagerRef, state_path: Arc, + group_id: ObjectId, + dec_id: ObjectId, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; @@ -237,7 +253,11 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(group_id), + Some(dec_id), + ) .await?; None } else { @@ -254,6 +274,8 @@ impl StorageEngineGroupStateWriter { state_mgr, prepare_map_id, write_result: Ok(()), + group_id, + dec_id, }) } @@ -264,7 +286,11 @@ impl StorageEngineGroupStateWriter { ) -> BuckyResult { let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; single_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(self.group_id), + Some(self.dec_id), + ) .await?; single_op_env .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) @@ -463,7 +489,11 @@ impl StorageEngineGroupStateWriter { } add_single_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new( + ObjectMapSimpleContentType::Set, + Some(self.group_id), + Some(self.dec_id), + ) .await?; } else { add_single_op_env diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a762c1b6..78af14c4b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -81,6 +81,8 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), + group_id.clone(), + dec_id.clone(), ), local_device_id, cache: StorageCacheInfo::new(None), @@ -138,7 +140,12 @@ impl GroupStorage { rpath: rpath.to_string(), non_driver, group_chunk_id: group_chunk_id.object_id(), - storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + state_path, + group_id.clone(), + dec_id.clone(), + ), local_device_id, cache, object_map_processor, diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 7d76e9fcc..47e3c8a7d 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -5,7 +5,7 @@ use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; use crate::stat::Stat; use crate::state_storage::{StateRef, StateWeakRef}; -use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base::{BuckyResult, RawConvertTo, ObjectId}; use cyfs_base_meta::*; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; From 069a50ad2eff1fea86aa4a532752759fd4cb819e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 17:36:57 +0800 Subject: [PATCH 244/553] Add interface create_new_with_option for RootStateStub to add params(owner/dec) --- .../cyfs-lib/src/root_state/output_request.rs | 14 ++ src/component/cyfs-lib/src/root_state/stub.rs | 167 +++++++++++++++++- 2 files changed, 175 insertions(+), 6 deletions(-) diff --git a/src/component/cyfs-lib/src/root_state/output_request.rs b/src/component/cyfs-lib/src/root_state/output_request.rs index d8426a5fe..6e80cfda4 100644 --- a/src/component/cyfs-lib/src/root_state/output_request.rs +++ b/src/component/cyfs-lib/src/root_state/output_request.rs @@ -311,6 +311,20 @@ impl FromStr for ObjectMapField { } } } + +impl From<&Option> for ObjectMapField { + fn from(id: &Option) -> Self { + id.as_ref() + .map_or(Self::None, |id| Self::Specific(id.clone())) + } +} + +impl From<&ObjectId> for ObjectMapField { + fn from(id: &ObjectId) -> Self { + Self::Specific(id.clone()) + } +} + // create_new pub struct OpEnvCreateNewOutputRequest { pub common: OpEnvOutputRequestCommon, diff --git a/src/component/cyfs-lib/src/root_state/stub.rs b/src/component/cyfs-lib/src/root_state/stub.rs index bb56ca3b5..31bd56684 100644 --- a/src/component/cyfs-lib/src/root_state/stub.rs +++ b/src/component/cyfs-lib/src/root_state/stub.rs @@ -17,6 +17,44 @@ pub struct GlobalStateStub { processor: GlobalStateOutputProcessorRef, } +pub struct CreateObjectMapOption { + owner: Option, + dec_id: Option, +} + +impl CreateObjectMapOption { + pub fn new(owner: Option, dec_id: Option) -> Self { + Self { owner, dec_id } + } + + pub fn new_with_owner(owner: ObjectId) -> Self { + Self { + owner: Some(owner), + dec_id: None, + } + } + + pub fn new_with_dec(dec_id: ObjectId) -> Self { + Self { + owner: None, + dec_id: Some(dec_id), + } + } + + pub fn new_with_none() -> Self { + Self { + owner: None, + dec_id: None, + } + } + + pub fn fill_request(&self, req: &mut OpEnvCreateNewOutputRequest) { + // options + req.owner = self.owner.as_ref().map(|id| ObjectMapField::from(id)); + req.dec = self.dec_id.as_ref().map(|id| ObjectMapField::from(id)); + } +} + impl GlobalStateStub { pub fn new( processor: GlobalStateOutputProcessorRef, @@ -107,7 +145,8 @@ impl GlobalStateStub { req.common.target_dec_id = self.target_dec_id.clone(); let resp = self.processor.create_op_env(req).await?; - let op_env = IsolatePathOpEnvStub::new(resp, self.target.clone(), self.target_dec_id.clone()); + let op_env = + IsolatePathOpEnvStub::new(resp, self.target.clone(), self.target_dec_id.clone()); Ok(op_env) } } @@ -140,6 +179,23 @@ impl SingleOpEnvStub { self.processor.create_new(req).await } + + // init methods + pub async fn create_new_with_option( + &self, + content_type: ObjectMapSimpleContentType, + options: &CreateObjectMapOption, + ) -> BuckyResult<()> { + let mut req = OpEnvCreateNewOutputRequest::new(content_type); + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + // options + options.fill_request(&mut req); + + self.processor.create_new(req).await + } + pub async fn load(&self, target: ObjectId) -> BuckyResult<()> { let mut req = OpEnvLoadOutputRequest::new(target); req.common.target = self.target.clone(); @@ -147,7 +203,11 @@ impl SingleOpEnvStub { self.processor.load(req).await } - pub async fn load_with_inner_path(&self, target: ObjectId, inner_path: impl Into) -> BuckyResult<()> { + pub async fn load_with_inner_path( + &self, + target: ObjectId, + inner_path: impl Into, + ) -> BuckyResult<()> { let mut req = OpEnvLoadOutputRequest::new_with_inner_path(target, inner_path); req.common.target = self.target.clone(); req.common.target_dec_id = self.target_dec_id.clone(); @@ -416,6 +476,24 @@ impl PathOpEnvStub { Ok(()) } + pub async fn create_new_with_option( + &self, + path: impl Into, + key: impl Into, + content_type: ObjectMapSimpleContentType, + options: &CreateObjectMapOption, + ) -> BuckyResult<()> { + let mut req = OpEnvCreateNewOutputRequest::new_with_path_and_key(path, key, content_type); + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + // options + options.fill_request(&mut req); + + self.processor.create_new(req).await?; + Ok(()) + } + pub async fn insert_with_key( &self, path: impl Into, @@ -490,6 +568,23 @@ impl PathOpEnvStub { Ok(()) } + pub async fn create_new_with_path_and_option( + &self, + full_path: impl Into, + content_type: ObjectMapSimpleContentType, + options: &CreateObjectMapOption, + ) -> BuckyResult<()> { + let mut req = OpEnvCreateNewOutputRequest::new_with_full_path(full_path, content_type); + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + // options + options.fill_request(&mut req); + + self.processor.create_new(req).await?; + Ok(()) + } + pub async fn insert_with_path( &self, full_path: impl Into, @@ -640,7 +735,6 @@ impl PathOpEnvStub { } } - #[derive(Clone)] pub struct IsolatePathOpEnvStub { processor: OpEnvOutputProcessorRef, @@ -669,6 +763,22 @@ impl IsolatePathOpEnvStub { self.processor.create_new(req).await } + + pub async fn create_new_with_option( + &self, + content_type: ObjectMapSimpleContentType, + options: &CreateObjectMapOption, + ) -> BuckyResult<()> { + let mut req = OpEnvCreateNewOutputRequest::new(content_type); + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + // options + options.fill_request(&mut req); + + self.processor.create_new(req).await + } + pub async fn load(&self, target: ObjectId) -> BuckyResult<()> { let mut req = OpEnvLoadOutputRequest::new(target); req.common.target = self.target.clone(); @@ -676,7 +786,11 @@ impl IsolatePathOpEnvStub { self.processor.load(req).await } - pub async fn load_with_inner_path(&self, target: ObjectId, inner_path: impl Into) -> BuckyResult<()> { + pub async fn load_with_inner_path( + &self, + target: ObjectId, + inner_path: impl Into, + ) -> BuckyResult<()> { let mut req = OpEnvLoadOutputRequest::new_with_inner_path(target, inner_path); req.common.target = self.target.clone(); req.common.target_dec_id = self.target_dec_id.clone(); @@ -736,6 +850,24 @@ impl IsolatePathOpEnvStub { Ok(()) } + pub async fn create_new_with_key_and_option( + &self, + path: impl Into, + key: impl Into, + content_type: ObjectMapSimpleContentType, + options: &CreateObjectMapOption, + ) -> BuckyResult<()> { + let mut req = OpEnvCreateNewOutputRequest::new_with_path_and_key(path, key, content_type); + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + // options + options.fill_request(&mut req); + + self.processor.create_new(req).await?; + Ok(()) + } + pub async fn insert_with_key( &self, path: impl Into, @@ -810,6 +942,23 @@ impl IsolatePathOpEnvStub { Ok(()) } + pub async fn create_new_with_path_and_option( + &self, + full_path: impl Into, + content_type: ObjectMapSimpleContentType, + options: &CreateObjectMapOption, + ) -> BuckyResult<()> { + let mut req = OpEnvCreateNewOutputRequest::new_with_full_path(full_path, content_type); + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + // options + options.fill_request(&mut req); + + self.processor.create_new(req).await?; + Ok(()) + } + pub async fn insert_with_path( &self, full_path: impl Into, @@ -1003,8 +1152,14 @@ impl GlobalStateAccessorStub { Ok(resp.list) } - pub async fn list_by_page(&self, path: impl Into, page_index: u32, page_size: u32) -> BuckyResult> { - let mut req = RootStateAccessorListOutputRequest::new_with_page(path, page_index, page_size); + pub async fn list_by_page( + &self, + path: impl Into, + page_index: u32, + page_size: u32, + ) -> BuckyResult> { + let mut req = + RootStateAccessorListOutputRequest::new_with_page(path, page_index, page_size); req.common.target = self.target.clone(); req.common.target_dec_id = self.target_dec_id.clone(); From 6ba197ceab00a2ff15b6b53c4dcd80b65cb979b8 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:13:38 +0800 Subject: [PATCH 245/553] merge from buckyos --- src/component/cyfs-group/Cargo.toml | 2 +- src/component/cyfs-noc/src/blob/file.rs | 1 - src/component/cyfs-stack/Cargo.toml | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 599e13b51..aaab4ed76 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -28,7 +28,7 @@ async-recursion = '1.0' rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } -cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index 13838c174..9417d1377 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -4,7 +4,6 @@ use cyfs_lib::*; use std::borrow::Cow; use std::path::{Path, PathBuf}; -use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 1e9264e88..76148a72e 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -15,6 +15,7 @@ cyfs-bdt = { path = "../../component/cyfs-bdt" } cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } +cyfs-group = { path = "../../component/cyfs-group" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } From f4296f669076b490b8796b2dbfd8e25e7410f906 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:22:30 +0800 Subject: [PATCH 246/553] rename GroupRPathMgr to GroupManager --- .../src/dec/{rpath_mgr.rs => group_manager.rs} | 4 ++-- src/component/cyfs-group/src/dec/mod.rs | 4 ++-- src/component/cyfs-group/src/network/listener.rs | 6 +++--- src/component/cyfs-stack/src/stack/cyfs_stack.rs | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_mgr.rs => group_manager.rs} (99%) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/group_manager.rs similarity index 99% rename from src/component/cyfs-group/src/dec/rpath_mgr.rs rename to src/component/cyfs-group/src/dec/group_manager.rs index 644fc2fcf..56ef5e7d9 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -34,9 +34,9 @@ struct LocalInfo { } #[derive(Clone)] -pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); +pub struct GroupManager(Arc<(LocalInfo, RwLock)>); -impl GroupRPathMgr { +impl GroupManager { pub fn new( signer: RsaCPUObjectSigner, non_driver: Box, diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index a1f964e95..b4e753a27 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod delegate_factory; mod rpath_client; mod rpath_control; -mod rpath_mgr; +mod group_manager; pub use delegate_factory::*; pub use rpath_client::*; pub use rpath_control::*; -pub use rpath_mgr::*; +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6a6d7b549..e66ef8a43 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; -use crate::{GroupRPathMgr, HotstuffPackage}; +use crate::{GroupManager, HotstuffPackage}; pub struct Listener; impl Listener { pub fn spawn( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { async_std::task::spawn(async move { @@ -20,7 +20,7 @@ impl Listener { async fn run( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { loop { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 96eaad5cf..d208f57cf 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,9 +35,9 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; -use cyfs_group::GroupRPathMgr; +use cyfs_bdt::{DeviceCache, SnStatus, StackGuard}; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; +use cyfs_group::GroupManager; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -105,7 +105,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupRPathMgr, + group_manager: GroupManager, } impl CyfsStackImpl { @@ -431,7 +431,7 @@ impl CyfsStackImpl { config.clone(), ); - let group_manager = GroupRPathMgr::new( + let group_manager = GroupManager::new( signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), @@ -1162,7 +1162,7 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupRPathMgr { + pub fn group_mgr(&self) -> &GroupManager { &self.stack.group_manager } From b951356ad304e591156c11ac9d0e726f8c8cc3b9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 21:19:34 +0800 Subject: [PATCH 247/553] integrate GroupState, not finish --- .../cyfs-base/src/objects/object_map/mod.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 4 + .../cyfs-group/src/statepath/design.md | 26 +-- .../src/storage/engine/group_state_path.rs | 178 +++++++++++++++ .../cyfs-group/src/storage/engine/mod.rs | 9 + .../src/storage/engine/storage_engine.rs | 23 ++ .../engine/storage_engine_group_state.rs | 207 ++++++++++++++++++ .../storage_engine_mock.rs} | 53 ++--- .../cyfs-group/src/storage/group_storage.rs | 71 +++++- src/component/cyfs-group/src/storage/mod.rs | 4 +- 12 files changed, 524 insertions(+), 70 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs create mode 100644 src/component/cyfs-group/src/storage/engine/mod.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs rename src/component/cyfs-group/src/storage/{storage_engine.rs => engine/storage_engine_mock.rs} (76%) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index be52c2ea5..3bbc5f131 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -2,6 +2,7 @@ mod access; mod cache; mod check; mod diff; +mod isolate_path_env; mod iterator; mod lock; mod object_map; @@ -13,7 +14,6 @@ mod path_iterator; mod root; mod single_env; mod visitor; -mod isolate_path_env; pub use access::*; pub use cache::*; @@ -25,4 +25,5 @@ pub use path::*; pub use path_env::*; pub use path_iterator::*; pub use root::*; +pub use single_env::*; pub use visitor::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ff4e06380..e89498b83 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -18,7 +18,7 @@ use crate::{ consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** @@ -1461,12 +1461,13 @@ impl HotstuffRunner { continue; } - if let Some(ending) = proposal.effective_ending() { - if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.desc().object_id()); - timeout_proposals.push(proposal); - continue; - } + let ending = proposal.effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), + |ending| bucky_time_to_system_time(ending)); + if now >= ending { + remove_proposals.push(proposal.desc().object_id()); + timeout_proposals.push(proposal); + continue; } match self.delegate.on_execute(&proposal, result_state_id).await { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index aa7babc44..1170176b2 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,6 +14,7 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 56ef5e7d9..95c931720 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,6 +6,7 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, @@ -31,6 +32,7 @@ struct LocalInfo { non_driver: Arc>, datagram: DatagramTunnelGuard, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl GroupManager { signer: RsaCPUObjectSigner, non_driver: Box, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); @@ -50,6 +53,7 @@ impl GroupManager { non_driver: Arc::new(non_driver), datagram: datagram.clone(), bdt_stack, + global_state_mgr, }; let raw = GroupRPathMgrRaw { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index b73a46939..7ec71d4d5 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -7,22 +7,18 @@ | |--list-->Set | |--option-->GroupOption | -|--.dec-state // for dec;各Group的dec状态放这里 -| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 -| |--${dec-id} | .group // 一个dec管理的${r-path}状态 -| | | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | -| -|--.link // 区块链结构,记录状态变更链条 -| |--${group-id} -| |--${dec-id} | .group // .group表示group本身的演变共识 +|--${group-id} +| |--${dec-id} +| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 +| | // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-chunk-->Chunk(Group) +| |--group-blob-->BLOB(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs new file mode 100644 index 000000000..4e67d6e1f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/group_state_path.rs @@ -0,0 +1,178 @@ +use cyfs_base::ObjectId; + +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; + +pub struct GroupStatePath { + rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, +} + +impl GroupStatePath { + pub fn new(rpath: String) -> Self { + Self { + rpath, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.rpath.as_str() + } + + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() + } + + pub fn link(&self) -> &str { + self.link.as_str() + } + + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() + } + + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() + } + + pub fn range(&self) -> &str { + self.range.as_str() + } + + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) + } + + pub fn commit_block(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn commit_proposals(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_PROPOSALS, + ]) + } + + pub fn prepares(&self) -> &str { + self.prepares.as_str() + } + + pub fn prepare_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() + } + + pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.pre_commits.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() + } + + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() + } + + pub fn recycle(&self) -> &str { + self.recycle.as_str() + } + + pub fn adding(&self) -> &str { + self.adding.as_str() + } +} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs new file mode 100644 index 000000000..71d5cc49f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -0,0 +1,9 @@ +mod group_state_path; +mod storage_engine; +mod storage_engine_group_state; +mod storage_engine_mock; + +pub(super) use group_state_path::*; +pub(super) use storage_engine::*; +pub(super) use storage_engine_group_state::*; +pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs new file mode 100644 index 000000000..e48e607bc --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -0,0 +1,23 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Send + Sync + Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs new file mode 100644 index 000000000..3aba73e31 --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -0,0 +1,207 @@ +use std::{collections::HashSet, sync::Arc}; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, +}; + +use crate::StatePath; + +use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; + +const ACCESS: Option = None; + +#[derive(Clone)] +pub struct StorageEngineGroupState { + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, +} + +impl StorageEngineGroupState { + pub async fn load( + dec_group_state: ObjectMapRootManagerRef, + state_path: GroupStatePath, + ) -> BuckyResult { + Ok(Self { + state_mgr: todo!(), + state_path: Arc::new(state_path), + }) + } + + pub async fn create_writer(&self) -> BuckyResult { + Ok( + StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) + .await?, + ) + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineGroupState { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + let op_env = self.state_mgr.create_op_env(ACCESS)?; + let block_id = op_env + .get_by_path(self.state_path.commit_block(height).as_str()) + .await?; + block_id.map_or( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), + |block_id| Ok(block_id), + ) + } +} + +#[derive(Clone)] +pub struct StorageEngineGroupStateWriter { + state_mgr: ObjectMapRootManagerRef, + op_env: ObjectMapPathOpEnvRef, + prepare_op_env: ObjectMapSingleOpEnvRef, + prepare_map_id: Option, + state_path: Arc, +} + +impl StorageEngineGroupStateWriter { + async fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; + let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; + match prepare_map_id.as_ref() { + Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, + None => { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await? + } + }; + + Ok(Self { + op_env, + prepare_op_env, + state_path, + state_mgr, + prepare_map_id, + }) + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; + new_prepare + .create_new(ObjectMapSimpleContentType::Map) + .await?; + new_prepare + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + let new_prepare_block = new_prepare.commit().await?; + + self.prepare_op_env + .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .await + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str()) + .await? + .is_some() + { + assert!(false); + } + + // TODO + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineGroupStateWriter<'a> { + fn drop(&mut self) {} +} diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs similarity index 76% rename from src/component/cyfs-group/src/storage/storage_engine.rs rename to src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b9376618b..6208b0680 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -2,28 +2,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -#[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; - async fn push_proposals( - &mut self, - proposal_ids: &[ObjectId], - timestamp: u64, - ) -> BuckyResult<()>; - - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; -} - -#[async_trait::async_trait] -pub trait StorageEngine { - async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult; - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; -} +use super::{StorageEngine, StorageWriter}; struct StorageEngineMockFinishProposalMgr { flip_timestamp: u64, @@ -58,6 +37,10 @@ impl StorageEngineMock { }, } } + + pub async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) + } } #[async_trait::async_trait] @@ -69,19 +52,15 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult { - Ok(StorageEngineMockWriter { engine: self }) - } - - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { - let is_finished = self - .finish_proposals - .adding - .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) - .is_some(); - Ok(is_finished) - } + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + // let is_finished = self + // .finish_proposals + // .adding + // .get(proposal_id) + // .or(self.finish_proposals.over.get(proposal_id)) + // .is_some(); + // Ok(is_finished) + // } } pub struct StorageEngineMockWriter<'a> { @@ -164,9 +143,9 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: u64, + timestamp: Option, ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + if let Some(timestamp) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 440613f51..bc9fc6009 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, time::SystemTime}; +use std::{ + collections::{HashMap, HashSet}, + time::SystemTime, +}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, @@ -6,10 +9,13 @@ use cyfs_base::{ }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; + +use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; +use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; -use super::{storage_engine::StorageEngineMock, StorageEngine}; +const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; pub enum BlockLinkState { Expired, @@ -23,6 +29,12 @@ pub enum BlockLinkState { InvalidBranch, } +struct FinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -39,6 +51,8 @@ pub struct GroupStorage { prepares: HashMap, pre_commits: HashMap, + finish_proposals: FinishProposalMgr, + storage_engine: StorageEngineMock, } @@ -50,11 +64,19 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + // let group_state = root_state_mgr + // .load_root_state(group_id, Some(group_id.clone()), true) + // .await? + // .expect("create group state failed."); + + // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + Ok(Self { group, group_id: group_id.clone(), @@ -70,6 +92,11 @@ impl GroupStorage { pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), local_device_id, + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, }) } @@ -78,6 +105,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -240,10 +268,17 @@ impl GroupStorage { .iter() .map(|p| p.proposal.clone()) .collect(); - writer.push_proposals( - finish_proposals.as_slice(), - new_header.named_object().desc().create_time(), - ); + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + writer + .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } // update memory @@ -276,6 +311,20 @@ impl GroupStorage { if self.first_block.is_none() { self.first_block = self.header_block.clone(); } + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.finish_proposals.over); + self.finish_proposals.flip_timestamp = timestamp; + } + + for proposal in new_header.proposals() { + let is_new = self.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -551,7 +600,13 @@ impl GroupStorage { // find in storage - self.storage_engine.is_proposal_finished(proposal_id).await + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d95cf7ddd..d4440419e 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,7 @@ mod dec_storage; +mod engine; mod group_storage; -mod storage_engine; pub use dec_storage::*; +use engine::*; pub use group_storage::*; -pub(crate) use storage_engine::*; From b5431fea71370557d5ed02d15ad2e8c8be289be9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 17:28:17 +0800 Subject: [PATCH 248/553] integrate GroupState update --- .../cyfs-group/src/statepath/design.md | 11 +- .../src/statepath/group_statepath.rs | 257 +++++------- .../src/storage/engine/group_state_path.rs | 178 --------- .../cyfs-group/src/storage/engine/mod.rs | 2 - .../src/storage/engine/storage_engine.rs | 17 +- .../engine/storage_engine_group_state.rs | 367 +++++++++++++----- .../src/storage/engine/storage_engine_mock.rs | 30 +- .../cyfs-group/src/storage/group_storage.rs | 30 +- .../cyfs-stack/src/stack/cyfs_stack.rs | 1 + 9 files changed, 439 insertions(+), 454 deletions(-) delete mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 7ec71d4d5..70a61e428 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -25,15 +25,10 @@ | |--last-vote-round-->u64 // 最后一次投票的轮次 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height}) -| | |--block-->GroupConsensusBlock +| |--str(${height})->block | | -| |--prepares // Prepare状态的block -| | |--${block.id} -| | |--block -| |--pre-commits // pre-commit状态的block -| | |--${block.id} -| | |--block +| |--prepares->Set // Prepare状态的block +| |--pre-commits->Set // pre-commit状态的block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index c0daef478..eade0f9e4 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,19 +1,17 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; -pub const STATEPATH_SEPARATOR: &str = "/"; - -pub const STATEPATH_GROUPS: &str = "groups"; - -pub const STATEPATH_DEC_STATE: &str = ".dec-state"; - -pub const STATEPATH_LINK: &str = ".link"; -pub const STATEPATH_GROUP_HASH: &str = "group-hash"; -pub const STATEPATH_USERS: &str = "users"; -pub const STATEPATH_USERS_NONCE: &str = "nonce"; -pub const STATEPATH_RANGE: &str = "range"; -pub const STATEPATH_BLOCK: &str = "block"; - -pub const STATEPATH_RPATHS: &str = ".r-paths"; +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; @@ -23,180 +21,131 @@ lazy_static::lazy_static! { pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } -pub struct StatePath { - group_id: ObjectId, - group_id_str: String, - dec_id: ObjectId, - dec_id_str: String, +pub struct GroupStatePath { rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, } -impl StatePath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { +impl GroupStatePath { + pub fn new(rpath: String) -> Self { Self { - group_id_str: group_id.to_string(), - group_id, - dec_id_str: dec_id.to_string(), - dec_id, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), rpath, } } pub fn join(fields: &[&str]) -> String { - fields.join(STATEPATH_SEPARATOR) - } - - pub fn dec_state() -> String { - STATEPATH_DEC_STATE.to_string() - } - - pub fn dec_state_group(&self) -> String { - Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) - } - - pub fn dec_state_dec(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + fields.join(STATE_PATH_SEPARATOR) } - pub fn dec_state_rpath(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn root(&self) -> &str { + self.rpath.as_str() } - pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - sub_path, - ]) + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() } - pub fn link() -> String { - STATEPATH_LINK.to_string() + pub fn link(&self) -> &str { + self.link.as_str() } - pub fn link_group(&self) -> String { - Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() } - pub fn link_dec(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() } - pub fn link_rpath(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn range(&self) -> &str { + self.range.as_str() } - pub fn link_group_hash(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_GROUP_HASH, - ]) + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) } - pub fn link_users(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - ]) + pub fn prepares(&self) -> &str { + self.prepares.as_str() } - pub fn link_user(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - ]) + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() } - pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - STATEPATH_USERS_NONCE, - ]) + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() } - pub fn link_range(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_RANGE, - ]) - } - - pub fn link_height(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - ]) - } - - pub fn link_block(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - STATEPATH_BLOCK, - ]) - } - - pub fn rpaths(&self) -> String { - STATEPATH_RPATHS.to_string() - } -} - -pub struct GroupUpdateStatePath; - -impl GroupUpdateStatePath { - pub fn latest_version() -> &'static str { - STATEPATH_GROUP_DEC_LATEST_VERSION + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() } - pub fn version_seq(version_seq: u64) -> String { - version_seq.to_string() + pub fn recycle(&self) -> &str { + self.recycle.as_str() } - pub fn group_hash(group_hash: &ObjectId) -> String { - group_hash.to_string() + pub fn adding(&self) -> &str { + self.adding.as_str() } } diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs deleted file mode 100644 index 4e67d6e1f..000000000 --- a/src/component/cyfs-group/src/storage/engine/group_state_path.rs +++ /dev/null @@ -1,178 +0,0 @@ -use cyfs_base::ObjectId; - -pub const STATE_PATH_SEPARATOR: &str = "/"; -pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; -pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; -pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; -pub const GROUP_STATE_PATH_RANGE: &str = "range"; -pub const GROUP_STATE_PATH_BLOCK: &str = "block"; -pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; -pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; -pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; -pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; -pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; -pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; -pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; -pub const GROUP_STATE_PATH_ADDING: &str = "adding"; - -pub struct GroupStatePath { - rpath: String, - dec_state: String, - link: String, - group_blob: String, - last_vote_round: String, - range: String, - prepares: String, - pre_commits: String, - finish_proposals: String, - flip_time: String, - recycle: String, - adding: String, -} - -impl GroupStatePath { - pub fn new(rpath: String) -> Self { - Self { - rpath, - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, - ]), - last_vote_round: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, - ]), - range: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_RANGE, - ]), - prepares: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PREPARES, - ]), - pre_commits: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PRE_COMMITS, - ]), - finish_proposals: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - ]), - flip_time: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_FLIP_TIME, - ]), - recycle: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_RECYCLE, - ]), - adding: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_ADDING, - ]), - } - } - - pub fn join(fields: &[&str]) -> String { - fields.join(STATE_PATH_SEPARATOR) - } - - pub fn root(&self) -> &str { - self.rpath.as_str() - } - - pub fn dec_state(&self) -> &str { - self.dec_state.as_str() - } - - pub fn link(&self) -> &str { - self.link.as_str() - } - - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() - } - - pub fn last_vote_round(&self) -> &str { - self.last_vote_round.as_str() - } - - pub fn range(&self) -> &str { - self.range.as_str() - } - - pub fn commit_height(&self, height: u64) -> String { - Self::join(&[self.link.as_str(), height.to_string().as_str()]) - } - - pub fn commit_block(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn commit_proposals(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_PROPOSALS, - ]) - } - - pub fn prepares(&self) -> &str { - self.prepares.as_str() - } - - pub fn prepare_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.prepares.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn pre_commits(&self) -> &str { - self.pre_commits.as_str() - } - - pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.pre_commits.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn finish_proposals(&self) -> &str { - self.finish_proposals.as_str() - } - - pub fn flip_time(&self) -> &str { - self.flip_time.as_str() - } - - pub fn recycle(&self) -> &str { - self.recycle.as_str() - } - - pub fn adding(&self) -> &str { - self.adding.as_str() - } -} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs index 71d5cc49f..c185cb24c 100644 --- a/src/component/cyfs-group/src/storage/engine/mod.rs +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -1,9 +1,7 @@ -mod group_state_path; mod storage_engine; mod storage_engine_group_state; mod storage_engine_mock; -pub(super) use group_state_path::*; pub(super) use storage_engine::*; pub(super) use storage_engine_group_state::*; pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e48e607bc..e19c46b81 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,19 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { +pub trait StorageWriter: Send + Sync { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()>; async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()>; - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + + async fn commit(mut self) -> BuckyResult<()>; } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 3aba73e31..731725e95 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use crate::StatePath; +use crate::{ + GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, +}; -use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; +use super::{StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -41,7 +44,7 @@ impl StorageEngine for StorageEngineGroupState { async fn find_block_by_height(&self, height: u64) -> BuckyResult { let op_env = self.state_mgr.create_op_env(ACCESS)?; let block_id = op_env - .get_by_path(self.state_path.commit_block(height).as_str()) + .get_by_path(self.state_path.commit_height(height).as_str()) .await?; block_id.map_or( Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), @@ -57,6 +60,7 @@ pub struct StorageEngineGroupStateWriter { prepare_op_env: ObjectMapSingleOpEnvRef, prepare_map_id: Option, state_path: Arc, + write_result: BuckyResult<()>, } impl StorageEngineGroupStateWriter { @@ -65,16 +69,20 @@ impl StorageEngineGroupStateWriter { state_path: Arc, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; - let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; - match prepare_map_id.as_ref() { - Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, - None => { - prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await? - } - }; + let prepare_map_id = + if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { + if err.code() == BuckyErrorCode::NotFound { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + None + } else { + return Err(err); + } + } else { + prepare_op_env.get_current_root().await + }; Ok(Self { op_env, @@ -82,126 +90,299 @@ impl StorageEngineGroupStateWriter { state_path, state_mgr, prepare_map_id, + write_result: Ok(()), }) } -} - -#[async_trait::async_trait] -impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { - let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; - new_prepare - .create_new(ObjectMapSimpleContentType::Map) - .await?; - new_prepare - .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) - .await?; - let new_prepare_block = new_prepare.commit().await?; + async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { self.prepare_op_env - .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .insert(block_id) .await + .map(|is_changed| assert!(is_changed)) } - async fn insert_pre_commit( + async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, is_instead: bool, ) -> BuckyResult<()> { - if !self - .prepare_op_env - .remove_with_key(block_id.to_string().as_str()) - .await? - .is_some() - { - assert!(false); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); - // TODO if is_instead { - self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); - } else { - if !self.engine.pre_commit_blocks.insert(block_id.clone()) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block pre-commit twice", - )); - } + self.op_env + .remove_with_path(self.state_path.pre_commits(), &None) + .await?; } - Ok(()) + self.op_env + .insert_with_path(self.state_path.pre_commits(), block_id) + .await } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if self - .engine - .commit_blocks - .insert(height, block_id.clone()) - .is_some() - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block commit twice", - )); - } + async fn push_commit_inner( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.op_env + .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) + .await?; - self.engine.block_height_range.1 = height; + let range_obj = make_range_obj(min_height, height); + if height == 1 { + self.op_env + .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) + .await?; + } else { + let prev_range = make_range_obj(min_height, height - 1); + let prev_value = self + .op_env + .set_with_key( + self.state_path.link(), + GROUP_STATE_PATH_RANGE, + &range_obj, + &Some(prev_range), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_range); + }; + + // update state from dec-app + if result_state_id == prev_result_state_id { + return Ok(()); + } else { + match result_state_id { + Some(result_state_id) => { + if prev_result_state_id.is_none() { + self.op_env + .insert_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + ) + .await?; + } else { + let prev_value = self + .op_env + .set_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + prev_result_state_id, + false, + ) + .await?; + assert_eq!(&prev_value, prev_result_state_id); + } + } + None => { + self.op_env + .remove_with_path(self.state_path.dec_state(), prev_result_state_id) + .await?; + } + } + } Ok(()) } - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - if !self.engine.prepare_blocks.remove(block_id) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "try remove prepare not exists", - )); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); } Ok(()) } - async fn push_proposals( + async fn push_proposals_inner( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); - self.engine.finish_proposals.flip_timestamp = timestamp; + if proposal_ids.is_empty() { + return Ok(()); } - for proposal_id in proposal_ids { - if !self - .engine - .finish_proposals - .adding - .insert(proposal_id.clone()) - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "dup finish proposal", - )); + let add_single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + + if let Some((timestamp, prev_timestamp)) = timestamp { + let new_over = self + .op_env + .remove_with_path(self.state_path.adding(), &None) + .await?; + + if let Some(new_over) = new_over.as_ref() { + self.op_env + .set_with_path(self.state_path.recycle(), new_over, &None, true) + .await?; } + + let timestamp_obj = make_u64_obj(timestamp); + if prev_timestamp != 0 { + let prev_timestamp_obj = make_u64_obj(prev_timestamp); + let prev_value = self + .op_env + .set_with_path( + self.state_path.flip_time(), + ×tamp_obj, + &Some(prev_timestamp_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_timestamp_obj); + } else { + self.op_env + .insert_with_key( + self.state_path.finish_proposals(), + GROUP_STATE_PATH_FLIP_TIME, + ×tamp_obj, + ) + .await?; + } + + add_single_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + } else { + add_single_op_env + .load_by_path(self.state_path.adding()) + .await?; } + for proposal_id in proposal_ids { + let is_new = add_single_op_env.insert(proposal_id).await?; + assert!(is_new); + } + let adding_set_id = add_single_op_env.commit().await?; + let prev_value = self + .op_env + .set_with_path(self.state_path.adding(), &adding_set_id, &None, true) + .await?; + Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - self.engine.last_vote_round = round; + async fn set_last_vote_round_inner(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert!(round > prev_value); + if round == prev_value { + return Ok(()); + } - Ok(()) + let round_obj = make_u64_obj(round); + + if prev_value == 0 { + self.op_env + .insert_with_path(self.state_path.last_vote_round(), &round_obj) + .await + } else { + let prev_obj = make_u64_obj(prev_value); + let prev_value = self + .op_env + .set_with_path( + self.state_path.last_vote_round(), + &round_obj, + &Some(prev_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_obj); + Ok(()) + } + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result.clone() + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result.clone() + } + + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self + .push_commit_inner( + height, + block_id, + result_state_id, + prev_result_state_id, + min_height, + ) + .await; + self.write_result.clone() + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.remove_prepares_inner(block_ids).await; + self.write_result.clone() + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.push_proposals_inner(proposal_ids, timestamp).await; + self.write_result.clone() + } + + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.set_last_vote_round_inner(round, prev_value).await; + self.write_result.clone() + } + + async fn commit(mut self) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + + let prepare_map_id = self.prepare_op_env.commit().await?; + self.op_env + .set_with_path( + self.state_path.prepares(), + &prepare_map_id, + &self.prepare_map_id, + self.prepare_map_id.is_none(), + ) + .await?; + self.op_env.commit().await.map(|_| ()) } } -impl<'a> Drop for StorageEngineGroupStateWriter<'a> { - fn drop(&mut self) {} +fn make_range_obj(min: u64, max: u64) -> ObjectId { + let mut range_buf = [0u8; 24]; + let (low, high) = range_buf.split_at_mut(12); + low.copy_from_slice(&min.to_le_bytes()); + high.copy_from_slice(&max.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() +} + +fn make_u64_obj(value: u64) -> ObjectId { + let mut range_buf = [0u8; 8]; + range_buf.copy_from_slice(&value.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 6208b0680..b944d3735 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -13,6 +13,7 @@ struct StorageEngineMockFinishProposalMgr { pub struct StorageEngineMock { last_vote_round: u64, + result_state_id: Option, block_height_range: (u64, u64), commit_blocks: HashMap, @@ -30,6 +31,7 @@ impl StorageEngineMock { commit_blocks: HashMap::new(), prepare_blocks: HashSet::new(), pre_commit_blocks: HashSet::new(), + result_state_id: None, finish_proposals: StorageEngineMockFinishProposalMgr { flip_timestamp: 0, over: HashSet::new(), @@ -108,7 +110,18 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + assert!(height > min_height); + assert_eq!(height, self.engine.block_height_range.1 + 1); + assert_eq!(prev_result_state_id, &self.engine.result_state_id); + if self .engine .commit_blocks @@ -123,6 +136,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } self.engine.block_height_range.1 = height; + self.engine.result_state_id = result_state_id.clone(); Ok(()) } @@ -143,12 +157,13 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if let Some(timestamp) = timestamp { + if let Some((timestamp, prev_timestamp)) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + assert_eq!(prev_timestamp, self.engine.finish_proposals.flip_timestamp); self.engine.finish_proposals.flip_timestamp = timestamp; } @@ -170,13 +185,14 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert_eq!(self.engine.last_vote_round, prev_value); self.engine.last_vote_round = round; Ok(()) } -} -impl<'a> Drop for StorageEngineMockWriter<'a> { - fn drop(&mut self) {} + async fn commit(mut self) -> BuckyResult<()> { + Ok(()) + } } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index bc9fc6009..a7284f403 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -13,7 +13,7 @@ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; +use super::{engine::StorageEngineMock, StorageEngine}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -42,15 +42,14 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, + group_chunk_id: ObjectId, dec_state_id: Option, // commited/header state id - group_chunk_id: ObjectId, last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, prepares: HashMap, pre_commits: HashMap, - finish_proposals: FinishProposalMgr, storage_engine: StorageEngineMock, @@ -258,7 +257,15 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit(new_header.height(), new_header.block_id().object_id()) + .push_commit( + new_header.height(), + new_header.block_id().object_id(), + new_header.result_state_id(), + self.header_block + .as_ref() + .map_or(&None, |b| b.result_state_id()), + self.first_block.as_ref().map_or(0, |b| b.height()), + ) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -272,7 +279,10 @@ impl GroupStorage { let timestamp = new_header.named_object().desc().create_time(); if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer - .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.finish_proposals.flip_timestamp)), + ) .await?; } else { writer @@ -281,6 +291,8 @@ impl GroupStorage { } } + writer.commit().await?; + // update memory if self .prepares @@ -293,7 +305,6 @@ impl GroupStorage { match new_header { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); - self.header_block = Some(new_header); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); self.prepares.remove(&new_pre_commit.0); @@ -309,7 +320,7 @@ impl GroupStorage { } if self.first_block.is_none() { - self.first_block = self.header_block.clone(); + self.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); @@ -325,6 +336,7 @@ impl GroupStorage { assert!(is_new); } + self.header_block = Some(new_header); return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -359,7 +371,9 @@ impl GroupStorage { // storage let mut writer = self.storage_engine.create_writer().await?; - writer.set_last_vote_round(round).await?; + writer + .set_last_vote_round(round, self.last_vote_round) + .await?; self.last_vote_round = round; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index d208f57cf..8cf9bcad0 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -435,6 +435,7 @@ impl CyfsStackImpl { signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), + global_state_manager.clone_processor(), )?; let mut stack = Self { From 7ed364755a5f3cd55531e8b72d1ad9db32ce6571 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 20:15:19 +0800 Subject: [PATCH 249/553] integrate GroupState load --- .../cyfs-group/src/dec/group_manager.rs | 12 +- .../src/storage/engine/storage_engine.rs | 37 ++++ .../engine/storage_engine_group_state.rs | 180 ++++++++++++++-- .../cyfs-group/src/storage/group_storage.rs | 198 ++++++++++-------- 4 files changed, 327 insertions(+), 100 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95c931720..5ecfcdba2 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -372,6 +372,7 @@ impl GroupManager { let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -379,7 +380,15 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; + let store = GroupStorage::load( + group_id, + dec_id, + rpath, + non_driver.clone(), + local_device_id.object_id().clone(), + &root_state_mgr, + ) + .await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -430,6 +439,7 @@ impl GroupManager { init_state, non_driver.clone(), local_device_id.object_id().clone(), + &root_state_mgr, ) .await? } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e19c46b81..735277a3a 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,4 +1,41 @@ +use std::collections::{HashMap, HashSet}; + use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct FinishProposalMgr { + pub flip_timestamp: u64, + pub over: HashSet, + pub adding: HashSet, +} + +pub struct StorageCacheInfo { + pub dec_state_id: Option, // commited/header state id + pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub header_block: Option, + pub first_block: Option, + pub prepares: HashMap, + pub pre_commits: HashMap, + pub finish_proposals: FinishProposalMgr, +} + +impl StorageCacheInfo { + pub fn new(init_state_id: Option) -> Self { + Self { + dec_state_id: init_state_id, + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 731725e95..ee429a78f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,16 +1,18 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, - ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, + ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_RANGE, }; -use super::{StorageEngine, StorageWriter}; +use super::{StorageCacheInfo, StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -21,14 +23,110 @@ pub struct StorageEngineGroupState { } impl StorageEngineGroupState { - pub async fn load( - dec_group_state: ObjectMapRootManagerRef, - state_path: GroupStatePath, - ) -> BuckyResult { - Ok(Self { - state_mgr: todo!(), + pub(crate) async fn load_cache( + state_mgr: &ObjectMapRootManagerRef, + non_driver: &NONDriverHelper, + state_path: &GroupStatePath, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; + + let last_vote_round = op_env + .get_by_path(state_path.last_vote_round()) + .await? + .map(|id| parse_u64_obj(&id)); + + let mut first_header_block_ids: Vec = vec![]; + let commit_range = op_env + .get_by_path(state_path.range()) + .await? + .map(|id| parse_range_obj(&id)); + let commit_block = match commit_range { + Some((first_height, header_height)) => { + let first_block_id = op_env + .get_by_path(state_path.commit_height(first_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(first_block_id); + + if header_height == first_height { + Some((first_block_id, first_block_id)) + } else { + let header_block_id = op_env + .get_by_path(state_path.commit_height(header_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(header_block_id); + Some((first_block_id, header_block_id)) + } + } + None => None, + }; + + let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let pre_commit_block_ids = + load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + + let flip_timestamp = op_env + .get_by_path(state_path.flip_time()) + .await? + .map_or(0, |id| parse_u64_obj(&id)); + + let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; + let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + + let load_block_ids = [ + first_header_block_ids.as_slice(), + prepare_block_ids.as_slice(), + pre_commit_block_ids.as_slice(), + ] + .concat(); + + let load_blocks = futures::future::join_all( + load_block_ids + .iter() + .map(|id| non_driver.get_block(id, None)), + ) + .await; + + let mut cache = StorageCacheInfo::new(dec_state_id); + cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); + cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); + cache.finish_proposals.flip_timestamp = flip_timestamp; + + let prepare_block_pos = match commit_block { + Some((first_block_id, header_block_id)) => { + cache.first_block = Some(load_blocks.get(0).unwrap().clone()?); + if header_block_id == first_block_id { + cache.header_block = cache.first_block.clone(); + 1 + } else { + cache.header_block = Some(load_blocks.get(1).unwrap().clone()?); + 2 + } + } + None => 0, + }; + + let (prepare_blocks, pre_commit_blocks) = + load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); + for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { + cache.prepares.insert(block_id, block.clone()?); + } + for (block, block_id) in pre_commit_blocks.iter().zip(pre_commit_block_ids) { + cache.pre_commits.insert(block_id, block.clone()?); + } + + Ok(cache) + } + + pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + Self { + state_mgr, state_path: Arc::new(state_path), - }) + } } pub async fn create_writer(&self) -> BuckyResult { @@ -132,12 +230,14 @@ impl StorageEngineGroupStateWriter { .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) .await?; - let range_obj = make_range_obj(min_height, height); if height == 1 { + let range_obj = make_range_obj(1, height); self.op_env .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) .await?; } else { + assert!(min_height < height); + let range_obj = make_range_obj(min_height, height); let prev_range = make_range_obj(min_height, height - 1); let prev_value = self .op_env @@ -376,13 +476,63 @@ impl StorageWriter for StorageEngineGroupStateWriter { fn make_range_obj(min: u64, max: u64) -> ObjectId { let mut range_buf = [0u8; 24]; let (low, high) = range_buf.split_at_mut(12); - low.copy_from_slice(&min.to_le_bytes()); - high.copy_from_slice(&max.to_le_bytes()); + low[..8].copy_from_slice(&min.to_le_bytes()); + high[..8].copy_from_slice(&max.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } +fn parse_range_obj(obj: &ObjectId) -> (u64, u64) { + let range_buf = obj.data(); + assert_eq!(range_buf.len(), 24); + let (low_buf, high_buf) = range_buf.split_at(12); + let mut low = [0u8; 8]; + low.copy_from_slice(&low_buf[..8]); + let mut high = [0u8; 8]; + high.copy_from_slice(&high_buf[..8]); + + (u64::from_le_bytes(low), u64::from_le_bytes(high)) +} + fn make_u64_obj(value: u64) -> ObjectId { let mut range_buf = [0u8; 8]; range_buf.copy_from_slice(&value.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } + +fn parse_u64_obj(obj: &ObjectId) -> u64 { + let mut buf = [0u8; 8]; + buf.copy_from_slice(obj.data()); + u64::from_le_bytes(buf) +} + +async fn load_object_ids_with_path( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Set(id) => object_ids.push(id.clone()), + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a7284f403..5ad19ea15 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -11,9 +11,14 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::GlobalStateManagerRawProcessorRef; -use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; +use crate::{ + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, +}; -use super::{engine::StorageEngineMock, StorageEngine}; +use super::{ + engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + StorageEngine, +}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -29,12 +34,6 @@ pub enum BlockLinkState { InvalidBranch, } -struct FinishProposalMgr { - flip_timestamp: u64, - over: HashSet, - adding: HashSet, -} - pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -44,15 +43,9 @@ pub struct GroupStorage { non_driver: NONDriverHelper, group_chunk_id: ObjectId, - dec_state_id: Option, // commited/header state id - last_vote_round: u64, // 参与投票的最后一个轮次 - header_block: Option, - first_block: Option, - prepares: HashMap, - pre_commits: HashMap, - finish_proposals: FinishProposalMgr, + cache: StorageCacheInfo, - storage_engine: StorageEngineMock, + storage_engine: StorageEngineGroupState, } impl GroupStorage { @@ -63,18 +56,18 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); - // let group_state = root_state_mgr - // .load_root_state(group_id, Some(group_id.clone()), true) - // .await? - // .expect("create group state failed."); + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); - // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; Ok(Self { group, @@ -82,20 +75,13 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - dec_state_id: init_state_id, group_chunk_id: group_chunk_id.object_id(), - last_vote_round: 0, - header_block: None, - first_block: None, - prepares: HashMap::new(), - pre_commits: HashMap::new(), - storage_engine: StorageEngineMock::new(), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + GroupStatePath::new(rpath.to_string()), + ), local_device_id, - finish_proposals: FinishProposalMgr { - flip_timestamp: 0, - over: HashSet::new(), - adding: HashSet::new(), - }, + cache: StorageCacheInfo::new(init_state_id), }) } @@ -104,37 +90,62 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - // unimplemented!() - Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); + + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + + let state_path = GroupStatePath::new(rpath.to_string()); + let cache = + StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + group_chunk_id: group_chunk_id.object_id(), + storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + local_device_id, + cache: cache, + }) } pub fn header_block(&self) -> &Option { - &self.header_block + &self.cache.header_block } pub fn header_round(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.round()) + self.cache.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.height()) + self.cache.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - &self.first_block + &self.cache.first_block } pub fn prepares(&self) -> &HashMap { - &self.prepares + &self.cache.prepares } pub fn pre_commits(&self) -> &HashMap { - &self.pre_commits + &self.cache.pre_commits } pub fn group(&self) -> &Group { @@ -146,34 +157,37 @@ impl GroupStorage { } pub fn dec_state_id(&self) -> &Option { - &self.dec_state_id + &self.cache.dec_state_id } pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { let header_height = self.header_height(); let block = match height.cmp(&header_height) { std::cmp::Ordering::Less => { - if height == self.first_block.as_ref().map_or(0, |b| b.height()) { - self.first_block.clone() + if height == self.cache.first_block.as_ref().map_or(0, |b| b.height()) { + self.cache.first_block.clone() } else { // find in storage let block_id = self.storage_engine.find_block_by_height(height).await?; Some(self.non_driver.get_block(&block_id, None).await?) } } - std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Equal => self.cache.header_block.clone(), std::cmp::Ordering::Greater => { if height == header_height + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.height() == height) .or(self + .cache .prepares .iter() .find(|(_, block)| block.height() == height)) .map(|(_, block)| block.clone()) } else if height == header_height + 2 { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.height() == height) .map(|(_, block)| block.clone()) @@ -202,16 +216,17 @@ impl GroupStorage { // prepare update memory if let Some(prev_block_id) = prev_block_id { - if let Some(prev_block) = self.prepares.get(prev_block_id) { + if let Some(prev_block) = self.cache.prepares.get(prev_block_id) { new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); if let Some(prev_prev_block_id) = prev_block.prev_block_id() { - if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + if let Some(prev_prev_block) = self.cache.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); assert_eq!( prev_prev_block.prev_block_id(), - self.header_block + self.cache + .header_block .as_ref() .map(|b| b.block_id().object_id().clone()) .as_ref() @@ -220,7 +235,7 @@ impl GroupStorage { new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.block_id().object_id(); - for (id, block) in self.prepares.iter() { + for (id, block) in self.cache.prepares.iter() { if block.prev_block_id().map(|prev_id| { assert_ne!(prev_id, prev_block_id); prev_id == new_header_id @@ -261,10 +276,11 @@ impl GroupStorage { new_header.height(), new_header.block_id().object_id(), new_header.result_state_id(), - self.header_block + self.cache + .header_block .as_ref() .map_or(&None, |b| b.result_state_id()), - self.first_block.as_ref().map_or(0, |b| b.height()), + self.cache.first_block.as_ref().map_or(0, |b| b.height()), ) .await?; @@ -277,11 +293,11 @@ impl GroupStorage { .collect(); let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer .push_proposals( finish_proposals.as_slice(), - Some((timestamp, self.finish_proposals.flip_timestamp)), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), ) .await?; } else { @@ -295,6 +311,7 @@ impl GroupStorage { // update memory if self + .cache .prepares .insert(block_id.object_id().clone(), block) .is_some() @@ -304,53 +321,60 @@ impl GroupStorage { match new_header { Some(new_header) => { - self.dec_state_id = new_header.result_state_id().clone(); + self.cache.dec_state_id = new_header.result_state_id().clone(); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); - self.prepares.remove(&new_pre_commit.0); + self.cache.prepares.remove(&new_pre_commit.0); let mut removed_blocks = HashMap::from([new_pre_commit]); - std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + std::mem::swap(&mut self.cache.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = removed_blocks.into_values().collect(); for id in remove_prepares.iter() { - removed_blocks.push(self.prepares.remove(id).unwrap()); + removed_blocks.push(self.cache.prepares.remove(id).unwrap()); } - if self.first_block.is_none() { - self.first_block = Some(new_header.clone()); + if self.cache.first_block.is_none() { + self.cache.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MS + { let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.finish_proposals.over); - self.finish_proposals.flip_timestamp = timestamp; + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; } for proposal in new_header.proposals() { - let is_new = self.finish_proposals.adding.insert(proposal.proposal); + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); assert!(is_new); } - self.header_block = Some(new_header); - return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + self.cache.header_block = Some(new_header); + return Ok(Some(( + self.cache.header_block.as_ref().unwrap(), + removed_blocks, + ))); } None => { if let Some(new_pre_commit) = new_pre_commit { assert!(remove_prepares.is_empty()); if self + .cache .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) .is_some() { assert!(false); } - self.prepares + self.cache + .prepares .remove(&new_pre_commit.0) .expect("any block in pre-commit should be from prepare"); } @@ -361,21 +385,21 @@ impl GroupStorage { } pub fn last_vote_round(&self) -> u64 { - self.last_vote_round + self.cache.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - if round <= self.last_vote_round { + if round <= self.cache.last_vote_round { return Ok(()); } // storage let mut writer = self.storage_engine.create_writer().await?; writer - .set_last_vote_round(round, self.last_vote_round) + .set_last_vote_round(round, self.cache.last_vote_round) .await?; - self.last_vote_round = round; + self.cache.last_vote_round = round; Ok(()) } @@ -533,15 +557,16 @@ impl GroupStorage { } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { - if let Some(block) = self.header_block.as_ref() { + if let Some(block) = self.cache.header_block.as_ref() { if block.block_id().object_id() == block_id { return Ok(block.clone()); } } - self.prepares + self.cache + .prepares .get(block_id) - .or(self.pre_commits.get(block_id)) + .or(self.cache.pre_commits.get(block_id)) .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) .map(|block| block.clone()) } @@ -553,20 +578,24 @@ impl GroupStorage { std::cmp::Ordering::Less => { return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Equal => self.cache.header_block.as_ref(), std::cmp::Ordering::Greater => if round == header_round + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .prepares .iter() .find(|(_, block)| block.round() == round)) } else { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .pre_commits .iter() .find(|(_, block)| block.round() == round)) @@ -615,10 +644,11 @@ impl GroupStorage { // find in storage let is_finished = self + .cache .finish_proposals .adding .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) + .or(self.cache.finish_proposals.over.get(proposal_id)) .is_some(); Ok(is_finished) } @@ -647,7 +677,7 @@ impl GroupStorage { &self, round: u64, ) -> (BuckyResult, Vec) { - if self.header_block.is_none() { + if self.cache.header_block.is_none() { return ( Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), vec![], @@ -655,7 +685,7 @@ impl GroupStorage { } let mut blocks = vec![]; - let mut block = self.header_block.clone().unwrap(); + let mut block = self.cache.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; let mut max_height = block.height(); From 80b54e380c0ea981d9b17f5159ea04af33af6610 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 15:20:55 +0800 Subject: [PATCH 250/553] update example for GroupState --- src/tests/group-example/src/main.rs | 479 +++++++++++++++++++--------- 1 file changed, 332 insertions(+), 147 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ffb45ccec..e7948f740 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -3,27 +3,28 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, }; use cyfs_stack::CyfsStack; -use Common::{ - create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, - EXAMPLE_RPATH, -}; +use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; + mod Common { - use std::sync::Arc; + use std::{fmt::format, io::ErrorKind, sync::Arc}; + use async_std::{fs, stream::StreamExt}; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, - UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -35,113 +36,109 @@ mod Common { CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, }; - use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members( + fn create_member( name_prefix: &str, - count: usize, - ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + index: usize, + port: u16, + ) -> ((People, PrivateKey), (Device, PrivateKey)) { log::info!("create members"); - let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); - let mut members = vec![]; + let name = format!("{}-{}", name_prefix, index); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); + endpoint.mut_addr().set_port(port); + endpoint.set_area(EndpointArea::Wan); + + let mut device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + device_private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); - for i in 0..count { - let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_rsa(1024).unwrap(); - let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); - let mut owner = - People::new(None, vec![], private_key.public(), None, Some(name), None).build(); - - let mut endpoint = Endpoint::default(); - endpoint.set_protocol(Protocol::Udp); - endpoint - .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); - endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_area(EndpointArea::Wan); - - let mut device = Device::new( - Some(owner.desc().object_id()), - UniqueId::create_with_random(), - vec![endpoint], - vec![], // TODO: 当前版本是否支持无SN? - vec![], - device_private_key.public(), - Area::default(), - DeviceCategory::PC, - ) - .build(); - - owner - .ood_list_mut() - .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - - let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); - let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); - let device_desc_hash = device.desc().raw_hash_value().unwrap(); - let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); - - let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = - async_std::task::block_on(async move { - let owner_desc_signature = signer - .sign( - owner_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let owner_body_signature = signer - .sign( - owner_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let desc_signature = signer - .sign( - device_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - let body_signature = signer - .sign( - device_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - ( - owner_desc_signature, - owner_body_signature, - desc_signature, - body_signature, + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), ) - }); + .await + .unwrap(); - device.signs_mut().set_desc_sign(desc_signature.clone()); - device.signs_mut().set_body_sign(body_signature); + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); - log::info!( + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", owner.name().unwrap(), owner.desc().object_id(), @@ -152,12 +149,9 @@ mod Common { owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() ); - owner.signs_mut().set_desc_sign(owner_desc_signature); - owner.signs_mut().set_body_sign(owner_body_signature); - members.push(((owner, private_key), (device, device_private_key))); - } - - members + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + ((owner, private_key), (device, device_private_key)) } fn create_group( @@ -194,16 +188,167 @@ mod Common { group } + // (succ, not-found) + fn check_read_buf(file_path: &str, result: &std::io::Result>) -> (bool, bool) { + match result.as_ref() { + Ok(b) => { + if b.len() == 0 { + (false, true) + } else { + (true, false) + } + } + Err(err) if ErrorKind::NotFound == err.kind() => (false, true), + Err(err) => { + log::warn!("read file {} failed: {:?}", file_path, err); + (false, false) + } + } + } + + async fn init_member_from_dir( + save_path: &str, + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + fs::create_dir_all(save_path) + .await + .expect(format!("create dir {} failed", save_path).as_str()); + + let min_port = 30217_u16; + + let mut members = vec![]; + + for i in 0..count { + let index = i + 1; + let people_desc_file_path = format!("{}/people-{}.desc", save_path, index); + let people_sec_file_path = format!("{}/people-{}.sec", save_path, index); + let device_desc_file_path = format!("{}/device-{}.desc", save_path, index); + let device_sec_file_path = format!("{}/device-{}.sec", save_path, index); + + let people_desc_r = fs::read(people_desc_file_path.clone()).await; + let people_sec_r = fs::read(people_sec_file_path.clone()).await; + let device_desc_r = fs::read(device_desc_file_path.clone()).await; + let device_sec_r = fs::read(device_sec_file_path.clone()).await; + + let (is_people_desc_succ, is_people_desc_not_found) = + check_read_buf(people_desc_file_path.as_str(), &people_desc_r); + let (is_people_sec_succ, is_people_sec_not_found) = + check_read_buf(people_sec_file_path.as_str(), &people_sec_r); + let (is_device_desc_succ, is_device_desc_not_found) = + check_read_buf(device_desc_file_path.as_str(), &device_desc_r); + let (is_device_sec_succ, is_device_sec_not_found) = + check_read_buf(device_sec_file_path.as_str(), &device_sec_r); + + if is_people_desc_succ + && is_people_sec_succ + && is_device_desc_succ + && is_device_sec_succ + { + // decode + let people_desc = People::raw_decode(people_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_desc_file_path).as_str()) + .0; + let people_sec = PrivateKey::raw_decode(people_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_sec_file_path).as_str()) + .0; + let device_desc = Device::raw_decode(device_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_desc_file_path).as_str()) + .0; + let device_sec = PrivateKey::raw_decode(device_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_sec_file_path).as_str()) + .0; + members.push(((people_desc, people_sec), (device_desc, device_sec))); + } else if is_people_desc_not_found + && is_people_sec_not_found + && is_device_desc_not_found + && is_device_sec_not_found + { + // create & save + let member = create_member(name_prefix, index, min_port + i as u16); + fs::write( + people_desc_file_path.as_str(), + member.0 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", people_desc_file_path).as_str()); + fs::write(people_sec_file_path.as_str(), member.0 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", people_sec_file_path).as_str()); + fs::write( + device_desc_file_path.as_str(), + member.1 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", device_desc_file_path).as_str()); + fs::write(device_sec_file_path.as_str(), member.1 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", device_sec_file_path).as_str()); + + members.push(member); + } else { + println!("read members failed!"); + std::process::exit(-1); + } + } + + members + } + + pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/admins", "admin", 4).await + } + + pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/members", "member", 9).await + } + + pub async fn init_group( + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + fs::create_dir_all("./test-group") + .await + .expect("create dir ./test-group failed"); + + let read_group_r = fs::read("./test-group/group.desc").await; + match read_group_r { + Ok(buf) => { + if buf.len() > 0 { + return Group::raw_decode(buf.as_slice()) + .expect("decode ./test-group/group.desc failed") + .0; + } + } + Err(err) => { + if ErrorKind::NotFound != err.kind() { + println!("read group failed: {:?}", err); + std::process::exit(-1); + } + } + } + + let group = create_group(admins.get(0).unwrap(), admins, members, oods); + fs::write("./test-group/group.desc", group.to_vec().unwrap()) + .await + .expect("save file ./test-group/group.desc failed"); + group + } + fn init_stack_params( people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); - let mut member_device: Vec = - EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); + let mut admin_device: Vec = admins.iter().map(|m| m.1.clone()).collect(); + let mut member_device: Vec = members.iter().map(|m| m.1.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { @@ -242,7 +387,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { + for (member, device) in admins.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -260,7 +405,7 @@ mod Common { )); } - for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { + for (member, device) in members.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -279,17 +424,17 @@ mod Common { } known_objects.list.push(NONObjectInfo::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_GROUP.to_vec().unwrap(), + group.desc().object_id(), + group.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( - EXAMPLE_GROUP.clone(), + group.clone(), )))), )); - let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( - EXAMPLE_DEC_APP.desc().object_id(), + dec_app.desc().object_id(), dec_app_vec, Some(Arc::new(AnyNamedObject::Core(typeless))), )); @@ -301,8 +446,13 @@ mod Common { people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> CyfsStack { - let params = init_stack_params(people, private_key, device); + let params = + init_stack_params(people, private_key, device, admins, members, group, dec_app); log::info!("cyfs-stack.open"); @@ -316,10 +466,6 @@ mod Common { stack } - - pub fn dummy(people: People, device: Device) { - log::info!("common::dummy"); - } } mod Client { @@ -352,22 +498,21 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + GroupProposalObject, }; use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; use cyfs_stack::CyfsStack; - use crate::Common::EXAMPLE_DEC_APP_ID; - pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { let group_mgr = cyfs_stack.group_mgr(); group_mgr .register( - EXAMPLE_DEC_APP_ID.clone(), + dec_app_id.clone(), Box::new(GroupRPathDelegateFactory { local_name }), ) .await @@ -575,13 +720,14 @@ mod GroupDecService { } } -fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { +fn create_proposal( + delta: u64, + owner: ObjectId, + group_id: ObjectId, + dec_id: ObjectId, +) -> GroupProposal { GroupProposal::create( - GroupRPath::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id().clone(), - EXAMPLE_RPATH.clone(), - ), + GroupRPath::new(group_id, dec_id, EXAMPLE_RPATH.to_string()), "add".to_string(), Some(Vec::from(delta.to_be_bytes())), None, @@ -614,23 +760,57 @@ async fn main_run() { log::info!("will open stacks"); + let admins = init_admins().await; + let members = init_members().await; + let group = init_group( + admins.iter().map(|m| &m.0 .0).collect(), + members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| &m.1 .0).collect(), + ) + .await; + let group_id = group.desc().object_id(); + let dec_app = DecApp::create( + admins.get(0).unwrap().0 .0.desc().object_id(), + EXAMPLE_APP_NAME.as_str(), + ); + let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); + let mut admin_stacks: Vec = vec![]; - for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { - // dummy(admin.clone(), device.clone()); - let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; + for ((admin, _), (device, private_key)) in admins.iter() { + let cyfs_stack = create_stack( + admin.clone(), + private_key, + device.clone(), + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + group.clone(), + dec_app.clone(), + ) + .await; admin_stacks.push(cyfs_stack); } for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); - DecService::run(&stack, admin.name().unwrap().to_string()).await; + let ((admin, _), _) = admins.get(i).unwrap(); + DecService::run( + &stack, + admin.name().unwrap().to_string(), + dec_app_id.clone(), + ) + .await; let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group.desc().object_id(), + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -647,14 +827,19 @@ async fn main_run() { let PROPOSAL_COUNT = 1000usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; - let proposal = create_proposal(i as u64, owner.desc().object_id()); + let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let proposal = create_proposal( + i as u64, + owner.desc().object_id(), + group_id, + dec_app_id.object_id().clone(), + ); let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -676,7 +861,7 @@ async fn main_run() { zone: None, zone_category: DeviceZoneCategory::CurrentDevice, }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + dec: dec_app_id.object_id().clone(), verified: None, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), @@ -700,8 +885,8 @@ async fn main_run() { let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) From 97953a4eb03599252abbfbc957c32f20eb3d5456 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 17:36:21 +0800 Subject: [PATCH 251/553] fix: path error --- .../src/statepath/group_statepath.rs | 13 ++++++++-- src/tests/group-example/src/main.rs | 26 +++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eade0f9e4..280fb6948 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -39,51 +39,60 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_GROUP_BLOB, ]), last_vote_round: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), range: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_RANGE, ]), prepares: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PREPARES, ]), pre_commits: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PRE_COMMITS, ]), finish_proposals: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, ]), flip_time: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_FLIP_TIME, ]), recycle: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_RECYCLE, ]), adding: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e7948f740..e29b1be6d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -337,13 +337,13 @@ mod Common { } fn init_stack_params( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -443,13 +443,13 @@ mod Common { } pub async fn create_stack( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> CyfsStack { let params = init_stack_params(people, private_key, device, admins, members, group, dec_app); @@ -778,9 +778,9 @@ async fn main_run() { let mut admin_stacks: Vec = vec![]; for ((admin, _), (device, private_key)) in admins.iter() { let cyfs_stack = create_stack( - admin.clone(), + admin, private_key, - device.clone(), + device, admins .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) @@ -789,8 +789,8 @@ async fn main_run() { .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) .collect(), - group.clone(), - dec_app.clone(), + &group, + &dec_app, ) .await; admin_stacks.push(cyfs_stack); @@ -898,7 +898,7 @@ async fn main_run() { }); if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(200)).await; + async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } From 1e3ceb1cb6e672687178b6b51eb913ce4e83e7e9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 18:34:11 +0800 Subject: [PATCH 252/553] fix: commit storage --- src/component/cyfs-group/src/storage/group_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 5ad19ea15..30fc08cad 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -398,6 +398,7 @@ impl GroupStorage { writer .set_last_vote_round(round, self.cache.last_vote_round) .await?; + writer.commit().await?; self.cache.last_vote_round = round; From 733797463ef4abb8506497a4d12362d81d289e38 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 253/553] fix: type of pre-commits --- .../cyfs-group/src/dec/group_manager.rs | 21 ++++++++++--------- .../engine/storage_engine_group_state.rs | 20 +++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5ecfcdba2..7ba376368 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,16 +289,17 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - let rpath = header_block.r_path(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::StateChangeNotify(header_block, qc_block), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = header_block.r_path(); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::StateChangeNotify(header_block, qc_block), + // remote, + // ) + // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index ee429a78f..c6acb7b52 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,7 +5,6 @@ use cyfs_base::{ ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -213,9 +212,11 @@ impl StorageEngineGroupStateWriter { .await?; } - self.op_env - .insert_with_path(self.state_path.pre_commits(), block_id) - .await + let is_changed = self.op_env + .insert(self.state_path.pre_commits(), block_id) + .await?; + assert!(is_changed); + Ok(()) } async fn push_commit_inner( @@ -469,7 +470,16 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.prepare_map_id.is_none(), ) .await?; - self.op_env.commit().await.map(|_| ()) + self.op_env.commit().await.map_or_else( + |err| { + if err.code() == BuckyErrorCode::AlreadyExists { + Ok(()) + } else { + Err(err) + } + }, + |_| Ok(()), + ) } } From 96666de6da53cfceaa4caf9705a01edbb5ee6bcb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:42:12 +0800 Subject: [PATCH 254/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e29b1be6d..316630f6a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: None, + isolate: Some(device.desc().object_id()), sync_service: false, shared_stack: false, }, From 5b1c58863969a5cbeaa3d0adf3f52c669e5981c7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:49:08 +0800 Subject: [PATCH 255/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 316630f6a..d69fcae2d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: Some(device.desc().object_id()), + isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: false, }, From 5b23421cff7cd42bfdc223faa129c06c1fde1565 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 21 Feb 2023 19:52:57 +0800 Subject: [PATCH 256/553] fix: the round for the first block when restart --- src/component/cyfs-core/src/coreobj.rs | 1 + .../src/group/group_quorum_certificate.rs | 144 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 2 + .../src/consensus/hotstuff/hotstuff.rs | 60 +++++++- .../cyfs-group/src/dec/group_manager.rs | 34 +++-- .../cyfs-group/src/network/non_driver.rs | 30 +++- .../cyfs-group/src/statepath/design.md | 1 + .../src/statepath/group_statepath.rs | 16 +- .../src/storage/engine/storage_engine.rs | 5 +- .../engine/storage_engine_group_state.rs | 130 ++++++++++++---- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 136 ++++++++++++----- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- src/tests/group-example/src/main.rs | 24 +-- 14 files changed, 493 insertions(+), 100 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_quorum_certificate.rs diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 724f0debb..30bf0e013 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupRPathStatus = 703, GroupAction = 704, + GroupQuorumCertificate = 705, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs new file mode 100644 index 000000000..7c3ad77fc --- /dev/null +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -0,0 +1,144 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, DescContent, EmptyBodyContent, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBuilder, NamedObjectId, RawDecode, RawEncode, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_RAW, +}; + +use crate::{CoreObjectType, HotstuffBlockQC, HotstuffTimeout}; + +#[derive(Clone)] +pub enum GroupQuorumCertificateDescContent { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), +} + +impl DescContent for GroupQuorumCertificateDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupQuorumCertificate as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupQuorumCertificateDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +pub type GroupQuorumCertificateType = + NamedObjType; +pub type GroupQuorumCertificateBuilder = + NamedObjectBuilder; + +pub type GroupQuorumCertificateId = NamedObjectId; +pub type GroupQuorumCertificate = NamedObjectBase; + +pub trait GroupQuorumCertificateObject { + fn quorum_round(&self) -> u64; +} + +impl GroupQuorumCertificateObject for GroupQuorumCertificate { + fn quorum_round(&self) -> u64 { + match self.desc().content() { + GroupQuorumCertificateDescContent::QC(qc) => qc.round, + GroupQuorumCertificateDescContent::TC(tc) => tc.round, + } + } +} + +impl RawEncode for GroupQuorumCertificateDescContent { + fn raw_measure( + &self, + purpose: &Option, + ) -> cyfs_base::BuckyResult { + let len = match self { + GroupQuorumCertificateDescContent::QC(qc) => qc.raw_measure(purpose)?, + GroupQuorumCertificateDescContent::TC(tc) => tc.raw_measure(purpose)?, + }; + + Ok(len + 1) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> cyfs_base::BuckyResult<&'a mut [u8]> { + match self { + GroupQuorumCertificateDescContent::QC(qc) => { + buf[0] = 0; + let buf = &mut buf[1..]; + qc.raw_encode(buf, purpose) + } + GroupQuorumCertificateDescContent::TC(tc) => { + buf[0] = 1; + let buf = &mut buf[1..]; + tc.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for GroupQuorumCertificateDescContent { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let obj_type = buf[0]; + let buf = &buf[1..]; + match obj_type { + 0 => { + let (qc, remain) = HotstuffBlockQC::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::QC(qc), remain)) + } + 1 => { + let (qc, remain) = HotstuffTimeout::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::TC(qc), remain)) + } + _ => Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown qc")), + } + } +} + +impl From for GroupQuorumCertificate { + fn from(qc: HotstuffBlockQC) -> Self { + let desc = GroupQuorumCertificateDescContent::QC(qc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl From for GroupQuorumCertificate { + fn from(tc: HotstuffTimeout) -> Self { + let desc = GroupQuorumCertificateDescContent::TC(tc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::QC(qc) => Ok(qc), + GroupQuorumCertificateDescContent::TC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is tc, expect qc")) + } + } + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::TC(tc) => Ok(tc), + GroupQuorumCertificateDescContent::QC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is qc, expect tc")) + } + } + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4c315c090..c153ab1ba 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,6 +1,7 @@ mod group_consensus_block; mod group_proposal; mod group_proposal_decide_param; +mod group_quorum_certificate; mod group_rpath; mod group_rpath_status; mod group_update_group_proposal_param; @@ -8,6 +9,7 @@ mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; pub use group_proposal_decide_param::*; +pub use group_quorum_certificate::*; pub use group_rpath::*; pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e89498b83..7868a7f90 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,7 +9,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; @@ -238,11 +238,36 @@ impl HotstuffRunner { rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); + let last_qc = store.last_qc(); + let (tc, qc) = last_qc + .as_ref() + .map_or((None, None), |qc| { + match qc.desc().content() { + cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), + cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), + } + }); - let round = store - .last_vote_round() - .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let last_vote_round = store + .last_vote_round(); + let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); + let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); + + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" + , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + + let max_round_qc_round = max_round_block + .as_ref() + .map_or(0, |block| + block.qc().as_ref().map_or(0, |qc| qc.round) + ); + let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); + let high_qc = if max_round_qc_round >= last_qc_round { + max_round_block.map_or(None, |b| b.qc().clone()) + } else { + qc + }; let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); @@ -277,7 +302,7 @@ impl HotstuffRunner { rpath, proposal_consumer, rx_proposal_waiter: None, - tc: None, + tc, state_pusher, tx_block_gen, rx_block_gen, @@ -627,6 +652,16 @@ impl HotstuffRunner { * 验证过的块执行这个函数 */ + if let Err(err) = self.non_driver.put_block(block).await { + if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + log::warn!( + "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", + self, block.block_id(), block.height(), block.round() + ); + return Err(err); + } + } + log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", self, block.block_id(), block.height(), block.round() @@ -1072,6 +1107,10 @@ impl HotstuffRunner { let qc_round = qc.round; let qc_prev_block_id = qc.prev_block_id; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); + + self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.process_qc(&Some(qc)).await; let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { @@ -1211,10 +1250,14 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", @@ -1324,6 +1367,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1814,6 +1861,7 @@ impl HotstuffRunner { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id + && max_round_block.round() == self.round && latest_group.is_ok() && last_group.is_ok() && last_group diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7ba376368..70fb10ba6 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -302,22 +302,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.r_path(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); @@ -397,6 +398,7 @@ impl GroupManager { return Err(e); } if let BuckyErrorCode::NotFound = e.code() { + log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); None } else { return Err(e); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4212a0355..979451b79 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,7 +7,9 @@ use cyfs_base::{ TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, +}; use cyfs_lib::NONObjectInfo; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -106,6 +108,32 @@ impl NONDriverHelper { Ok(()) } + pub async fn get_qc( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupQuorumCertificate::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn put_qc(&self, qc: &GroupQuorumCertificate) -> BuckyResult<()> { + let buf = qc.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let qc = NONObjectInfo { + object_id: qc.desc().object_id(), + object_raw: qc.to_vec()?, + object: Some(block_any), + }; + self.put_object(qc).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 70a61e428..cb964e066 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -23,6 +23,7 @@ | | |--${user-id} | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 280fb6948..0e6a887b0 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -5,6 +5,7 @@ pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -23,10 +24,12 @@ lazy_static::lazy_static! { pub struct GroupStatePath { rpath: String, + root: String, dec_state: String, link: String, group_blob: String, last_vote_round: String, + last_qc: String, range: String, prepares: String, pre_commits: String, @@ -39,6 +42,7 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { + root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ @@ -53,6 +57,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), + last_qc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_QC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -107,7 +117,7 @@ impl GroupStatePath { } pub fn root(&self) -> &str { - self.rpath.as_str() + self.root.as_str() } pub fn dec_state(&self) -> &str { @@ -126,6 +136,10 @@ impl GroupStatePath { self.last_vote_round.as_str() } + pub fn last_qc(&self) -> &str { + self.last_qc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index 735277a3a..aebf6fb96 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,6 +12,7 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub last_qc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -33,6 +34,7 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, + last_qc: None, } } } @@ -58,6 +60,7 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index c6acb7b52..2b61dbc47 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, }; use crate::{ @@ -27,26 +27,35 @@ impl StorageEngineGroupState { non_driver: &NONDriverHelper, state_path: &GroupStatePath, ) -> BuckyResult { - let op_env = state_mgr.create_op_env(ACCESS)?; - - let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; - - let last_vote_round = op_env - .get_by_path(state_path.last_vote_round()) - .await? - .map(|id| parse_u64_obj(&id)); + let op_env = state_mgr.create_op_env(ACCESS).map_err(|err| { + log::warn!("create_op_env failed {:?}", err); + err + })?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await; + let dec_state_id = map_not_found_option_to_option(dec_state_id)?; + + let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; + let last_vote_round = + map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; + let last_qc = map_not_found_option_to_option(last_qc)?; + let last_qc = match last_qc.as_ref() { + Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + None => None, + }; let mut first_header_block_ids: Vec = vec![]; - let commit_range = op_env - .get_by_path(state_path.range()) - .await? - .map(|id| parse_range_obj(&id)); + let commit_range = op_env.get_by_path(state_path.range()).await; + let commit_range = + map_not_found_option_to_option(commit_range)?.map(|id| parse_range_obj(&id)); let commit_block = match commit_range { Some((first_height, header_height)) => { let first_block_id = op_env .get_by_path(state_path.commit_height(first_height).as_str()) - .await? - .expect("first block is lost"); + .await; + let first_block_id = + map_not_found_option_to_option(first_block_id)?.expect("first block is lost"); first_header_block_ids.push(first_block_id); if header_height == first_height { @@ -54,7 +63,8 @@ impl StorageEngineGroupState { } else { let header_block_id = op_env .get_by_path(state_path.commit_height(header_height).as_str()) - .await? + .await; + let header_block_id = map_not_found_option_to_option(header_block_id)? .expect("first block is lost"); first_header_block_ids.push(header_block_id); Some((first_block_id, header_block_id)) @@ -64,13 +74,27 @@ impl StorageEngineGroupState { }; let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + if prepare_block_ids.len() == 0 && commit_range.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "not found in storage", + )); + } + let pre_commit_block_ids = load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; - let flip_timestamp = op_env - .get_by_path(state_path.flip_time()) - .await? - .map_or(0, |id| parse_u64_obj(&id)); + let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; + let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { + let n = parse_u64_obj(&id); + // log::debug!( + // "load flip timestamp {}/{} -> {}", + // id, + // id.to_hex().unwrap(), + // n + // ); + n + }); let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; @@ -82,15 +106,18 @@ impl StorageEngineGroupState { ] .concat(); - let load_blocks = futures::future::join_all( - load_block_ids - .iter() - .map(|id| non_driver.get_block(id, None)), - ) + let load_blocks = futures::future::join_all(load_block_ids.iter().map(|id| async { + let id = id.clone(); + non_driver.get_block(&id, None).await.map_err(|err| { + log::warn!("get block {} failed {:?}", id, err); + err + }) + })) .await; let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.last_qc = last_qc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -212,7 +239,8 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self.op_env + let is_changed = self + .op_env .insert(self.state_path.pre_commits(), block_id) .await?; assert!(is_changed); @@ -326,6 +354,15 @@ impl StorageEngineGroupStateWriter { let timestamp_obj = make_u64_obj(timestamp); if prev_timestamp != 0 { let prev_timestamp_obj = make_u64_obj(prev_timestamp); + // log::debug!( + // "will update flip-time from {} -> {}/{} to {} -> {}/{}", + // prev_timestamp, + // prev_timestamp_obj, + // prev_timestamp_obj.to_hex().unwrap(), + // timestamp, + // timestamp_obj, + // timestamp_obj.to_hex().unwrap(), + // ); let prev_value = self .op_env .set_with_path( @@ -337,6 +374,7 @@ impl StorageEngineGroupStateWriter { .await?; assert_eq!(prev_value.unwrap(), prev_timestamp_obj); } else { + // log::debug!("will update flip-time from None to {}", timestamp); self.op_env .insert_with_key( self.state_path.finish_proposals(), @@ -395,6 +433,13 @@ impl StorageEngineGroupStateWriter { Ok(()) } } + + async fn save_last_qc_inner(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_qc(), qc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -458,6 +503,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_qc_inner(qc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; @@ -522,6 +573,7 @@ async fn load_object_ids_with_path( let content = match op_env.list(full_path).await { Ok(content) => content, Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); if err.code() == BuckyErrorCode::NotFound { return Ok(vec![]); } else { @@ -546,3 +598,29 @@ async fn load_object_ids_with_path( Ok(object_ids) } + +fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { + match r { + Ok(t) => Ok(Some(t)), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} + +fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult> { + match r { + Ok(t) => Ok(t), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b944d3735..79491b186 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -192,6 +192,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 30fc08cad..3f9fc9910 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -8,7 +8,10 @@ use cyfs_base::{ ObjectDesc, ObjectId, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupQuorumCertificateObject, HotstuffTimeout, +}; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ @@ -20,7 +23,7 @@ use super::{ StorageEngine, }; -const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; +const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() as u64; pub enum BlockLinkState { Expired, @@ -96,16 +99,32 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver.get_group(group_id, None, None).await?; + let group = non_driver + .get_group(group_id, None, None) + .await + .map_err(|err| { + log::warn!("get group {} from noc failed {:?}", group_id, err); + err + })?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) - .await? + .await + .map_err(|err| { + log::warn!("load root state for group {} failed {:?}", group_id, err); + err + })? .expect("create group state failed."); - let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state + .get_dec_root_manager(dec_id, true) + .await + .map_err(|err| { + log::warn!("get root state manager for dec {} failed {:?}", dec_id, err); + err + })?; let state_path = GroupStatePath::new(rpath.to_string()); let cache = @@ -120,7 +139,7 @@ impl GroupStorage { group_chunk_id: group_chunk_id.object_id(), storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, - cache: cache, + cache, }) } @@ -286,24 +305,33 @@ impl GroupStorage { writer.remove_prepares(remove_prepares.as_slice()).await?; - let finish_proposals: Vec = new_header - .proposals() - .iter() - .map(|p| p.proposal.clone()) - .collect(); - - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { - writer - .push_proposals( - finish_proposals.as_slice(), - Some((timestamp, self.cache.finish_proposals.flip_timestamp)), - ) - .await?; - } else { - writer - .push_proposals(finish_proposals.as_slice(), None) - .await?; + if new_header.proposals().len() > 0 { + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + + let timestamp = new_header.named_object().desc().create_time(); + // log::debug!( + // "push proposals storage flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + writer + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), + ) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } } @@ -340,19 +368,28 @@ impl GroupStorage { self.cache.first_block = Some(new_header.clone()); } - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp - > PROPOSAL_MAX_TIMEOUT_AS_MS - { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); - self.cache.finish_proposals.flip_timestamp = timestamp; - } + if new_header.proposals().len() > 0 { + let timestamp = new_header.named_object().desc().create_time(); + + // log::debug!( + // "push proposals flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; + } - for proposal in new_header.proposals() { - let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); - assert!(is_new); + for proposal in new_header.proposals() { + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } } self.cache.header_block = Some(new_header); @@ -405,6 +442,33 @@ impl GroupStorage { Ok(()) } + pub fn last_qc(&self) -> &Option { + &self.cache.last_qc + } + + pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { + let quorum_round = qc.quorum_round(); + if quorum_round < self.cache.last_vote_round + || quorum_round + <= self + .cache + .last_qc + .as_ref() + .map_or(0, |qc| qc.quorum_round()) + { + return Ok(()); + } + + self.non_driver.put_qc(&qc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_qc(&qc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_qc = Some(qc); + Ok(()) + } + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { log::debug!( "[group storage] {} block_linked {} step1", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9414cda7c..fcb0dd6da 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, @@ -55,6 +55,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { } async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let access = AccessString::full(); + log::debug!("put object {} with access {}", obj.object_id, access); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { @@ -76,7 +78,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { flags: 0, }, object: obj, - access: None, // TODO access + access: Some(AccessString::full()), // TODO access }) .await .map(|_| ()) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d69fcae2d..b5b6f4ce4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,7 +1,8 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ - AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; @@ -23,8 +24,8 @@ mod Common { AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, - TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, - SIGNATURE_SOURCE_REFINDEX_SELF, + TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -210,13 +211,12 @@ mod Common { save_path: &str, name_prefix: &str, count: usize, + min_port: u16, ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { fs::create_dir_all(save_path) .await .expect(format!("create dir {} failed", save_path).as_str()); - let min_port = 30217_u16; - let mut members = vec![]; for i in 0..count { @@ -296,11 +296,13 @@ mod Common { } pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/admins", "admin", 4).await + let min_port = 30217_u16; + init_member_from_dir("./test-group/admins", "admin", 4, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/members", "member", 9).await + let min_port = 31217_u16; + init_member_from_dir("./test-group/members", "member", 9, min_port).await } pub async fn init_group( @@ -369,7 +371,7 @@ mod Common { }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { - bdt_listeners: vec![], + bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], tcp_listeners: vec![], ws_listener: None, }, @@ -868,7 +870,7 @@ async fn main_run() { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: Some(AccessString::full().value()), }; noc.put_object(&req).await; proposals.push(proposal); @@ -878,8 +880,8 @@ async fn main_run() { log::info!("proposals prepared."); - for i in 0..(PROPOSAL_COUNT - 1) { - let proposal = proposals.get(i).unwrap().clone(); + for i in 1..PROPOSAL_COUNT { + let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let control = stack From ee7389ea5b790c68159c7f77d1fbe6d309308732 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 16:04:16 +0800 Subject: [PATCH 257/553] fix: first block with tc --- .../src/consensus/hotstuff/hotstuff.rs | 75 ++++++++++--------- .../src/statepath/group_statepath.rs | 12 +++ .../src/storage/engine/storage_engine.rs | 9 ++- .../engine/storage_engine_group_state.rs | 35 ++++++++- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 41 +++++++--- src/tests/group-example/src/main.rs | 2 + 7 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7868a7f90..a2a5e8f70 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -239,36 +239,30 @@ impl HotstuffRunner { ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); - let (tc, qc) = last_qc - .as_ref() - .map_or((None, None), |qc| { - match qc.desc().content() { - cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), - cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), - } - }); + let last_tc = store.last_tc(); let last_vote_round = store .last_vote_round(); - let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); - let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); + let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); + let quorum_round = block_quorum_round.max(timeout_quorum_round); + let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" - , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" + , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); - let max_round_qc_round = max_round_block - .as_ref() - .map_or(0, |block| - block.qc().as_ref().map_or(0, |qc| qc.round) - ); - let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); - let high_qc = if max_round_qc_round >= last_qc_round { + let high_qc = if max_round_qc_round >= block_quorum_round { max_round_block.map_or(None, |b| b.qc().clone()) } else { - qc + last_qc.clone() }; + let tc = last_tc.clone(); + let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; @@ -954,18 +948,22 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && qc_round - >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; if !is_valid_round { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {:?}", self, block.block_id(), block.round(), qc_round, - block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + block.tc().as_ref().map_or((0, 0), |tc| { + let qc_round = tc.votes.iter().map(|v| v.high_qc_round).max().unwrap(); + (tc.round, qc_round) + })); return None; } @@ -1109,7 +1107,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); - self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.store.save_qc(&qc).await?; self.process_qc(&Some(qc)).await; @@ -1125,7 +1123,7 @@ impl HotstuffRunner { })?; if self.local_device_id == new_leader { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } Ok(()) } @@ -1251,12 +1249,12 @@ impl HotstuffRunner { max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( @@ -1367,9 +1365,9 @@ impl HotstuffRunner { err })?; - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1535,7 +1533,7 @@ impl HotstuffRunner { self.remove_pending_proposals(remove_proposals).await; if self - .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .try_wait_proposals(executed_proposals.len(), &prev_block) .await { log::debug!( @@ -1739,12 +1737,12 @@ impl HotstuffRunner { async fn try_wait_proposals( &mut self, - executed_proposals: &[(GroupProposal, ExecuteResult)], + proposal_count: usize, pre_block: &Option, ) -> bool { // empty block, qc only, it's unuseful when no block to qc let mut will_wait_proposals = false; - if executed_proposals.len() == 0 { + if proposal_count == 0 { match pre_block.as_ref() { None => { log::warn!( @@ -1814,14 +1812,17 @@ impl HotstuffRunner { assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); - let tc = self.tc.as_ref().map_or(None, |tc| { + self.generate_block(self.with_tc()).await + } + + fn with_tc(&self) -> Option { + self.tc.as_ref().map_or(None, |tc| { if tc.round + 1 == self.round { Some(tc.clone()) } else { None } - }); - self.generate_block(tc).await + }) } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { @@ -1876,7 +1877,7 @@ impl HotstuffRunner { ); } _ => { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } } } diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0e6a887b0..72f48e601 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -6,6 +6,7 @@ pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; +pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -30,6 +31,7 @@ pub struct GroupStatePath { group_blob: String, last_vote_round: String, last_qc: String, + last_tc: String, range: String, prepares: String, pre_commits: String, @@ -63,6 +65,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_QC, ]), + last_tc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_TC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -140,6 +148,10 @@ impl GroupStatePath { self.last_qc.as_str() } + pub fn last_tc(&self) -> &str { + self.last_tc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index aebf6fb96..c4803d6ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,7 +12,8 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 - pub last_qc: Option, + pub last_qc: Option, + pub last_tc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -25,6 +26,8 @@ impl StorageCacheInfo { Self { dec_state_id: init_state_id, last_vote_round: 0, + last_qc: None, + last_tc: None, header_block: None, first_block: None, prepares: HashMap::new(), @@ -34,7 +37,6 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, - last_qc: None, } } } @@ -61,6 +63,7 @@ pub trait StorageWriter: Send + Sync { async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 2b61dbc47..b3a01fd60 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -38,10 +39,26 @@ impl StorageEngineGroupState { let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; let last_vote_round = map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; let last_qc = map_not_found_option_to_option(last_qc)?; let last_qc = match last_qc.as_ref() { - Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + Some(qc_id) => non_driver + .get_qc(qc_id, None) + .await? + .try_into() + .map_or(None, |qc| Some(qc)), + None => None, + }; + + let last_tc = op_env.get_by_path(state_path.last_tc()).await; + let last_tc = map_not_found_option_to_option(last_tc)?; + let last_tc = match last_tc.as_ref() { + Some(tc_id) => non_driver + .get_qc(tc_id, None) + .await? + .try_into() + .map_or(None, |tc| Some(tc)), None => None, }; @@ -118,6 +135,7 @@ impl StorageEngineGroupState { let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); cache.last_qc = last_qc; + cache.last_tc = last_tc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -440,6 +458,13 @@ impl StorageEngineGroupStateWriter { .await .map(|_| ()) } + + async fn save_last_tc_inner(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_tc(), tc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -509,6 +534,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_tc_inner(tc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 79491b186..ebeedd7ca 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -196,6 +196,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3f9fc9910..ee2618cde 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -10,7 +10,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffTimeout, + GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; @@ -442,30 +442,49 @@ impl GroupStorage { Ok(()) } - pub fn last_qc(&self) -> &Option { + pub fn last_qc(&self) -> &Option { &self.cache.last_qc } - pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { - let quorum_round = qc.quorum_round(); + pub async fn save_qc(&mut self, qc: &HotstuffBlockQC) -> BuckyResult<()> { + let quorum_round = qc.round; if quorum_round < self.cache.last_vote_round - || quorum_round - <= self - .cache - .last_qc - .as_ref() - .map_or(0, |qc| qc.quorum_round()) + || quorum_round <= self.cache.last_qc.as_ref().map_or(0, |qc| qc.round) { return Ok(()); } + let qc = GroupQuorumCertificate::from(qc.clone()); self.non_driver.put_qc(&qc).await?; let mut writer = self.storage_engine.create_writer().await?; writer.save_last_qc(&qc.desc().object_id()).await?; writer.commit().await?; - self.cache.last_qc = Some(qc); + self.cache.last_qc = Some(qc.try_into().unwrap()); + Ok(()) + } + + pub fn last_tc(&self) -> &Option { + &self.cache.last_tc + } + + pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + let quorum_round = tc.round; + if quorum_round < self.cache.last_vote_round + || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) + { + return Ok(()); + } + + let tc = GroupQuorumCertificate::from(tc.clone()); + self.non_driver.put_qc(&tc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_tc(&tc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_tc = Some(tc.try_into().unwrap()); Ok(()) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b5b6f4ce4..2ba99716e 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -798,6 +798,8 @@ async fn main_run() { admin_stacks.push(cyfs_stack); } + async_std::task::sleep(Duration::from_millis(10000)).await; + for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); From 30f9f6a77561ef9323c52af9de9fc2761b848a9d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:23:03 +0800 Subject: [PATCH 258/553] prepare for verify --- .../cyfs-core/protos/core_objects.proto | 14 -- src/component/cyfs-core/src/coreobj.rs | 1 - .../src/group/group_consensus_block.rs | 23 +++ .../cyfs-core/src/group/group_rpath_status.rs | 17 --- src/component/cyfs-core/src/group/mod.rs | 2 - .../protos/group_bft_protocol.proto | 6 + src/component/cyfs-group/src/crypto/crypto.rs | 14 -- src/component/cyfs-group/src/crypto/mod.rs | 3 - .../cyfs-group/src/dec/group_manager.rs | 35 +++-- .../src/dec_state/dec_state_requestor.rs | 32 ++-- src/component/cyfs-group/src/helper/verify.rs | 6 +- src/component/cyfs-group/src/lib.rs | 2 - .../src/objects/group_rpath_status.rs | 89 +++++++++++ src/component/cyfs-group/src/objects/mod.rs | 2 + .../cyfs-group/src/objects/protocol.rs | 140 +++++++++++++----- .../cyfs-group/src/storage/dec_storage.rs | 6 +- 16 files changed, 259 insertions(+), 133 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs delete mode 100644 src/component/cyfs-group/src/crypto/crypto.rs delete mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/objects/group_rpath_status.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 164c6bcd6..487ece4bd 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -431,20 +431,6 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } -message GroupRPathSubStatus { - string sub_path = 1; - repeated bytes state_id = 2; // for set -} - -message GroupRPathStatusDescContent { - bytes block_id = 1; - optional bytes sub_status_hash = 2; -} - -message GroupRPathStatusBodyContent { - repeated GroupRPathSubStatus sub_status = 1; -} - message GroupActionDescContent { // target GroupRPath r_path = 1; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 30bf0e013..3d53a082f 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -64,7 +64,6 @@ pub enum CoreObjectType { GroupProposal = 700, GroupUpdateGroup = 701, GroupConsensusBlock = 702, - GroupRPathStatus = 703, GroupAction = 704, GroupQuorumCertificate = 705, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 5d6d114c0..35c418552 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -38,6 +38,28 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } +impl GroupConsensusBlockDescContent { + pub fn rpath(&self) -> &GroupRPath { + &self.r_path + } + + pub fn result_state_id(&self) -> &Option { + &self.result_state_id + } + + pub fn height(&self) -> u64 { + self.height + } + + pub fn round(&self) -> u64 { + self.round + } + + pub fn group_chunk_id(&self) -> &ObjectId { + &self.group_chunk_id + } +} + #[derive(Clone, ProtobufTransformType)] #[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] pub struct HotstuffBlockQCSign { @@ -175,6 +197,7 @@ impl BodyContent for GroupConsensusBlockBodyContent { } } +pub type GroupConsensusBlockDesc = NamedObjectDesc; type GroupConsensusBlockType = NamedObjType; type GroupConsensusBlockBuilder = diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs deleted file mode 100644 index c55c41243..000000000 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::atomic::{AtomicU8, Ordering}; - -use crate::CoreObjectType; -use cyfs_base::*; -use serde::Serialize; -use sha2::Digest; - -// TODO: 后面再封装这个对象 -#[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus { - pub value_object_id: ObjectId, - pub block_id: ObjectId, - pub qc_block_id: ObjectId, -} - -#[cfg(test)] -mod test {} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index c153ab1ba..b2885d637 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -3,7 +3,6 @@ mod group_proposal; mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_rpath_status; mod group_update_group_proposal_param; pub use group_consensus_block::*; @@ -11,5 +10,4 @@ pub use group_proposal::*; pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 6ed8c3afe..621186522 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -15,3 +15,9 @@ message HotstuffTimeoutVote { bytes voter = 3; bytes signature = 4; } + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs deleted file mode 100644 index 9949f7a67..000000000 --- a/src/component/cyfs-group/src/crypto/crypto.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cyfs_base::{HashValue, ObjectId, Signature}; - -#[derive(Clone)] -pub struct Crypto {} - -impl Crypto { - pub fn sign(&self, hash: &HashValue) -> Signature { - unimplemented!() - } - - pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs deleted file mode 100644 index 066e79b6b..000000000 --- a/src/component/cyfs-group/src/crypto/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod crypto; - -pub use crypto::*; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 70fb10ba6..2f2229890 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,7 +289,7 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - // TODO: 暂时不实现 + // TODO: unimplemented // let rpath = header_block.r_path(); // let client = self // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) @@ -302,23 +302,22 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - // TODO: 暂时不实现 - // let rpath = result.as_ref().map_or_else( - // |(_, target)| target.check_rpath(), - // |(_, block, _)| block.r_path(), - // ); - // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - // .await?; - // client - // .on_message( - // HotstuffMessage::ProposalResult( - // proposal_id, - // result.map_err(|(err, _)| err), - // ), - // remote, - // ) - // .await; + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) + .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e30c0a5a7..369b3db6e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,10 +3,13 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; -use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; +use crate::{ + helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + CHANNEL_CAPACITY, +}; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -143,7 +146,7 @@ impl DecStateRequestorRunner { let result = self .verify_verifiable_state(sub_path.as_str(), &result, &remote) .await - .map(|_| result.value_object_id); + .map(|_| unimplemented!()); // TODO: 搜索目标值 self.query_state_notifier.reply(&sub_path, result).await } @@ -157,25 +160,22 @@ impl DecStateRequestorRunner { result: &GroupRPathStatus, remote: &ObjectId, ) -> BuckyResult<()> { - let header_block = self - .non_driver - .get_block(&result.block_id, Some(remote)) - .await?; - let qc_block = self - .non_driver - .get_block(&result.qc_block_id, Some(remote)) - .await?; + // let header_block = self + // .non_driver + // .get_block(&result.block_id, Some(remote)) + // .await?; + // let qc_block = self + // .non_driver + // .get_block(&result.qc_block_id, Some(remote)) + // .await?; - let qc = match qc_block.qc() { - Some(qc) => qc, - None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), - }; + let qc = &result.certificate; let group = self .non_driver .get_group( self.rpath.group_id(), - Some(header_block.group_chunk_id()), + Some(result.block_desc.content().group_chunk_id()), Some(&remote), ) .await?; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 2a384d1cf..b8ab12b69 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; + +use crate::GroupRPathStatus; pub async fn verify_block( block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index fefe3f808..ba8e83569 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -1,6 +1,5 @@ mod consensus; mod constant; -mod crypto; mod dec; mod dec_state; mod helper; @@ -12,7 +11,6 @@ mod utils; pub use consensus::*; pub use constant::*; -pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs new file mode 100644 index 000000000..f266d3dbd --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use cyfs_base::*; +use cyfs_core::{GroupConsensusBlockDesc, HotstuffBlockQC}; +use cyfs_lib::NONObjectInfo; +use prost::Message; + +#[derive(Clone)] +pub struct GroupRPathStatus { + pub block_desc: GroupConsensusBlockDesc, + pub certificate: HotstuffBlockQC, + pub status_map: HashMap, +} + +impl RawEncode for GroupRPathStatus { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + Ok(proto.encoded_len()) + } + + fn raw_encode<'a>( + &self, + mut buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + proto.encode_raw(&mut buf); + + Ok(buf) + } +} + +impl<'de> RawDecode<'de> for GroupRPathStatus { + fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + let (block_desc, remain) = + GroupConsensusBlockDesc::raw_decode(proto.block_desc.as_slice())?; + assert_eq!(remain.len(), 0); + let (certificate, remain) = HotstuffBlockQC::raw_decode(proto.certificate.as_slice())?; + assert_eq!(remain.len(), 0); + let mut status_map = HashMap::new(); + for obj_buf in proto.status_list.iter() { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status_map.insert(status.object_id, status); + } + + Ok(( + Self { + block_desc, + certificate, + status_map, + }, + buf, + )) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs index d6de55d79..5d1a8b13f 100644 --- a/src/component/cyfs-group/src/objects/mod.rs +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -1,7 +1,9 @@ mod group_decide_proposal; +mod group_rpath_status; mod group_update_proposal; mod protocol; pub use group_decide_proposal::*; +pub use group_rpath_status::*; pub use group_update_proposal::*; pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 3e5f513df..6c9f89e96 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,16 +2,15 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } -use std::result; - use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; +use crate::GroupRPathStatus; + #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), @@ -163,20 +162,16 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::ProposalResult({}, {:?})", proposal_id, - result.as_ref().map_or_else( - |err| { Err(err) }, - |(obj, block, qc)| { - let ok = format!( - "({:?}, {}/{}, {}/{})", - obj.as_ref().map(|o| o.object_id), - block.block_id(), - block.round(), - qc.block_id(), - qc.round() - ); - Ok(ok) - } - ) + result.as_ref().map(|(obj, block, qc)| { + format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + }) ) } Self::QueryState(sub_path) => { @@ -187,7 +182,17 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map(|status| { + let desc = status.block_desc.content(); + format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ) + }) ) } } @@ -196,6 +201,7 @@ impl std::fmt::Debug for HotstuffMessage { const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; +const PACKAGE_FLAG_QUERY_STATE_RESULT_OK: u8 = 0x80u8; #[derive(Clone)] pub(crate) enum HotstuffPackage { @@ -220,7 +226,10 @@ pub(crate) enum HotstuffPackage { >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, String, BuckyResult), + VerifiableState( + String, + Result, + ), } impl std::fmt::Debug for HotstuffPackage { @@ -296,12 +305,26 @@ impl std::fmt::Debug for HotstuffPackage { Self::QueryState(_, sub_path) => { write!(f, "HotstuffPackage::QueryState({})", sub_path) } - Self::VerifiableState(_, sub_path, result) => { + Self::VerifiableState(sub_path, result) => { write!( f, "HotstuffPackage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |status| { + let desc = status.block_desc.content(); + let ok = format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ); + Ok(ok) + } + ) ) } } @@ -323,7 +346,10 @@ impl HotstuffPackage { |(_, block, _)| block.r_path(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), - HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |status| status.block_desc.content().rpath(), + ), } } } @@ -399,10 +425,14 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::QueryState(addr, sub_path) => { addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { - 2 + addr.raw_measure(purpose)? - + sub_path.raw_measure(purpose)? - + result.raw_measure(purpose)? + HotstuffPackage::VerifiableState(sub_path, result) => { + sub_path.raw_measure(purpose)? + + match result { + Ok(status) => status.raw_measure(purpose)?, + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } } }; @@ -459,7 +489,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; if result.is_ok() { - buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + buf[0] |= PACKAGE_FLAG_PROPOSAL_RESULT_OK; } let buf = &mut buf[1..]; @@ -482,12 +512,20 @@ impl RawEncode for HotstuffPackage { let buf = sub_path.raw_encode(buf, purpose)?; addr.raw_encode(buf, purpose) } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { + HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; + if result.is_ok() { + buf[0] |= PACKAGE_FLAG_QUERY_STATE_RESULT_OK; + } let buf = &mut buf[1..]; - let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = sub_path.raw_encode(buf, purpose)?; - result.raw_encode(buf, purpose) + match result { + Ok(status) => status.raw_encode(buf, purpose), + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } } } } @@ -502,24 +540,28 @@ impl<'de> RawDecode<'de> for HotstuffPackage { 0 => { let buf = &buf[1..]; let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { @@ -527,17 +569,20 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } 7 => { @@ -549,6 +594,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), buf, @@ -557,6 +603,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { false => { let (err, buf) = BuckyError::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } } @@ -565,17 +612,29 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let buf = &buf[1..]; let (sub_path, buf) = String::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } 9 => { + let is_ok = (buf[0] & PACKAGE_FLAG_QUERY_STATE_RESULT_OK) != 0; let buf = &buf[1..]; - let (addr, buf) = decode_with_length(buf, 3)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (result, buf) = BuckyResult::::raw_decode(buf)?; - Ok(( - HotstuffPackage::VerifiableState(addr, sub_path, result), - buf, - )) + match is_ok { + true => { + let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok(( + HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), + buf, + )) + } + } } _ => unreachable!("unknown protocol"), } @@ -613,9 +672,10 @@ impl HotstuffPackage { HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) } - HotstuffMessage::VerifiableState(sub_path, result) => { - HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) - } + HotstuffMessage::VerifiableState(sub_path, result) => HotstuffPackage::VerifiableState( + sub_path, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ), } } } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 12e3629d8..cce00e736 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use async_std::sync::RwLock; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; +use cyfs_core::GroupConsensusBlock; + +use crate::GroupRPathStatus; #[derive(Clone)] pub struct DecStorageCache { @@ -11,8 +13,6 @@ pub struct DecStorageCache { pub qc_block: GroupConsensusBlock, } -// TODO: storage - #[derive(Clone)] pub struct DecStorage { cache: Arc>>, From 96881e8e96131a44a65bf3240150956428e4dc91 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:28:28 +0800 Subject: [PATCH 259/553] compile --- .../cyfs-group/src/dec/group_manager.rs | 12 +++++++++--- .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 14 +++++++++----- src/component/cyfs-group/src/helper/verify.rs | 16 +++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 2f2229890..0d863e17b 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -328,13 +328,19 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - HotstuffPackage::VerifiableState(target, sub_path, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::VerifiableState(sub_path, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |status| status.block_desc.content().rpath(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .on_message( + HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), + remote, + ) .await; } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 369b3db6e..b5c3b107e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -180,7 +180,7 @@ impl DecStateRequestorRunner { ) .await?; - if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { Err(BuckyError::new( BuckyErrorCode::InvalidSignature, "verify failed", diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f33ec5fa..73afb0ad0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -315,10 +315,7 @@ impl DecStateSynchronizerRunner { remote: ObjectId, ) -> BuckyResult<()> { if qc_block.qc().is_none() { - log::warn!( - "the qc is none for qc-block({})", - qc_block.block_id() - ); + log::warn!("the qc is none for qc-block({})", qc_block.block_id()); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } @@ -365,7 +362,14 @@ impl DecStateSynchronizerRunner { } }; - if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + if header_block.check() + && verify_block( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + &group.1, + ) + .await? + { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index b8ab12b69..759bf2c4a 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,15 +1,17 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, +}; use crate::GroupRPathStatus; pub async fn verify_block( - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.block_id().object_id(); - if qc.round != block.round() || &qc.block_id != block_id { + let block_id = block_desc.object_id(); + if qc.round != block_desc.content().round() || qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, @@ -18,17 +20,13 @@ pub async fn verify_block( return Ok(false); } - if !block.check() { - return Ok(false); - } - unimplemented!() } pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { From 415623b9953276e11ae56c7a06a35df06383ce8f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 23 Feb 2023 21:02:07 +0800 Subject: [PATCH 260/553] Verify the value on sub-path from anyone OOD in group --- .../src/consensus/hotstuff/hotstuff.rs | 28 ++++- .../src/consensus/vote/committee.rs | 66 ++++++++++- .../cyfs-group/src/dec/group_manager.rs | 54 ++++++--- .../cyfs-group/src/dec/rpath_client.rs | 34 ++++-- .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../src/dec_state/dec_state_requestor.rs | 73 ++++++------ .../src/dec_state/dec_state_synchronizer.rs | 80 ++++++-------- src/component/cyfs-group/src/helper/verify.rs | 18 --- .../src/objects/group_rpath_status.rs | 4 +- .../cyfs-group/src/storage/dec_storage.rs | 76 ++++++++++++- .../src/storage/engine/storage_engine.rs | 4 +- .../engine/storage_engine_group_state.rs | 23 +++- .../cyfs-group/src/storage/group_storage.rs | 104 +++++++++++++++++- src/component/cyfs-group/src/utils.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 15 files changed, 410 insertions(+), 166 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index a2a5e8f70..667966a6c 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -187,6 +187,19 @@ impl Hotstuff { self.state_pusher.request_last_state(remote).await; } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_query_state: sub_path: {}, remote: {:?},", + self, + sub_path, + remote + ); + + self.tx_message + .send((HotstuffMessage::QueryState(sub_path), remote)) + .await; + } } struct HotstuffRunner { @@ -1834,6 +1847,19 @@ impl HotstuffRunner { Ok(()) } + async fn handle_query_state(&self, sub_path: String, remote: ObjectId) -> BuckyResult<()> { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + + Ok(()) + } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; @@ -1918,7 +1944,7 @@ impl HotstuffRunner { Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), - Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d3fbd489c..ad3a21e35 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,9 +10,13 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { @@ -136,6 +140,47 @@ impl Committee { Ok(()) } + pub async fn verify_block_desc_with_qc( + &self, + block_desc: &GroupConsensusBlockDesc, + qc: &HotstuffBlockQC, + from: ObjectId, + ) -> BuckyResult<()> { + let block_id = block_desc.object_id(); + + log::debug!( + "[group committee] {} verify block desc {} step1", + self.local_device_id, + block_id + ); + + if block_id != qc.block_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the block id is unmatch with the qc", + )); + } + + self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + .await?; + + log::debug!( + "[group committee] {} verify block desc {} step2", + self.local_device_id, + block_id + ); + + self.verify_qc_with_desc(qc, block_desc.content()).await?; + + log::debug!( + "[group committee] {} verify block desc {} step3", + self.local_device_id, + block_id + ); + + Ok(()) + } + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { let hash = vote.hash(); let device = self.non_driver.get_device(&vote.voter).await?; @@ -250,8 +295,17 @@ impl Committee { qc: &HotstuffBlockQC, prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { - if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); + self.verify_qc_with_desc(qc, prev_block.named_object().desc().content()) + .await + } + + pub async fn verify_qc_with_desc( + &self, + qc: &HotstuffBlockQC, + prev_block_desc: &GroupConsensusBlockDescContent, + ) -> BuckyResult<()> { + if qc.round != prev_block_desc.round() { + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block_desc.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, "round not match in qc", @@ -261,7 +315,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block.group_chunk_id()), + Some(prev_block_desc.group_chunk_id()), ) .await?; @@ -291,7 +345,7 @@ impl Committee { .map_or(Ok(()), |e| e) } - async fn check_group( + pub async fn check_group( &self, chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 0d863e17b..f7b7fbbbe 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -123,6 +123,7 @@ impl GroupManager { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); + let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), @@ -143,9 +144,13 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let state_proccessor = state_mgr + .load_root_state(local_device_id.object_id(), Some(local_id), true) + .await?; let client = RPathClient::load( - local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + state_proccessor.unwrap(), non_driver, network_sender, ) @@ -199,7 +204,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, Some(&block), Some(&remote), ) @@ -215,7 +220,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -231,7 +236,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -247,7 +252,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -263,7 +268,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -279,7 +284,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -321,12 +326,32 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message(HotstuffMessage::QueryState(sub_path), remote) + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + IsCreateRPath::No, + None, + Some(&remote), + ) .await; + + match control { + Ok(control) => { + control + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + _ => { + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + } } HotstuffPackage::VerifiableState(sub_path, result) => { let rpath = result.as_ref().map_or_else( @@ -436,15 +461,10 @@ impl GroupManager { let store = match store { Some(store) => store, None => { - let init_state = match is_auto_create { - IsCreateRPath::Yes(init_state) => init_state, - _ => unreachable!(), - }; GroupStorage::create( group_id, dec_id, rpath, - init_state, non_driver.clone(), local_device_id.object_id().clone(), &root_state_mgr, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 9f1d08579..8a1dd34a7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -5,18 +5,18 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, storage::DecStorage, - HotstuffMessage, CLIENT_POLL_TIMEOUT, + Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; struct RPathClientRaw { rpath: GroupRPath, - local_id: ObjectId, + local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, @@ -28,22 +28,31 @@ pub struct RPathClient(Arc); impl RPathClient { pub(crate) async fn load( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { - let dec_store = DecStorage::load().await?; + let dec_store = DecStorage::load(state_processor).await?; + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); + let state_sync = DecStateSynchronizer::new( - local_id, + local_device_id, rpath.clone(), + committee.clone(), non_driver.clone(), dec_store.clone(), ); let state_requestor = DecStateRequestor::new( - local_id, + local_device_id, rpath.clone(), + committee, network_sender.clone(), non_driver.clone(), dec_store.clone(), @@ -53,7 +62,7 @@ impl RPathClient { rpath, non_driver, network_sender, - local_id, + local_device_id, state_sync, state_requestor, }; @@ -77,7 +86,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -143,7 +152,7 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let random = rand::thread_rng().gen_range(0..oods.len()); let ood = oods.get(random).unwrap().clone(); @@ -154,14 +163,15 @@ impl RPathClient { Ok(()) } - pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 .non_driver .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); + let members = + group.select_members_with_distance(&self.0.local_device_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 101b34075..7abff1ec1 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -89,7 +89,9 @@ impl RPathControl { HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), HotstuffMessage::ProposalResult(_, _) => unreachable!(), - HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::QueryState(sub_path) => { + self.0.hotstuff.on_query_state(sub_path, remote).await + } HotstuffMessage::VerifiableState(_, _) => unreachable!(), } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index b5c3b107e..0a3544c09 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,10 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, CHANNEL_CAPACITY, }; @@ -19,9 +20,9 @@ enum DecStateRequestorMessage { } struct DecStateRequestorRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } #[derive(Clone)] @@ -29,8 +30,9 @@ pub struct DecStateRequestor(Arc); impl DecStateRequestor { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, store: DecStorage, @@ -39,8 +41,9 @@ impl DecStateRequestor { let notifier = CallReplyNotifier::new(); let mut runner = DecStateRequestorRunner::new( - local_id, + local_device_id, rpath, + committee, rx, store, network_sender, @@ -51,7 +54,7 @@ impl DecStateRequestor { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateRequestorRaw { - local_id, + local_device_id, tx_dec_state_req_message: tx, query_state_notifier: notifier, })) @@ -60,7 +63,7 @@ impl DecStateRequestor { pub async fn wait_query_state( &self, sub_path: String, - ) -> CallReplyWaiter> { + ) -> CallReplyWaiter>> { self.0.query_state_notifier.prepare(sub_path).await } @@ -88,21 +91,23 @@ impl DecStateRequestor { } struct DecStateRequestorRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, // timer: Timer, store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } impl DecStateRequestorRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<( DecStateRequestorMessage, ObjectId, @@ -110,10 +115,10 @@ impl DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, rx_dec_state_req_message, // timer: Timer::new(SYNCHRONIZER_TIMEOUT), @@ -121,6 +126,7 @@ impl DecStateRequestorRunner { query_state_notifier, network_sender, non_driver, + committee, } } @@ -144,9 +150,9 @@ impl DecStateRequestorRunner { match result { Ok(result) => { let result = self - .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .check_sub_path_value(sub_path.as_str(), &result, &remote) .await - .map(|_| unimplemented!()); // TODO: 搜索目标值 + .map(|r| r.cloned()); self.query_state_notifier.reply(&sub_path, result).await } @@ -154,40 +160,23 @@ impl DecStateRequestorRunner { } } - async fn verify_verifiable_state( + async fn check_sub_path_value<'a>( &self, sub_path: &str, - result: &GroupRPathStatus, + verifiable_status: &'a GroupRPathStatus, remote: &ObjectId, - ) -> BuckyResult<()> { - // let header_block = self - // .non_driver - // .get_block(&result.block_id, Some(remote)) - // .await?; - // let qc_block = self - // .non_driver - // .get_block(&result.qc_block_id, Some(remote)) - // .await?; - - let qc = &result.certificate; - - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(result.block_desc.content().group_chunk_id()), - Some(&remote), + ) -> BuckyResult> { + self.committee + .verify_block_desc_with_qc( + &verifiable_status.block_desc, + &verifiable_status.certificate, + remote.clone(), ) .await?; - if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "verify failed", - )) - } else { - Ok(()) - } + self.store + .check_sub_path_value(sub_path, verifiable_status) + .await } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 73afb0ad0..7272b3882 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -10,10 +10,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::{verify_block, Timer}, + helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, + Committee, CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -32,7 +32,7 @@ enum DecStateSynchronizerMessage { } struct DecStateSynchronizerRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, proposal_result_notifier: CallReplyNotifier>>, } @@ -42,8 +42,9 @@ pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { @@ -51,8 +52,9 @@ impl DecStateSynchronizer { let notifier = CallReplyNotifier::new(); let mut runner = DecStateSynchronizerRunner::new( - local_id, + local_device_id, rpath, + committee, tx.clone(), rx, store, @@ -63,7 +65,7 @@ impl DecStateSynchronizer { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateSynchronizerRaw { - local_id, + local_device_id, tx_dec_state_sync_message: tx, proposal_result_notifier: notifier, })) @@ -126,8 +128,9 @@ struct UpdateNotifyInfo { } struct DecStateSynchronizerRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, @@ -142,8 +145,9 @@ struct DecStateSynchronizerRunner { impl DecStateSynchronizerRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<( DecStateSynchronizerMessage, ObjectId, @@ -157,7 +161,7 @@ impl DecStateSynchronizerRunner { proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, tx_dec_state_sync_message, rx_dec_state_sync_message, @@ -167,6 +171,7 @@ impl DecStateSynchronizerRunner { update_notifies: None, non_driver, proposal_result_notifier, + committee, } } @@ -330,52 +335,29 @@ impl DecStateSynchronizerRunner { } } - let group = match self.update_notifies.as_ref() { - Some(n) => Some((n.group_chunk_id, n.group.clone())), - None => self - .check_cache() - .await - .as_ref() - .map(|c| (c.group_chunk_id, c.group.clone())), - } - .map_or(None, |(chunk_id, group)| { - if &chunk_id == header_block.group_chunk_id() { - Some((chunk_id, group)) - } else { - None - } - }); - - // group changed - let group = match group { - Some(group) => group, - None => { - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(header_block.group_chunk_id()), - Some(&remote), - ) - .await?; - (header_block.group_chunk_id().clone(), group) - } - }; - if header_block.check() - && verify_block( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - &group.1, - ) - .await? + && self + .committee + .verify_block_desc_with_qc( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + remote, + ) + .await + .is_ok() { + let group = self + .committee + .check_group(Some(header_block.group_chunk_id()), None) + .await?; + let group_chunk_id = header_block.group_chunk_id().clone(); + self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, remotes: HashSet::from([remote]), - group_chunk_id: group.0, - group: group.1, + group_chunk_id, + group, }); }; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 759bf2c4a..ef3e34495 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -5,24 +5,6 @@ use cyfs_core::{ use crate::GroupRPathStatus; -pub async fn verify_block( - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - let block_id = block_desc.object_id(); - if qc.round != block_desc.content().round() || qc.block_id != block_id { - log::error!( - "the qc-block({}) should be next block({})", - qc.round, - block_id - ); - return Ok(false); - } - - unimplemented!() -} - pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index f266d3dbd..858c37fff 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -13,7 +13,7 @@ pub struct GroupRPathStatus { } impl RawEncode for GroupRPathStatus { - fn raw_measure(&self, purpose: &Option) -> BuckyResult { + fn raw_measure(&self, _purpose: &Option) -> BuckyResult { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; let mut status_list = vec![]; @@ -33,7 +33,7 @@ impl RawEncode for GroupRPathStatus { fn raw_encode<'a>( &self, mut buf: &'a mut [u8], - purpose: &Option, + _purpose: &Option, ) -> BuckyResult<&'a mut [u8]> { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index cce00e736..de5a0fd4a 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -1,10 +1,14 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, + ObjectTypeCode, RawDecode, +}; use cyfs_core::GroupConsensusBlock; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::GroupRPathStatus; +use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; #[derive(Clone)] pub struct DecStorageCache { @@ -16,13 +20,15 @@ pub struct DecStorageCache { #[derive(Clone)] pub struct DecStorage { cache: Arc>>, + pub state_processor: GlobalStateRawProcessorRef, } impl DecStorage { - pub async fn load() -> BuckyResult { - unimplemented!(); + pub async fn load(state_processor: GlobalStateRawProcessorRef) -> BuckyResult { + // unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), + state_processor, }; Ok(obj) @@ -45,4 +51,64 @@ impl DecStorage { pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } + + pub async fn check_sub_path_value<'a>( + &self, + sub_path: &str, + verifiable_status: &'a GroupRPathStatus, + ) -> BuckyResult> { + let block_desc = &verifiable_status.block_desc; + let qc = &verifiable_status.certificate; + + let mut parent_state_id = match block_desc.content().result_state_id() { + Some(state_id) => state_id.clone(), + None => return Ok(None), + }; + + let root_cache = self.state_processor.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { + Some(state) => state, + None => return Ok(None), + }; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(None); + } + } + } + + Ok(verifiable_status.status_map.get(&parent_state_id)) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index c4803d6ff..eb0ede98f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -22,9 +22,9 @@ pub struct StorageCacheInfo { } impl StorageCacheInfo { - pub fn new(init_state_id: Option) -> Self { + pub fn new(dec_state_id: Option) -> Self { Self { - dec_state_id: init_state_id, + dec_state_id, last_vote_round: 0, last_qc: None, last_tc: None, diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index b3a01fd60..604e44744 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,10 +2,10 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, + ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -154,6 +154,19 @@ impl StorageEngineGroupState { None => 0, }; + let dec_state_id_in_header = cache + .header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); + + assert_eq!(dec_state_id, dec_state_id_in_header); + if dec_state_id != dec_state_id_in_header { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the state should same as it in header-block", + )); + } + let (prepare_blocks, pre_commit_blocks) = load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { @@ -179,6 +192,10 @@ impl StorageEngineGroupState { .await?, ) } + + pub fn root_cache(&self) -> &ObjectMapRootCacheRef { + self.state_mgr.root_cache() + } } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index ee2618cde..d233025ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -5,7 +5,7 @@ use std::{ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, + ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -15,7 +15,8 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ @@ -56,7 +57,6 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, @@ -84,7 +84,7 @@ impl GroupStorage { GroupStatePath::new(rpath.to_string()), ), local_device_id, - cache: StorageCacheInfo::new(init_state_id), + cache: StorageCacheInfo::new(None), }) } @@ -809,4 +809,100 @@ impl GroupStorage { ) } } + + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let (header_block, qc) = match self.cache.header_block.as_ref() { + Some(block) => { + let (_, qc_block) = self + .cache + .pre_commits + .iter() + .next() + .expect("pre-commit should not be empty"); + + assert_eq!( + qc_block.prev_block_id().unwrap(), + block.block_id().object_id(), + "the prev-block for all pre-commits should be the header" + ); + + (block, qc_block.qc().as_ref().unwrap()) + } + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "the header block is none", + )); + } + }; + + let mut parent_state_id = match header_block.result_state_id() { + Some(state_id) => state_id.clone(), + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map: HashMap::new(), + }) + } + }; + + let mut status_map = HashMap::new(); + + let root_cache = self.storage_engine.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + status_map.insert(parent_state_id, parent_state); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } + } + } + + let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + status_map.insert(parent_state_id, leaf_state); + + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } } diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 9fbc4eb4f..5d005a726 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), // init state + Yes, } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 2ba99716e..0401c55a0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -816,7 +816,7 @@ async fn main_run() { &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -845,7 +845,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -892,7 +892,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); From f21ac10eb6eefb84c4c15112d019c6737342f534 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 17:03:44 +0800 Subject: [PATCH 261/553] Example for APP-State as tree --- .../src/consensus/hotstuff/hotstuff.rs | 9 +- .../cyfs-group/src/dec/delegate_factory.rs | 10 +- .../src/storage/engine/storage_engine.rs | 2 +- .../engine/storage_engine_group_state.rs | 23 ++- .../cyfs-group/src/storage/group_storage.rs | 18 +- src/tests/group-example/src/main.rs | 155 +++++++++++++++--- 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 667966a6c..d9773bd88 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,13 +9,13 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, @@ -499,7 +499,7 @@ impl HotstuffRunner { if self .delegate - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -851,6 +851,7 @@ impl HotstuffRunner { .on_commited( &proposal_obj, pre_state_id, + self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1528,7 +1529,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id).await { + match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index bdcb98f60..0b13d97ce 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -34,12 +34,14 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult; @@ -47,7 +49,13 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ); } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index eb0ede98f..cbb5d99df 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 604e44744..aae81394b 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -8,8 +8,8 @@ use cyfs_base::{ use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -672,3 +672,22 @@ fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult Self { + Self { + state_mgr: state_mgr.clone(), + } + } +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { + async fn create_single_op_env(&self) -> BuckyResult { + self.state_mgr.create_single_op_env(ACCESS) + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d233025ab..3a1c20f2a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,12 +15,15 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ - engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + engine::{ + GroupObjectMapProcessorGroupState, StorageCacheInfo, StorageEngineGroupState, + StorageEngineMock, + }, StorageEngine, }; @@ -50,6 +53,7 @@ pub struct GroupStorage { cache: StorageCacheInfo, storage_engine: StorageEngineGroupState, + object_map_processor: GroupObjectMapProcessorGroupState, } impl GroupStorage { @@ -71,6 +75,7 @@ impl GroupStorage { .expect("create group state failed."); let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -85,6 +90,7 @@ impl GroupStorage { ), local_device_id, cache: StorageCacheInfo::new(None), + object_map_processor, }) } @@ -129,6 +135,7 @@ impl GroupStorage { let state_path = GroupStatePath::new(rpath.to_string()); let cache = StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -140,6 +147,7 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, cache, + object_map_processor, }) } @@ -905,4 +913,8 @@ impl GroupStorage { status_map, }); } + + pub fn get_object_map_processor(&self) -> &dyn GroupObjectMapProcessor { + &self.object_map_processor + } } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0401c55a0..0fae6dd53 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -38,16 +38,18 @@ mod Common { CyfsStackNOCParams, CyfsStackParams, }; - lazy_static::lazy_static! { - // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + /** + * |--root + * |--folder1 + * |--folder2 + * |--value-->u64 + */ - // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); + pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } fn create_member( @@ -495,7 +497,7 @@ mod Client { } mod GroupDecService { - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, fmt::format, sync::Arc}; use async_std::sync::Mutex; use cyfs_base::*; @@ -503,9 +505,11 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; use cyfs_stack::CyfsStack; + use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; + pub struct DecService {} impl DecService { @@ -580,17 +584,78 @@ mod GroupDecService { } impl MyRPathDelegate { - pub fn execute( + pub async fn get_value_from_state_tree_with_single_op_envs( + pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<( + Option, + Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + )> { + let mut single_op_envs = vec![]; + let mut parent_map_id = pre_state_id; + for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + let single_op_env = object_map_processor.create_single_op_env().await.expect( + format!( + "create_single_op_env load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + parent_map_id = match parent_map_id { + Some(parent_map_id) => { + single_op_env.load(&parent_map_id).await.expect( + format!( + "load folder {} parent with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + single_op_env.get_by_key(folder).await.expect( + format!( + "load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ) + } + None => { + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!( + "create folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + None + } + }; + single_op_envs.push((single_op_env, folder, parent_map_id)); + } + + Ok((parent_map_id, single_op_envs)) + } + + pub async fn execute( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let result_state_id = { + let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await?; + + let result_value = { /** * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); + let pre_value = pre_value.map_or(0, |pre_value| { + let buf = pre_value.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -608,6 +673,32 @@ mod GroupDecService { .unwrap() }; + let result_state_id = { + let mut sub_folder_value = result_value; + for (parent_single_op_env, folder, sub_folder_prev_value) in + single_op_envs.into_iter().rev() + { + parent_single_op_env + .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + .await + .expect( + format!( + "update folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + sub_folder_value = parent_single_op_env.commit().await.expect( + format!( + "commit folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + } + sub_folder_value + }; + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? @@ -623,7 +714,7 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_state_id + proposal + context + * (result_state_id, return_object) = pre_value + proposal + context */ Ok(ExecuteResult { context, @@ -632,17 +723,20 @@ mod GroupDecService { }) } - pub fn verify( + pub async fn verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context */ - let result = self.execute(proposal, pre_state_id)?; + let result = self + .execute(proposal, pre_state_id, object_map_processor) + .await?; let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() @@ -658,23 +752,28 @@ mod GroupDecService { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id) + self.execute(proposal, pre_state_id, object_map_processor) + .await } async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) + self.verify(proposal, pre_state_id, object_map_processor, execute_result) + .await } async fn on_commited( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { @@ -685,14 +784,28 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let pre_value = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); - let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let result_value = Self::get_value_from_state_tree_with_single_op_envs( + execute_result.result_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); @@ -901,7 +1014,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } From 9070426b5a8572c339ecfee061837e49d41d6591 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 19:51:46 +0800 Subject: [PATCH 262/553] Fix: Update the state structure, mount the template dec-state of blocks in prepare/pre-commit, to avoid it's recycled. --- .../cyfs-base/src/objects/object_map/mod.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 5 +- .../cyfs-group/src/statepath/design.md | 12 +- .../src/statepath/group_statepath.rs | 34 +++ .../src/storage/engine/storage_engine.rs | 20 +- .../engine/storage_engine_group_state.rs | 139 ++++++++-- .../src/storage/engine/storage_engine_mock.rs | 7 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 248 +++++++++++------- 9 files changed, 351 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index 3bbc5f131..75589834b 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -18,6 +18,7 @@ mod visitor; pub use access::*; pub use cache::*; pub use diff::*; +pub use isolate_path_env::*; pub use iterator::*; pub use object_map::*; pub use op_env::*; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 0b13d97ce..f5092dbfc 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,6 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -58,4 +60,5 @@ pub trait RPathDelegate: Sync + Send { #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; } diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index cb964e066..885888d5b 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -22,14 +22,20 @@ | |--users | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-vote-round-->u64 // 最后一次投票的 轮次 | |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block | | -| |--prepares->Set // Prepare状态的block -| |--pre-commits->Set // pre-commit状态的block +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 72f48e601..0ed0abd25 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -10,6 +10,8 @@ pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; @@ -164,10 +166,42 @@ impl GroupStatePath { self.prepares.as_str() } + pub fn prepares_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn prepares_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn pre_commits(&self) -> &str { self.pre_commits.as_str() } + pub fn pre_commits_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn finish_proposals(&self) -> &str { self.finish_proposals.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index cbb5d99df..e14445695 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -43,9 +43,19 @@ impl StorageCacheInfo { #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()>; + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + is_instead: bool, + ) -> BuckyResult<()>; + async fn push_commit( &mut self, height: u64, @@ -54,7 +64,9 @@ pub trait StorageWriter: Send + Sync { prev_result_state_id: &Option, min_height: u64, ) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( &mut self, proposal_ids: &[ObjectId], @@ -62,7 +74,9 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index aae81394b..8b8799207 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,14 +2,15 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, - ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -90,7 +91,8 @@ impl StorageEngineGroupState { None => None, }; - let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let prepare_block_ids = + load_object_ids_with_path_map_key(&op_env, state_path.prepares()).await?; if prepare_block_ids.len() == 0 && commit_range.is_none() { return Err(BuckyError::new( BuckyErrorCode::NotFound, @@ -99,7 +101,7 @@ impl StorageEngineGroupState { } let pre_commit_block_ids = - load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + load_object_ids_with_path_map_key(&op_env, state_path.pre_commits()).await?; let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { @@ -113,8 +115,10 @@ impl StorageEngineGroupState { n }); - let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; - let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + let adding_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.adding()).await?; + let over_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.recycle()).await?; let load_block_ids = [ first_header_block_ids.as_slice(), @@ -233,7 +237,7 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new(ObjectMapSimpleContentType::Map) .await?; None } else { @@ -253,20 +257,51 @@ impl StorageEngineGroupStateWriter { }) } - async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn create_block_result_object_map( + &self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult { + let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await?; + single_op_env + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + if let Some(state_id) = result_state_id.as_ref() { + single_op_env + .insert_with_key(GROUP_STATE_PATH_RESULT_STATE, state_id) + .await?; + } + + single_op_env.commit().await + } + + async fn insert_prepares_inner( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) + .await?; self.prepare_op_env - .insert(block_id) + .insert_with_key(block_id.to_string().as_str(), &block_result_pair) .await - .map(|is_changed| assert!(is_changed)) } async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); if is_instead { self.op_env @@ -274,12 +309,17 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self - .op_env - .insert(self.state_path.pre_commits(), block_id) + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) .await?; - assert!(is_changed); - Ok(()) + + self.op_env + .insert_with_key( + self.state_path.pre_commits(), + block_id.to_string().as_str(), + &block_result_pair, + ) + .await } async fn push_commit_inner( @@ -357,8 +397,11 @@ impl StorageEngineGroupStateWriter { async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); } Ok(()) } @@ -486,19 +529,26 @@ impl StorageEngineGroupStateWriter { #[async_trait::async_trait] impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result = self.insert_prepares_inner(block_id, result_state_id).await; self.write_result.clone() } async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result = self + .insert_pre_commit_inner(block_id, result_state_id, is_instead) + .await; self.write_result.clone() } @@ -614,7 +664,7 @@ fn parse_u64_obj(obj: &ObjectId) -> u64 { u64::from_le_bytes(buf) } -async fn load_object_ids_with_path( +async fn load_object_ids_with_path_set( op_env: &ObjectMapPathOpEnvRef, full_path: &str, ) -> BuckyResult> { @@ -647,6 +697,41 @@ async fn load_object_ids_with_path( Ok(object_ids) } +async fn load_object_ids_with_path_map_key( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Map((key_id_base58, _)) => { + object_ids.push(ObjectId::from_base58(key_id_base58)?) + } + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} + fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { match r { Ok(t) => Ok(Some(t)), @@ -690,4 +775,8 @@ impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { async fn create_single_op_env(&self) -> BuckyResult { self.state_mgr.create_single_op_env(ACCESS) } + + async fn create_sub_tree_op_env(&self) -> BuckyResult { + self.state_mgr.create_isolate_path_op_env(ACCESS) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index ebeedd7ca..fbc7cafdc 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -71,7 +71,11 @@ pub struct StorageEngineMockWriter<'a> { #[async_trait::async_trait] impl<'a> StorageWriter for StorageEngineMockWriter<'a> { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { if !self.engine.prepare_blocks.insert(block_id.clone()) { assert!(false); return Err(BuckyError::new( @@ -85,6 +89,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { if !self.engine.prepare_blocks.remove(block_id) { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a1c20f2a..491d029dd 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -291,10 +291,16 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(block_id.object_id()).await?; - if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_prepares(block_id.object_id(), block.result_state_id()) + .await?; + if let Some((new_pre_commit_id, new_pre_commit)) = new_pre_commit.as_ref() { writer - .insert_pre_commit(new_pre_commit, new_header.is_some()) + .insert_pre_commit( + new_pre_commit_id, + new_pre_commit.result_state_id(), + new_header.is_some(), + ) .await?; } if let Some(new_header) = new_header.as_ref() { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0fae6dd53..394b15acb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -584,59 +584,59 @@ mod GroupDecService { } impl MyRPathDelegate { - pub async fn get_value_from_state_tree_with_single_op_envs( - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, - ) -> BuckyResult<( - Option, - Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - )> { - let mut single_op_envs = vec![]; - let mut parent_map_id = pre_state_id; - for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - let single_op_env = object_map_processor.create_single_op_env().await.expect( - format!( - "create_single_op_env load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - parent_map_id = match parent_map_id { - Some(parent_map_id) => { - single_op_env.load(&parent_map_id).await.expect( - format!( - "load folder {} parent with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - single_op_env.get_by_key(folder).await.expect( - format!( - "load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ) - } - None => { - single_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await - .expect( - format!( - "create folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - None - } - }; - single_op_envs.push((single_op_env, folder, parent_map_id)); - } - - Ok((parent_map_id, single_op_envs)) - } + // pub async fn get_value_from_state_tree_with_single_op_envs( + // pre_state_id: Option, + // object_map_processor: &dyn GroupObjectMapProcessor, + // ) -> BuckyResult<( + // Option, + // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + // )> { + // let mut single_op_envs = vec![]; + // let mut parent_map_id = pre_state_id; + // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + // let single_op_env = object_map_processor.create_single_op_env().await.expect( + // format!( + // "create_single_op_env load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // parent_map_id = match parent_map_id { + // Some(parent_map_id) => { + // single_op_env.load(&parent_map_id).await.expect( + // format!( + // "load folder {} parent with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // single_op_env.get_by_key(folder).await.expect( + // format!( + // "load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ) + // } + // None => { + // single_op_env + // .create_new(ObjectMapSimpleContentType::Map) + // .await + // .expect( + // format!( + // "create folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // None + // } + // }; + // single_op_envs.push((single_op_env, folder, parent_map_id)); + // } + + // Ok((parent_map_id, single_op_envs)) + // } pub async fn execute( &self, @@ -644,11 +644,30 @@ mod GroupDecService { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await?; + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + let pre_value = match pre_state_id { + Some(pre_state_id) => { + state_op_env.load(&pre_state_id).await?; + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ) + } + None => { + state_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ); + None + } + }; let result_value = { /** @@ -674,29 +693,50 @@ mod GroupDecService { }; let result_state_id = { - let mut sub_folder_value = result_value; - for (parent_single_op_env, folder, sub_folder_prev_value) in - single_op_envs.into_iter().rev() - { - parent_single_op_env - .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - .await - .expect( - format!( - "update folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value - ) - .as_str(), - ); - sub_folder_value = parent_single_op_env.commit().await.expect( + state_op_env + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .await + .expect( format!( - "commit folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value + "set_with_path {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value ) .as_str(), ); - } - sub_folder_value + state_op_env.commit().await.expect( + format!( + "commit {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value + ) + .as_str(), + ) + // let mut sub_folder_value = result_value; + // for (parent_single_op_env, folder, sub_folder_prev_value) in + // single_op_envs.into_iter().rev() + // { + // parent_single_op_env + // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + // .await + // .expect( + // format!( + // "update folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // sub_folder_value = parent_single_op_env.commit().await.expect( + // format!( + // "commit folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // } + // sub_folder_value }; let receipt = { @@ -784,13 +824,26 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let pre_value = match pre_state_id { + Some(pre_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&pre_state_id) + .await + .expect(format!("load {} failed", pre_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; @@ -798,13 +851,26 @@ mod GroupDecService { u64::from_be_bytes(pre_value) }); - let result_value = Self::get_value_from_state_tree_with_single_op_envs( - execute_result.result_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let result_value = match execute_result.result_state_id { + Some(result_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&result_state_id) + .await + .expect(format!("load {} failed", result_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; From 5eb534d46e0f4f2dbe93a3360dfd33035f8c4440 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:00 +0800 Subject: [PATCH 263/553] Accept the invalid block with vote it. --- src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 138 +++++++++++++----- .../cyfs-group/src/storage/group_storage.rs | 102 +------------ 3 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index aaab4ed76..4a7aae6c2 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' +itertools = "0.10.3" cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d9773bd88..511b0b32e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -13,6 +13,7 @@ use cyfs_core::{ }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; +use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, @@ -365,7 +366,7 @@ impl HotstuffRunner { } } - let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, Err(err) => return err }; @@ -391,9 +392,6 @@ impl HotstuffRunner { self, block.block_id()); - self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await?; - self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -402,7 +400,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote, &proposals).await + self.process_block(block, remote, &HashMap::new()).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -574,7 +572,7 @@ impl HotstuffRunner { } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { match self.store.block_linked(block).await .map_err(|err| Err(err))? { @@ -585,16 +583,6 @@ impl HotstuffRunner { ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - Err (Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - ))) - } crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", @@ -605,7 +593,7 @@ impl HotstuffRunner { "duplicate block", ))) } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { + crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", self, @@ -614,7 +602,7 @@ impl HotstuffRunner { // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; - Ok((prev_block, proposals)) + Ok(prev_block) } crate::storage::BlockLinkState::Pending => { log::warn!( @@ -942,20 +930,6 @@ impl HotstuffRunner { return None; } - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 - let mut proposal_temp: HashMap = HashMap::new(); - if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { - Ok(_) => proposals = &proposal_temp, - Err(_) => return None - } - } else { - assert_eq!(proposals.len(), block.proposals().len()); - } - if !Self::check_timestamp_precision(block, proposals) { - return None; - } - // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -982,6 +956,22 @@ impl HotstuffRunner { return None; } + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block.clone()), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None + }, + }, + None => None + }; + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -993,6 +983,77 @@ impl HotstuffRunner { } } + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + return None + } + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + return None; + } + + if proposals.len() != block.proposals().len() { + let mut dup_proposals = block.proposals().clone(); + dup_proposals.sort_unstable_by_key(|p| p.proposal); + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + ); + return None; + } + + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + match block.prev_block_id() { + Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await.map(|is_finished| (is_finished, &proposal_result.proposal)), + None => Ok((false, &proposal_result.proposal)) + } + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok((is_finished, proposal_id)) => { + if is_finished { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + proposal_id + ); + return None; + } + }, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", + self, + block.block_id(), + err + ); + return None; + }, + } + } + + if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await.is_err() { + return None; + } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1021,12 +1082,23 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { false } else { + if let Some(prev_block) = prev_block { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { + if duration > TIME_PRECISION { + return false + } + } + } + for proposal in block.proposals() { let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 491d029dd..04e4c80fc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,22 +1,19 @@ -use std::{ - collections::{HashMap, HashSet}, - time::SystemTime, -}; +use std::collections::{HashMap, HashSet}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ @@ -31,11 +28,10 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, - DuplicateProposal, Duplicate, Link( Option, - HashMap, + // HashMap, ), // Pending, InvalidBranch, @@ -528,18 +524,6 @@ impl GroupStorage { return Ok(BlockLinkState::Duplicate); } - let now = SystemTime::now(); - let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); - - if let Ok(duration) = block_time.duration_since(now) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } - log::debug!( "[group storage] {} block_linked {} step2", self.local_device_id, @@ -554,17 +538,6 @@ impl GroupStorage { } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); - if let Ok(duration) = prev_block_time.duration_since(block_time) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } Some(prev_block) } } @@ -592,66 +565,7 @@ impl GroupStorage { block.block_id() ); - let mut proposals = HashMap::new(); - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? - { - return Ok(BlockLinkState::DuplicateProposal); - } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - - Ok(BlockLinkState::Link( - None, - HashMap::from([(proposal_result.proposal, proposal)]), - )) - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok(result) => match result { - BlockLinkState::Link(_, proposal) => { - let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); - if proposals.get(&proposal_id).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } - proposals.insert(proposal_id, proposal); - } - _ => return Ok(result), - }, - _ => return check_result, - } - } - - log::debug!( - "[group storage] {} block_linked {} step4", - self.local_device_id, - block.block_id() - ); - - Ok(BlockLinkState::Link(prev_block, proposals)) + Ok(BlockLinkState::Link(prev_block)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From a47305547fc9ddd16a140e071420296733a0ae5c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:55 +0800 Subject: [PATCH 264/553] Chore unused code --- src/component/cyfs-group/src/storage/group_storage.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 04e4c80fc..122ae72ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -29,10 +29,7 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, Duplicate, - Link( - Option, - // HashMap, - ), // + Link(Option), // Pending, InvalidBranch, } From 0cc9546ebf1604ab08986baf15329a1c1297fa61 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 12:20:23 +0800 Subject: [PATCH 265/553] get VerifiableState from the admin --- .../src/consensus/hotstuff/hotstuff.rs | 260 +++++++++++------- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 2 +- src/component/cyfs-group/src/constant.rs | 2 +- .../src/dec_state/dec_state_requestor.rs | 5 + .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../src/objects/group_rpath_status.rs | 21 +- .../cyfs-group/src/objects/protocol.rs | 11 +- .../cyfs-group/src/storage/dec_storage.rs | 6 + .../cyfs-group/src/storage/group_storage.rs | 27 +- src/tests/group-example/Cargo.toml | 3 +- src/tests/group-example/src/main.rs | 79 +++++- 11 files changed, 302 insertions(+), 116 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 511b0b32e..10c5d9635 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -4,7 +4,7 @@ use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, + RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -19,11 +19,13 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * + * synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -212,6 +214,7 @@ struct HotstuffRunner { round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, + max_quorum_round: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -311,6 +314,7 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, + max_quorum_round: round - 1, state_pusher, tx_block_gen, rx_block_gen, @@ -366,15 +370,6 @@ impl HotstuffRunner { } } - let prev_block = match self.check_block_linked(&block, remote).await { - Ok(link) => link, - Err(err) => return err - }; - - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", - self, - block.block_id()); - self.committee .verify_block(block, remote) .await @@ -388,6 +383,18 @@ impl HotstuffRunner { err })?; + let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); + self.update_max_quorum_round(quorum_round); + + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + + let prev_block = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err + }; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", self, block.block_id()); @@ -452,10 +459,19 @@ impl HotstuffRunner { block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, + remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = prev_block - .as_ref() - .map_or(None, |block| block.result_state_id().clone()); + let mut prev_state_id = match prev_block + .as_ref() { + Some(prev_block) => { + let result_state_id = block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; + } + result_state_id.clone() + }, + None => None + }; for proposal_exe_info in block.proposals() { // 去重 @@ -672,7 +688,7 @@ impl HotstuffRunner { err })?; - if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", self, header_block.block_id() @@ -696,29 +712,18 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(header_block.clone(), qc_block).await; + self.notify_block_committed(&header_block, &old_header_block, qc_block).await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", self, block.block_id() ); - let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self, self.round, err - ); - - err - }); - // notify by leader - if let Ok(leader) = leader { - if self.local_device_id == leader { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } + if &self.local_id == header_block.owner() { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; } log::debug!( @@ -733,7 +738,7 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, the qc of block {:?} has received before", self, block.block_id() ); - return self.process_block_qc(qc, block, remote).await; + return self.process_block_qc(qc, block).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( @@ -762,7 +767,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block, proposals).await { + if let Some(vote) = self.make_vote(block, proposals, &remote).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -791,22 +796,12 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - let mut pre_state_id = match new_header.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); + + let mut pre_state_id = old_header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); for proposal in new_header.proposals() { let proposal_obj = self @@ -900,6 +895,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_round(&mut self, quorum_round: u64) { + if quorum_round > self.max_quorum_round { + self.max_quorum_round = quorum_round; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -922,7 +923,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -930,6 +931,13 @@ impl HotstuffRunner { return None; } + if self.max_quorum_round >= self.round { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } + // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -1002,6 +1010,10 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + self, + block.block_id(), + ); return None; } @@ -1016,44 +1028,15 @@ impl HotstuffRunner { return None; } - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - match block.prev_block_id() { - Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await.map(|is_finished| (is_finished, &proposal_result.proposal)), - None => Ok((false, &proposal_result.proposal)) - } - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok((is_finished, proposal_id)) => { - if is_finished { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", - self, - block.block_id(), - proposal_id - ); - return None; - } - }, - Err(err) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", - self, - block.block_id(), - err - ); - return None; - }, - } + if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err + ); + return None; } - if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await.is_err() { - return None; - } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1075,7 +1058,12 @@ impl HotstuffRunner { } }; - if self.store.set_last_vote_round(block.round()).await.is_err() { + if let Err(err) = self.store.set_last_vote_round(block.round()).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for update last-vote-round failed {:?}", + self, + block.block_id(), + err + ); return None; } @@ -1086,23 +1074,39 @@ impl HotstuffRunner { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + block.block_id(), + block_timestamp, + now + ); + false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); + let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + block.block_id(), + block_timestamp, + prev_block_time + ); return false } } } for proposal in block.proposals() { - let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_id = proposal.proposal; + let proposal = proposals.get(&proposal_id).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + block.block_id(), + block_timestamp, + proposal_id, + proposal_timestamp + ); return false } } @@ -1174,7 +1178,7 @@ impl HotstuffRunner { if is_prev_none {"None"} else {"Some"} ); - self.process_block_qc(qc, &block, remote).await?; + self.process_block_qc(qc, &block).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1185,7 +1189,6 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, - remote: ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1334,7 +1337,10 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - + + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1453,6 +1459,9 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1501,8 +1510,7 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ) - .await.map_err(|err| { + ).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", self, err @@ -1541,7 +1549,13 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let prev_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), + Some(qc) => { + let prev_block = self.store.find_block_in_cache(&qc.block_id)?; + if let Some(result_state_id) = prev_block.result_state_id() { + self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + } + Some(prev_block) + }, None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1940,6 +1954,58 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } + async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 + let obj_map_processor = self.store.get_object_map_processor(); + + #[async_recursion::async_recursion] + async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if non_driver.get_object(&root_id, None).await.is_ok() { + // TODO: 可能有下级分支子树因为异常不齐全 + return Ok(()); + } + let obj = non_driver.get_object(root_id, Some(remote)).await?; + match obj.object.as_ref() { + Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { + let single_op_env = obj_map_processor.create_single_op_env().await?; + single_op_env.load(root_id).await?; + loop { + let branchs = single_op_env.next(16).await?; + for branch in branchs.list.iter() { + let branch_id = match branch { + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Map(map) => &map.1, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Set(set) => set, + }; + make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + } + + if branchs.list.len() < 16 { + return Ok(()) + } + } + }, + _ => return Ok(()) + } + } + + let mut result = Ok(()); + for remote in remotes { + result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + if result.is_ok() { + return result; + } + } + result + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 82f4017a0..f44260a04 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 1170176b2..77a652a7e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,7 +17,7 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; -pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(5000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 0a3544c09..790429c6c 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -154,6 +154,11 @@ impl DecStateRequestorRunner { .await .map(|r| r.cloned()); + log::debug!( + "handle_verifiable_state sub_path: {}, result: {:?}", + sub_path, + result + ); self.query_state_notifier.reply(&sub_path, result).await } Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cc0b4aff2..b1506a192 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -13,7 +13,7 @@ use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), - BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), // LastStateRequest(ObjectId), DelayBroadcast, } diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index 858c37fff..bfc9bc5d2 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -69,8 +69,25 @@ impl<'de> RawDecode<'de> for GroupRPathStatus { assert_eq!(remain.len(), 0); let mut status_map = HashMap::new(); for obj_buf in proto.status_list.iter() { - let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; - assert_eq!(remain.len(), 0); + log::debug!("will decode len: {}", obj_buf.len()); + // size + object_id + let status = if obj_buf.len() > OBJECT_ID_LEN + 1 { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status + } else if obj_buf.len() == OBJECT_ID_LEN + 1 { + NONObjectInfo::new( + ObjectId::clone_from_slice(&obj_buf.as_slice()[1..])?, + obj_buf.clone(), + None, + ) + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidData, + "expect NONObjectInfo", + )); + }; + status_map.insert(status.object_id, status); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 6c9f89e96..932e5cd46 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use itertools::Itertools; use sha2::Digest; use crate::GroupRPathStatus; @@ -185,12 +186,13 @@ impl std::fmt::Debug for HotstuffMessage { result.as_ref().map(|status| { let desc = status.block_desc.content(); format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ) }) ) @@ -315,12 +317,13 @@ impl std::fmt::Debug for HotstuffPackage { |status| { let desc = status.block_desc.content(); let ok = format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ); Ok(ok) } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index de5a0fd4a..60a45724f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -69,6 +69,10 @@ impl DecStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { Some(state) => state, None => return Ok(None), @@ -98,6 +102,8 @@ impl DecStorage { assert_eq!(remain.len(), 0); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 122ae72ab..966fa518a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, - ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, @@ -223,7 +223,13 @@ impl GroupStorage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - ) -> BuckyResult)>> { + ) -> BuckyResult< + Option<( + &GroupConsensusBlock, + Option, + Vec, + )>, + > { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); @@ -399,9 +405,10 @@ impl GroupStorage { } } - self.cache.header_block = Some(new_header); + let old_header_block = self.cache.header_block.replace(new_header); return Ok(Some(( self.cache.header_block.as_ref().unwrap(), + old_header_block, removed_blocks, ))); } @@ -736,6 +743,7 @@ impl GroupStorage { } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + // TODO: 需要一套通用的同步ObjectMap树的实现 let (header_block, qc) = match self.cache.header_block.as_ref() { Some(block) => { let (_, qc_block) = self @@ -778,6 +786,9 @@ impl GroupStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { @@ -806,6 +817,8 @@ impl GroupStorage { status_map.insert(parent_state_id, parent_state); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder @@ -821,7 +834,11 @@ impl GroupStorage { } } - let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + let leaf_state = if parent_state_id.is_data() { + NONObjectInfo::new(parent_state_id, parent_state_id.to_vec()?, None) + } else { + self.non_driver.get_object(&parent_state_id, None).await? + }; status_map.insert(parent_state_id, leaf_state); return Ok(GroupRPathStatus { diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 0053ccd5f..01094f12a 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -27,4 +27,5 @@ cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } -cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 394b15acb..618336df4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -14,7 +14,7 @@ use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; mod Common { use std::{fmt::format, io::ErrorKind, sync::Arc}; @@ -505,8 +505,15 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + use cyfs_group::{ + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, + }; + use cyfs_lib::{ + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, + }; use cyfs_stack::CyfsStack; + use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -522,10 +529,42 @@ mod GroupDecService { Box::new(GroupRPathDelegateFactory { local_name }), ) .await - .unwrap() + .unwrap(); + + // let source = RequestSourceInfo { + // protocol: todo!(), + // zone: todo!(), + // dec: todo!(), + // verified: todo!(), + // }; + + // cyfs_stack + // .router_handlers() + // .handlers(&RouterHandlerChain::PostRouter) + // .post_object() + // .add_handler(RouterHandler::new()); } } + // pub struct PostProposalRoutine { + // controller: RPathControl, + // } + + // #[async_trait::async_trait] + // impl EventListenerAsyncRoutine + // for PostProposalRoutine + // { + // async fn call( + // &self, + // param: &NONPostObjectInputRequest, + // ) -> BuckyResult { + // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // self.controller.push_proposal(proposal).await?; + // Ok(NONPostObjectInputResponse { object: None }) + // } + // } + pub struct GroupRPathDelegateFactory { local_name: String, } @@ -778,6 +817,16 @@ mod GroupDecService { .execute(proposal, pre_state_id, object_map_processor) .await?; + log::info!( + "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + execute_result.result_state_id, + execute_result.context.is_none(), + execute_result.receipt.is_none(), + result.result_state_id, + result.context.is_none(), + result.receipt.is_none() + ); + let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() && execute_result.receipt.is_none(); @@ -1007,7 +1056,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 1000usize; + let PROPOSAL_COUNT = 5usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1085,6 +1134,28 @@ async fn main_run() { log::info!("will push new proposals, i: {}", i); } } + + let client = admin_stacks + .get(0) + .unwrap() + .group_mgr() + .rpath_client( + &group.desc().object_id(), + dec_app_id.object_id(), + &EXAMPLE_RPATH, + ) + .await + .unwrap(); + + let value_obj = client + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .unwrap(); + let buf = value_obj.as_ref().unwrap().object_id.data(); + let mut value = [0u8; 8]; + value.copy_from_slice(&buf[..8]); + + log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From a70f7d47e25ac77aeac1a6a90e38d298d37d8e7f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 15:46:00 +0800 Subject: [PATCH 266/553] Fix: result-state verify failed --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++++++++++++++---- src/tests/group-example/src/main.rs | 3 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 10c5d9635..e142d4069 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -464,7 +464,7 @@ impl HotstuffRunner { let mut prev_state_id = match prev_block .as_ref() { Some(prev_block) => { - let result_state_id = block.result_state_id(); + let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; } @@ -520,14 +520,24 @@ impl HotstuffRunner { err })? { + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); + prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", self, proposal_exe_info.proposal, - prev_state_id, - proposal_exe_info.result_state + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); @@ -966,7 +976,7 @@ impl HotstuffRunner { let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block.clone()), + Ok(block) => Some(block), Err(_) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", self, @@ -1960,11 +1970,18 @@ impl HotstuffRunner { #[async_recursion::async_recursion] async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if root_id.is_data() { + return Ok(()); + } + if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await?; + let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { + log::warn!("get branch {} failed {:?}", root_id, err); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { let single_op_env = obj_map_processor.create_single_op_env().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 618336df4..4daa0d4f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -818,7 +818,8 @@ mod GroupDecService { .await?; log::info!( - "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + pre_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), From 9a4bfa61e502a28986dc047a8cdf5391cea6521a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 28 Feb 2023 20:27:49 +0800 Subject: [PATCH 267/553] Redefine the Group object for Permission --- .../protos/standard_objects-permission.proto | 203 ++++++++++++++++++ src/tests/group-example/src/main.rs | 8 +- 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto new file mode 100644 index 000000000..b2ec61f60 --- /dev/null +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -0,0 +1,203 @@ +syntax="proto3"; + +// contract +message ContractBodyContent { + bytes data = 1; +} + +// device +message DeviceBodyContent { + repeated bytes endpoints = 1; + repeated bytes sn_list = 2; + repeated bytes passive_pn_list = 3; + optional string name = 4; + optional uint32 bdt_version = 5; +} + +// dir +message DirBodyContent { + enum Type { + Chunk = 0; + ObjList = 1; + } + Type type = 1; + optional bytes chunk_id = 2; + + // 使用list编码hash_map + message ObjItem { + bytes obj_id = 1; + bytes value = 2; + } + repeated ObjItem obj_list = 3; +} + +// file +message ChunkList { + enum Type { + ChunkInList = 0; + ChunkInFile = 1; + ChunkInBundle = 2; + } + enum HashMethod { + Serial = 0; + } + + Type type = 1; + repeated bytes chunk_id_list = 2; + bytes file_id = 3; + optional HashMethod hash_method = 4; +} + +message FileBodyContent { + ChunkList chunk_list = 1; +} + +// people +message PeopleBodyContent { + repeated bytes ood_list = 1; + optional string name = 2; + optional bytes icon = 3; + optional string ood_work_mode = 4; +} + +message GroupRPathPermissionWeight { + string rpath = 1; + GroupFunctionPermissionWeight weight = 2; +} + +message GroupDecPermissionWeight { + bytes dec_id = 1; + optional GroupRPathPermissionWeight default_dec_weight = 2; + repeated GroupRPathPermissionWeight rpath_weight = 3; +} + +message GroupMember { + bytes id = 1; + string title = 2; + // uint64 shares = 3; delay + optional GroupGlobalPermissionWeight global_weight = 4; + optional GroupDecPermissionWeight weight = 5; +} + +/** +admin 修改管理员列表 +member 修改成员列表 +display-${scope} 修改展示信息 + ${scope}=g: 修改group信息 + ${scope}=s: 修改自身信息 + ${scope}=m: 修改任意member信息 + ${scope}=a: 修改任意admin信息 +property 修改资产信息 +conclusion 修改决议类别列表 +conclusion-${category} 修改决议类别配置 +it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) +c-${any} 其他自定义(custom)权限 +*/ + +message GroupGlobalPermissionWeight { + optional uint32 admin = 1; + optional uint32 member = 2; + optional uint32 display_group = 3; + optional uint32 display_self = 4; + optional uint32 display_member = 5; + optional uint32 display_admin = 6; + optional uint32 property = 7; +} + +message GroupCommonPermissionWeight { + string category = 1; + uint32 weight = 2; +} + +message GroupFunctionPermissionWeight { + optional uint32 it = 1; + optional uint32 conclusion = 2; + repeated GroupCommonPermissionWeight conclusion_category = 3; + repeated GroupCommonPermissionWeight custom = 4; +} + +message GroupITConfig { + repeated bytes ood_list = 8; + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms +} + +message GroupConclusionConfig { + string category = 1; + uint64 lifespan = 2; // ms +} + +message GroupConfigItem { + optional GroupITConfig it = 1; + repeated GroupConclusionConfig conclusions = 2; + optional GroupFunctionPermissionWeight weight_threshold = 3; +} + +message GroupRPathConfig { + string rpath = 1; + GroupConfigItem config = 2; +} + +message GroupDecConfig { + bytes dec_id = 1; + optional GroupConfigItem default_dec_config = 2; + repeated GroupRPathConfig rpath_configs = 3; +} + +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; + + repeated GroupMember members = 4; + + // uint64 total_equity = 5; // delay + + repeated bytes revoked_conclusions = 6; + + GroupConfigItem default_config = 7; + repeated GroupDecConfig dec_configs = 8; + + GroupGlobalPermissionWeight global_weight_threshold = 9; + GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + + uint64 version = 11; +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} + +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} + +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; +} + +// tx +message TxBodyContent { + bytes data = 1; +} + +// proof_of_service +message ProofData { + bytes data = 1; +} + +message ProofOfServiceBodyContent { + ProofData data = 1; +} \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 4daa0d4f1..ef2366de0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1051,13 +1051,13 @@ async fn main_run() { .unwrap(); } - async_std::task::sleep(Duration::from_millis(30000)).await; + async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 5usize; + let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1130,12 +1130,14 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } + async_std::task::sleep(Duration::from_millis(10000)).await; + let client = admin_stacks .get(0) .unwrap() From 122ab80b6531b28ab0dd322f40bac0c6565fb358 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 14:41:55 +0800 Subject: [PATCH 268/553] Simplify group definition --- .../protos/standard_objects-permission.proto | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto index b2ec61f60..09f9e3684 100644 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -60,89 +60,9 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } -message GroupRPathPermissionWeight { - string rpath = 1; - GroupFunctionPermissionWeight weight = 2; -} - -message GroupDecPermissionWeight { - bytes dec_id = 1; - optional GroupRPathPermissionWeight default_dec_weight = 2; - repeated GroupRPathPermissionWeight rpath_weight = 3; -} - message GroupMember { bytes id = 1; string title = 2; - // uint64 shares = 3; delay - optional GroupGlobalPermissionWeight global_weight = 4; - optional GroupDecPermissionWeight weight = 5; -} - -/** -admin 修改管理员列表 -member 修改成员列表 -display-${scope} 修改展示信息 - ${scope}=g: 修改group信息 - ${scope}=s: 修改自身信息 - ${scope}=m: 修改任意member信息 - ${scope}=a: 修改任意admin信息 -property 修改资产信息 -conclusion 修改决议类别列表 -conclusion-${category} 修改决议类别配置 -it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) -c-${any} 其他自定义(custom)权限 -*/ - -message GroupGlobalPermissionWeight { - optional uint32 admin = 1; - optional uint32 member = 2; - optional uint32 display_group = 3; - optional uint32 display_self = 4; - optional uint32 display_member = 5; - optional uint32 display_admin = 6; - optional uint32 property = 7; -} - -message GroupCommonPermissionWeight { - string category = 1; - uint32 weight = 2; -} - -message GroupFunctionPermissionWeight { - optional uint32 it = 1; - optional uint32 conclusion = 2; - repeated GroupCommonPermissionWeight conclusion_category = 3; - repeated GroupCommonPermissionWeight custom = 4; -} - -message GroupITConfig { - repeated bytes ood_list = 8; - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms -} - -message GroupConclusionConfig { - string category = 1; - uint64 lifespan = 2; // ms -} - -message GroupConfigItem { - optional GroupITConfig it = 1; - repeated GroupConclusionConfig conclusions = 2; - optional GroupFunctionPermissionWeight weight_threshold = 3; -} - -message GroupRPathConfig { - string rpath = 1; - GroupConfigItem config = 2; -} - -message GroupDecConfig { - bytes dec_id = 1; - optional GroupConfigItem default_dec_config = 2; - repeated GroupRPathConfig rpath_configs = 3; } message CommonGroupBodyContent { @@ -152,17 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - // uint64 total_equity = 5; // delay - - repeated bytes revoked_conclusions = 6; - - GroupConfigItem default_config = 7; - repeated GroupDecConfig dec_configs = 8; - - GroupGlobalPermissionWeight global_weight_threshold = 9; - GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + repeated bytes ood_list = 5; - uint64 version = 11; + optional bytes prev_version = 6; + uint64 version_num = 7; } // simple_group @@ -184,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx From 7fdbff4bf6bcac420dec50f716f2cd382f222f93 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 20:16:27 +0800 Subject: [PATCH 269/553] Move the interface to cyfs-lib --- .../src/consensus/hotstuff/hotstuff.rs | 8 +++--- .../cyfs-group/src/dec/group_manager.rs | 6 ++--- src/component/cyfs-group/src/dec/mod.rs | 6 ++--- .../cyfs-group/src/dec/rpath_control.rs | 3 ++- .../engine/storage_engine_group_state.rs | 6 ++--- .../cyfs-group/src/storage/group_storage.rs | 6 ++--- .../src/group}/delegate_factory.rs | 2 +- .../cyfs-lib/src/group/group_manager.rs | 20 ++++++++++++++ src/component/cyfs-lib/src/group/mod.rs | 7 +++++ .../cyfs-lib/src/group/rpath_client.rs | 27 +++++++++++++++++++ src/component/cyfs-lib/src/lib.rs | 6 +++-- src/tests/group-example/src/main.rs | 8 +++--- 12 files changed, 79 insertions(+), 26 deletions(-) rename src/component/{cyfs-group/src/dec => cyfs-lib/src/group}/delegate_factory.rs (98%) create mode 100644 src/component/cyfs-lib/src/group/group_manager.rs create mode 100644 src/component/cyfs-lib/src/group/mod.rs create mode 100644 src/component/cyfs-lib/src/group/rpath_client.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e142d4069..52dcdd650 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,15 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, + GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7b7fbbbe..60ddba1fb 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,11 +6,11 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; use crate::{ - storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, + NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index b4e753a27..8a43844b2 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,11 +1,9 @@ // dec framework -mod delegate_factory; +mod group_manager; mod rpath_client; mod rpath_control; -mod group_manager; -pub use delegate_factory::*; +pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 7abff1ec1..c3a25b060 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,10 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathDelegate, + PendingProposalHandler, PendingProposalMgr, }; struct RPathControlRaw { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 8b8799207..adf11c7e4 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,11 +6,11 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_lib::GroupObjectMapProcessor; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, - GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, - GROUP_STATE_PATH_RESULT_STATE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 966fa518a..fa6f4930f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,11 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-lib/src/group/delegate_factory.rs similarity index 98% rename from src/component/cyfs-group/src/dec/delegate_factory.rs rename to src/component/cyfs-lib/src/group/delegate_factory.rs index f5092dbfc..9e55ff8f4 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-lib/src/group/delegate_factory.rs @@ -1,8 +1,8 @@ +use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-lib/src/group/group_manager.rs new file mode 100644 index 000000000..7d836ae49 --- /dev/null +++ b/src/component/cyfs-lib/src/group/group_manager.rs @@ -0,0 +1,20 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +use crate::{DelegateFactory, RPathClient}; + +#[derive(Clone)] +pub struct GroupManager; + +impl GroupManager { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self) { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-lib/src/group/mod.rs new file mode 100644 index 000000000..482d9ea0d --- /dev/null +++ b/src/component/cyfs-lib/src/group/mod.rs @@ -0,0 +1,7 @@ +mod delegate_factory; +mod group_manager; +mod rpath_client; + +pub use delegate_factory::*; +pub use group_manager::*; +pub use rpath_client::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-lib/src/group/rpath_client.rs new file mode 100644 index 000000000..4162abe68 --- /dev/null +++ b/src/component/cyfs-lib/src/group/rpath_client.rs @@ -0,0 +1,27 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{GroupProposal, GroupRPath}; + +use crate::NONObjectInfo; + +struct RPathClientRaw {} + +#[derive(Clone)] +pub struct RPathClient(Arc); + +impl RPathClient { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index f74e62985..d2f02315a 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,9 +4,11 @@ mod base; mod crypto; mod default_app; mod events; +mod group; mod ndn; mod non; mod prelude; +mod requestor; mod rmeta; mod root_state; mod router_handler; @@ -17,7 +19,6 @@ mod trans; mod util; mod ws; mod zone; -mod requestor; pub use crate::util::*; pub use acl::*; @@ -26,9 +27,11 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; +pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; +pub use requestor::*; pub use rmeta::*; pub use root_state::*; pub use router_handler::*; @@ -38,7 +41,6 @@ pub use sync::*; pub use trans::*; pub use ws::*; pub use zone::*; -pub use requestor::*; // 重新导出cache相关接口,由于bdt层的依赖关系,只能放在util工程 pub use cyfs_util::cache::*; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ef2366de0..42544e51c 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,12 +505,10 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, - }; + use cyfs_group::RPathControl; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, + NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, }; use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; From 084fd8058224c2e35ad5219ef399d6ca5728e031 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 12:20:30 +0800 Subject: [PATCH 270/553] Remove the `decide` from proposal, It seems unuseful --- .../cyfs-core/protos/core_objects.proto | 9 +- .../cyfs-core/src/group/group_proposal.rs | 415 +++++++++--------- src/component/cyfs-core/src/group/mod.rs | 10 +- 3 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 487ece4bd..abd299e9d 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -352,7 +352,7 @@ message GroupProposalDescContent { message GroupProposalBodyContent { optional bytes payload = 1; - +/* message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; @@ -360,8 +360,10 @@ message GroupProposalBodyContent { } repeated Signature decide_signatures = 2; +*/ } +/* message GroupUpdateGroupPropsalParam { repeated bytes target_dec_id = 1; // the proccesor decs optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) @@ -373,6 +375,7 @@ message GroupPropsalDecideParam { bytes proposal_id = 2; bytes decide = 3; } +*/ message HotstuffBlockQc { bytes block_id = 1; @@ -431,6 +434,7 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } +/* message GroupActionDescContent { // target GroupRPath r_path = 1; @@ -441,4 +445,5 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 10aeed798..bf28aafb2 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,4 +1,4 @@ -use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; +use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use sha2::Digest; @@ -34,45 +34,44 @@ impl DescContent for GroupProposalDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone)] -pub struct GroupProposalSignature { - signature: Signature, - proponent_id: ObjectId, - decide: Vec, -} - -impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> - for GroupProposalSignature -{ - fn transform( - value: &crate::codec::protos::group_proposal_body_content::Signature, - ) -> BuckyResult { - Ok(Self { - signature: Signature::raw_decode(value.signature.as_slice())?.0, - proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, - decide: value.decide.clone(), - }) - } -} - -impl ProtobufTransform<&GroupProposalSignature> - for crate::codec::protos::group_proposal_body_content::Signature -{ - fn transform(value: &GroupProposalSignature) -> BuckyResult { - Ok(Self { - signature: value.signature.to_vec()?, - proponent_id: value.proponent_id.to_vec()?, - decide: value.decide.clone(), - }) - } -} +// #[derive(Clone)] +// pub struct GroupProposalSignature { +// signature: Signature, +// proponent_id: ObjectId, +// decide: Vec, +// } + +// impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> +// for GroupProposalSignature +// { +// fn transform( +// value: &crate::codec::protos::group_proposal_body_content::Signature, +// ) -> BuckyResult { +// Ok(Self { +// signature: Signature::raw_decode(value.signature.as_slice())?.0, +// proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, +// decide: value.decide.clone(), +// }) +// } +// } + +// impl ProtobufTransform<&GroupProposalSignature> +// for crate::codec::protos::group_proposal_body_content::Signature +// { +// fn transform(value: &GroupProposalSignature) -> BuckyResult { +// Ok(Self { +// signature: value.signature.to_vec()?, +// proponent_id: value.proponent_id.to_vec()?, +// decide: value.decide.clone(), +// }) +// } +// } #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] pub struct GroupProposalBodyContent { payload: Option>, - - decide_signatures: Vec, + // decide_signatures: Vec, } impl BodyContent for GroupProposalBodyContent { @@ -85,14 +84,14 @@ impl ProtobufTransform for GroupProposalBodyContent { fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push(GroupProposalSignature::transform(sign)?); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push(GroupProposalSignature::transform(sign)?); + // } Ok(Self { payload: value.payload, - decide_signatures, + // decide_signatures, }) } } @@ -101,16 +100,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> for crate::codec::protos::GroupProposalBodyContent { fn transform(value: &GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push( - crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, - ); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push( + // crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + // ); + // } Ok(Self { payload: value.payload.clone(), - decide_signatures, + // decide_signatures, }) } } @@ -143,17 +142,17 @@ impl GroupProposalDescContent { } impl GroupProposalBodyContent { - fn hash_decide_signature( - proposal_id: &ObjectId, - proponent_id: &ObjectId, - decide: &[u8], - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(proposal_id.as_slice()); - sha256.input(proponent_id.as_slice()); - sha256.input(decide); - sha256.result().into() - } + // fn hash_decide_signature( + // proposal_id: &ObjectId, + // proponent_id: &ObjectId, + // decide: &[u8], + // ) -> HashValue { + // let mut sha256 = sha2::Sha256::new(); + // sha256.input(proposal_id.as_slice()); + // sha256.input(proponent_id.as_slice()); + // sha256.input(decide); + // sha256.result().into() + // } } #[async_trait] @@ -182,27 +181,27 @@ pub trait GroupProposalObject { fn payload(&self) -> &Option>; fn set_payload(&mut self, payload: Option>); - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult>; - - fn decided_members_no_verify(&self) -> &Vec; - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult; - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()>; + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult>; + + // fn decided_members_no_verify(&self) -> &Vec; + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult; + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()>; } #[async_trait] @@ -231,7 +230,7 @@ impl GroupProposalObject for GroupProposal { desc, GroupProposalBodyContent { payload, - decide_signatures: vec![], + // decide_signatures: vec![], }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) @@ -252,9 +251,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { - Some(params) => { - HashValue::try_from(params.as_slice()).map(|h| Some(h)) - } + Some(params) => HashValue::try_from(params.as_slice()).map(|h| Some(h)), None => Ok(None), } } @@ -298,134 +295,130 @@ impl GroupProposalObject for GroupProposal { self.body_mut().as_mut().unwrap().content_mut().payload = payload; } - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult> { - let signs = self - .body() - .as_ref() - .unwrap() - .content() - .decide_signatures - .as_slice(); - - let proposal_id = self.desc().object_id(); - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - - let mut decides = vec![]; - - for sign in signs { - if &sign.proponent_id == member_id { - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &sign.proponent_id, - sign.decide.as_slice(), - ); - - if verifier.verify(hash.as_slice(), &sign.signature).await { - decides.push(sign.decide.as_slice()); - } else { - return Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )); - } - } - } - - Ok(decides) - } - - fn decided_members_no_verify(&self) -> &Vec { - &self.body().as_ref().unwrap().content().decide_signatures - } - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult { - let signs = &self.body().as_ref().unwrap().content().decide_signatures; - - if signs.iter().find(|s| s.proponent_id == member_id).is_some() { - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicated decide", - )); - } - - let proposal_id = self.desc().object_id(); - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.as_slice(), - ); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - let sign = signer - .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) - .await?; - - Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) - } - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()> { - let proposal_id = self.desc().object_id(); - - if decide.proposal_id() != &proposal_id { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - format!( - "proposal id not match for decide signature: {}/{}", - proposal_id, - decide.proposal_id() - ), - )); - } - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.decide(), - ); - - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - if verifier.verify(hash.as_slice(), decide.signature()).await { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - for exist in signs.iter() { - if &exist.proponent_id == &member_id && exist.decide == decide.decide() { - return Ok(()); - } - } - - signs.push(GroupProposalSignature { - signature: decide.signature().clone(), - proponent_id: member_id, - decide: Vec::from(decide.decide()), - }); - - Ok(()) - } else { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )) - } - } + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult> { + // let signs = self + // .body() + // .as_ref() + // .unwrap() + // .content() + // .decide_signatures + // .as_slice(); + + // let proposal_id = self.desc().object_id(); + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + // let mut decides = vec![]; + + // for sign in signs { + // if &sign.proponent_id == member_id { + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &sign.proponent_id, + // sign.decide.as_slice(), + // ); + + // if verifier.verify(hash.as_slice(), &sign.signature).await { + // decides.push(sign.decide.as_slice()); + // } else { + // return Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )); + // } + // } + // } + + // Ok(decides) + // } + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult { + // let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + // if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + // return Err(BuckyError::new( + // BuckyErrorCode::AlreadyExists, + // "duplicated decide", + // )); + // } + + // let proposal_id = self.desc().object_id(); + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.as_slice(), + // ); + + // let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + // let sign = signer + // .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + // .await?; + + // Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) + // } + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()> { + // let proposal_id = self.desc().object_id(); + + // if decide.proposal_id() != &proposal_id { + // return Err(BuckyError::new( + // BuckyErrorCode::NotMatch, + // format!( + // "proposal id not match for decide signature: {}/{}", + // proposal_id, + // decide.proposal_id() + // ), + // )); + // } + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.decide(), + // ); + + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + // if verifier.verify(hash.as_slice(), decide.signature()).await { + // let signs = &mut self + // .body_mut() + // .as_mut() + // .unwrap() + // .content_mut() + // .decide_signatures; + // for exist in signs.iter() { + // if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + // return Ok(()); + // } + // } + + // signs.push(GroupProposalSignature { + // signature: decide.signature().clone(), + // proponent_id: member_id, + // decide: Vec::from(decide.decide()), + // }); + + // Ok(()) + // } else { + // Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )) + // } + // } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b2885d637..4310f48a5 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,13 +1,15 @@ mod group_consensus_block; mod group_proposal; -mod group_proposal_decide_param; +// mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_update_group_proposal_param; +// mod group_update_group_proposal_param; +mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; -pub use group_proposal_decide_param::*; +// pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_update_group_proposal_param::*; +// pub use group_update_group_proposal_param::*; +pub use group_protocol::*; From 44f3333c7697a67000a7d13177c755d824cb349c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 20:52:45 +0800 Subject: [PATCH 271/553] Prepare for export interface to SDK --- .../cyfs-core/protos/core_objects.proto | 2 +- src/component/cyfs-core/src/coreobj.rs | 1 + src/component/cyfs-core/src/group/mod.rs | 2 - src/component/cyfs-group-lib/Cargo.toml | 34 ++ .../{cyfs-group => cyfs-group-lib}/build.rs | 27 +- .../protos/group_bft_protocol.proto | 63 +++ src/component/cyfs-group-lib/readme.md | 14 + .../src/delegate.rs} | 18 +- .../src}/group_manager.rs | 6 +- .../mod.rs => cyfs-group-lib/src/lib.rs} | 6 +- .../cyfs-group-lib/src/objects/certificate.rs | 190 ++++++++ .../cyfs-group-lib/src/objects/codec/mod.rs | 3 + .../src/objects/group_command.rs | 428 ++++++++++++++++++ .../src/objects/group_decide_proposal.rs | 0 .../src/objects/group_rpath_status.rs | 6 +- .../src/objects/group_update_proposal.rs | 0 .../cyfs-group-lib/src/objects/mod.rs | 12 + .../src}/rpath_client.rs | 3 +- src/component/cyfs-group/Cargo.toml | 3 +- .../protos/group_bft_protocol.proto | 23 - .../src/consensus/hotstuff/hotstuff.rs | 60 +-- .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 7 +- .../cyfs-group/src/dec/group_events.rs | 42 ++ .../cyfs-group/src/dec/group_manager.rs | 94 ++-- src/component/cyfs-group/src/dec/mod.rs | 2 + .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec/rpath_control.rs | 8 +- .../src/dec_state/dec_state_requestor.rs | 6 +- .../src/dec_state/dec_state_synchronizer.rs | 64 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/helper/mod.rs | 2 - src/component/cyfs-group/src/helper/verify.rs | 16 - src/component/cyfs-group/src/lib.rs | 4 - src/component/cyfs-group/src/network/mod.rs | 2 + .../src/{objects => network}/protocol.rs | 306 +++---------- src/component/cyfs-group/src/objects/mod.rs | 9 - .../cyfs-group/src/storage/dec_storage.rs | 9 +- .../engine/storage_engine_group_state.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 7 +- src/component/cyfs-group/src/utils.rs | 8 - src/component/cyfs-lib/src/lib.rs | 2 - 42 files changed, 977 insertions(+), 529 deletions(-) create mode 100644 src/component/cyfs-group-lib/Cargo.toml rename src/component/{cyfs-group => cyfs-group-lib}/build.rs (66%) create mode 100644 src/component/cyfs-group-lib/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group-lib/readme.md rename src/component/{cyfs-lib/src/group/delegate_factory.rs => cyfs-group-lib/src/delegate.rs} (81%) rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/group_manager.rs (100%) rename src/component/{cyfs-lib/src/group/mod.rs => cyfs-group-lib/src/lib.rs} (56%) create mode 100644 src/component/cyfs-group-lib/src/objects/certificate.rs create mode 100644 src/component/cyfs-group-lib/src/objects/codec/mod.rs create mode 100644 src/component/cyfs-group-lib/src/objects/group_command.rs rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_decide_proposal.rs (100%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_rpath_status.rs (93%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_update_proposal.rs (100%) create mode 100644 src/component/cyfs-group-lib/src/objects/mod.rs rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/rpath_client.rs (94%) delete mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group/src/dec/group_events.rs delete mode 100644 src/component/cyfs-group/src/helper/verify.rs rename src/component/cyfs-group/src/{objects => network}/protocol.rs (70%) delete mode 100644 src/component/cyfs-group/src/objects/mod.rs delete mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index abd299e9d..742c14904 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -446,4 +446,4 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; } -*/ \ No newline at end of file +*/ diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3d53a082f..8eb96a930 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupAction = 704, GroupQuorumCertificate = 705, + GroupCommand = 706, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4310f48a5..d7134a3c0 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,7 +4,6 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; @@ -12,4 +11,3 @@ pub use group_proposal::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; -pub use group_protocol::*; diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml new file mode 100644 index 000000000..e7cfda851 --- /dev/null +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -0,0 +1,34 @@ + +[package] +name = 'cyfs-group-lib' +version = '0.1.1' +authors = ['zhangzhen '] +edition = '2021' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +prost-build = { version = '0.9.0' } +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +itertools = "0.10.3" +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group-lib/build.rs similarity index 66% rename from src/component/cyfs-group/build.rs rename to src/component/cyfs-group-lib/build.rs index 8d4efe9c9..206d6bc6f 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group-lib/build.rs @@ -37,28 +37,13 @@ fn gen_protos() { } fn main() { - println!("cargo:rerun-if-env-changed=VERSION"); - println!("cargo:rerun-if-env-changed=CHANNEL"); - println!("cargo:rerun-if-env-changed=TARGET"); - println!( - "cargo:rustc-env=VERSION={}", - std::env::var("VERSION").unwrap_or("0".to_owned()) - ); - println!( - "cargo:rustc-env=CHANNEL={}", - std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) - ); - println!( - "cargo:rustc-env=TARGET={}", - std::env::var("TARGET").unwrap() - ); - + println!("cargo:rerun-if-changed=protos"); println!( - "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + "cargo:warning={}", + format!( + "cyfs-core run build script, OUT_DIR={}", + std::env::var("OUT_DIR").unwrap() + ) ); - - println!("cargo:rerun-if-changed=protos"); - gen_protos(); } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto new file mode 100644 index 000000000..2bfdd8d21 --- /dev/null +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -0,0 +1,63 @@ + +syntax = "proto3"; + +message HotstuffBlockQCVote { + bytes block_id = 1; + optional bytes prev_block_id = 2; + uint64 round = 3; + bytes voter = 4; + bytes signature = 5; +} + +message HotstuffTimeoutVote { + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; +} + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} + +// GroupCommand + +message GroupCommandDescContent { + +} + +message GroupCommandNewRPath { + bytes group_id = 1; + string rpath = 2; + optional bytes with_block = 3; // Block.to_vec() +} + +message GroupCommandExecute { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId +} + +message GroupCommandExecuteResult { + optional bytes result_state_id = 1; // ObjectId + optional bytes receipt = 2; // NONObjectInfo.to_vec() + optional bytes context = 3; // Vec +} + +message GroupCommandVerify { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec +} + +message GroupCommandCommited { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec + bytes block = 6; // Block.to_vec() +} diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group-lib/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-lib/src/group/delegate_factory.rs b/src/component/cyfs-group-lib/src/delegate.rs similarity index 81% rename from src/component/cyfs-lib/src/group/delegate_factory.rs rename to src/component/cyfs-group-lib/src/delegate.rs index 9e55ff8f4..21b1e6346 100644 --- a/src/component/cyfs-lib/src/group/delegate_factory.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,25 +1,17 @@ -use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult>; - - async fn on_state_changed( &self, group_id: &ObjectId, rpath: &str, - state_id: Option, - pre_state_id: Option, - ); + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()>; } pub struct ExecuteResult { @@ -30,8 +22,6 @@ pub struct ExecuteResult { #[async_trait::async_trait] pub trait RPathDelegate: Sync + Send { - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; - async fn on_execute( &self, proposal: &GroupProposal, @@ -45,7 +35,7 @@ pub trait RPathDelegate: Sync + Send { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult; + ) -> BuckyResult<()>; async fn on_commited( &self, diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs similarity index 100% rename from src/component/cyfs-lib/src/group/group_manager.rs rename to src/component/cyfs-group-lib/src/group_manager.rs index 7d836ae49..8c82bc9e1 100644 --- a/src/component/cyfs-lib/src/group/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -6,15 +6,15 @@ use crate::{DelegateFactory, RPathClient}; pub struct GroupManager; impl GroupManager { - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { unimplemented!() } - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn unregister(&self) { unimplemented!() } } diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-group-lib/src/lib.rs similarity index 56% rename from src/component/cyfs-lib/src/group/mod.rs rename to src/component/cyfs-group-lib/src/lib.rs index 482d9ea0d..199307bcc 100644 --- a/src/component/cyfs-lib/src/group/mod.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,7 +1,9 @@ -mod delegate_factory; +mod delegate; mod group_manager; +mod objects; mod rpath_client; -pub use delegate_factory::*; +pub use delegate::*; pub use group_manager::*; +pub use objects::*; pub use rpath_client::*; diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs new file mode 100644 index 000000000..32b1b53c8 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -0,0 +1,190 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, HashValue, ObjectId, ObjectLink, ProtobufDecode, + ProtobufEncode, ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, + RawEncodePurpose, RsaCPUObjectSigner, Signature, SignatureSource, Signer, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffBlockQcVote)] +pub struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub prev_block_id: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.block_id().object_id(); + let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let signature = signer + .sign( + hash.as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + block_id: block_id.clone(), + round, + voter: local_device_id, + signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) + } + + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: super::codec::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for super::codec::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffTimeoutVote)] +pub struct HotstuffTimeoutVote { + pub high_qc: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: Option, + round: u64, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_device_id, + signature, + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + } + + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: super::codec::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffTimeoutVote { + high_qc: match value.high_qc.as_ref() { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} diff --git a/src/component/cyfs-group-lib/src/objects/codec/mod.rs b/src/component/cyfs-group-lib/src/objects/codec/mod.rs new file mode 100644 index 000000000..66df9053f --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/codec/mod.rs @@ -0,0 +1,3 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs new file mode 100644 index 000000000..912ced438 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -0,0 +1,428 @@ +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, NamedObjType, NamedObject, + NamedObjectBase, NamedObjectBuilder, NamedObjectId, ObjectId, ProtobufDecode, ProtobufEncode, + ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, RawEncode, RawEncodePurpose, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, +}; + +use cyfs_core::{CoreObjectType, GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandDescContent)] +pub struct GroupCommandDescContent {} + +impl DescContent for GroupCommandDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupCommand as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupCommandDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Debug)] +pub enum GroupCommandType { + NewRPath, + Execute, + ExecuteResult, + Verify, + Commited, +} + +#[derive(Clone, RawEncode, RawDecode)] +pub enum GroupCommandBodyContent { + NewRPath(GroupCommandNewRPath), + Execute(GroupCommandExecute), + ExecuteResult(GroupCommandExecuteResult), + Verify(GroupCommandVerify), + Commited(GroupCommandCommited), +} + +pub type GroupCommandObjectType = NamedObjType; +pub type GroupCommandBuilder = NamedObjectBuilder; + +pub type GroupCommandId = NamedObjectId; +pub type GroupCommand = NamedObjectBase; + +impl GroupCommandBodyContent { + pub fn cmd_type(&self) -> GroupCommandType { + match self { + GroupCommandBodyContent::NewRPath(_) => GroupCommandType::NewRPath, + GroupCommandBodyContent::Execute(_) => GroupCommandType::Execute, + GroupCommandBodyContent::ExecuteResult(_) => GroupCommandType::ExecuteResult, + GroupCommandBodyContent::Verify(_) => GroupCommandType::Verify, + GroupCommandBodyContent::Commited(_) => GroupCommandType::Commited, + } + } +} + +pub trait GroupCommandObject { + fn cmd_type(&self) -> GroupCommandType; + fn into_cmd(self) -> GroupCommandBodyContent; +} + +impl GroupCommandObject for GroupCommand { + fn cmd_type(&self) -> GroupCommandType { + self.body().as_ref().unwrap().content().cmd_type() + } + + fn into_cmd(self) -> GroupCommandBodyContent { + self.into_body().unwrap().into_content() + } +} + +impl BodyContent for GroupCommandBodyContent { + fn version(&self) -> u8 { + 0 + } + + fn format(&self) -> u8 { + cyfs_base::OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupCommandBodyContent") + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandNewRPath)] +pub struct GroupCommandNewRPath { + pub group_id: ObjectId, + pub rpath: String, + pub with_block: Option, +} + +impl ProtobufTransform for GroupCommandNewRPath { + fn transform(value: super::codec::protos::GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: ObjectId::raw_decode(value.group_id.as_slice())?.0, + with_block: match value.with_block.as_ref() { + Some(buf) => Some(GroupConsensusBlock::raw_decode(buf.as_slice())?.0), + None => None, + }, + rpath: value.rpath, + }) + } +} + +impl ProtobufTransform<&GroupCommandNewRPath> for super::codec::protos::GroupCommandNewRPath { + fn transform(value: &GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: value.group_id.to_vec()?, + rpath: value.rpath.clone(), + with_block: match value.with_block.as_ref() { + Some(block) => Some(block.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecute)] +pub struct GroupCommandExecute { + pub proposal: GroupProposal, + pub prev_state_id: Option, +} + +impl ProtobufTransform for GroupCommandExecute { + fn transform(value: super::codec::protos::GroupCommandExecute) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecute> for super::codec::protos::GroupCommandExecute { + fn transform(value: &GroupCommandExecute) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecuteResult)] +pub struct GroupCommandExecuteResult { + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform + for GroupCommandExecuteResult +{ + fn transform(value: super::codec::protos::GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecuteResult> + for super::codec::protos::GroupCommandExecuteResult +{ + fn transform(value: &GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandVerify)] +pub struct GroupCommandVerify { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform for GroupCommandVerify { + fn transform(value: super::codec::protos::GroupCommandVerify) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + receipt: match value.receipt { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupCommandVerify { + fn transform(value: &GroupCommandVerify) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] +pub struct GroupCommandCommited { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, + pub block: GroupConsensusBlock, +} + +impl ProtobufTransform for GroupCommandCommited { + fn transform(value: super::codec::protos::GroupCommandCommited) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, + }, + block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { + fn transform(value: &GroupCommandCommited) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + block: value.block.to_vec()?, + }) + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandNewRPath) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::NewRPath(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecute) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Execute(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecuteResult) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::ExecuteResult(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandVerify) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Verify(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandCommited) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Commited(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::NewRPath(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect NewRPath", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Execute(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Execute", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::ExecuteResult(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect ExecuteResult", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Verify(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Verify", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Commited(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Commited", cmd_type), + )), + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_decide_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs similarity index 93% rename from src/component/cyfs-group/src/objects/group_rpath_status.rs rename to src/component/cyfs-group-lib/src/objects/group_rpath_status.rs index bfc9bc5d2..ae656b5ad 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs @@ -21,7 +21,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -42,7 +42,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -56,7 +56,7 @@ impl RawEncode for GroupRPathStatus { impl<'de> RawDecode<'de> for GroupRPathStatus { fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let proto = super::codec::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::Failed, msg) diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_update_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_update_proposal.rs diff --git a/src/component/cyfs-group-lib/src/objects/mod.rs b/src/component/cyfs-group-lib/src/objects/mod.rs new file mode 100644 index 000000000..668afe8cf --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/mod.rs @@ -0,0 +1,12 @@ +mod group_command; +// mod group_decide_proposal; +mod group_rpath_status; +// mod group_update_proposal; +mod certificate; +mod codec; + +pub use group_command::*; +// pub use group_decide_proposal::*; +pub use group_rpath_status::*; +// pub use group_update_proposal::*; +pub use certificate::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs similarity index 94% rename from src/component/cyfs-lib/src/group/rpath_client.rs rename to src/component/cyfs-group-lib/src/rpath_client.rs index 4162abe68..2fea6dcf7 100644 --- a/src/component/cyfs-lib/src/group/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -5,8 +5,7 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupProposal, GroupRPath}; - -use crate::NONObjectInfo; +use cyfs_lib::NONObjectInfo; struct RPathClientRaw {} diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 4a7aae6c2..1caf5b9a4 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,5 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto deleted file mode 100644 index 621186522..000000000 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ /dev/null @@ -1,23 +0,0 @@ - -syntax = "proto3"; - -message HotstuffBlockQCVote { - bytes block_id = 1; - optional bytes prev_block_id = 2; - uint64 round = 3; - bytes voter = 4; - bytes signature = 5; -} - -message HotstuffTimeoutVote { - optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) - uint64 round = 2; - bytes voter = 3; - bytes signature = 4; -} - -message GroupRPathStatus { - bytes block_desc = 1; // GroupConsensusBlockDescContent - bytes certificate = 2; // HotstuffBlockQC for block - repeated bytes status_list = 4; // Array> -} \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52dcdd650..cc555298b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,16 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; +use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, }; /** @@ -51,7 +52,7 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -81,7 +82,7 @@ impl Hotstuff { rx_message, proposal_consumer, state_pusher_runner, - delegate, + event_notifier, rpath2, ) .run() @@ -224,7 +225,7 @@ struct HotstuffRunner { tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, synchronizer: Synchronizer, rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, @@ -251,7 +252,7 @@ impl HotstuffRunner { rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, state_pusher: StatePusher, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); @@ -307,7 +308,7 @@ impl HotstuffRunner { network_sender, tx_message, rx_message, - delegate, + event_notifier, synchronizer, non_driver, rpath, @@ -511,37 +512,25 @@ impl HotstuffRunner { context: proposal_exe_info.context.clone(), }; - if self - .delegate - .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) + self + .event_notifier + .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); err - })? - { - log::debug!( - "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + })?; - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); - return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); - } + prev_state_id = proposal_exe_info.result_state; } assert_eq!( @@ -840,11 +829,10 @@ impl HotstuffRunner { None => None, }; - self.delegate + self.event_notifier .on_commited( &proposal_obj, pre_state_id, - self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1625,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { + match self.event_notifier.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ad3a21e35..398274723 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -14,9 +14,10 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::network::NONDriverHelper; #[derive(Clone)] pub(crate) struct Committee { diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index f44260a04..6a9735a7f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,13 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, -}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, HotstuffTimeout, HotstuffTimeoutSign, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::Committee; pub(crate) struct VoteMgr { committee: Committee, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs new file mode 100644 index 000000000..67f79cfdd --- /dev/null +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -0,0 +1,42 @@ +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_group_lib::ExecuteResult; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone)] +pub(crate) struct RPathEventNotifier {} + +impl RPathEventNotifier { + pub fn new() -> Self { + unimplemented!() + } + + pub async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 60ddba1fb..95bdbcd17 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,15 +2,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, - NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, + RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -22,7 +22,6 @@ type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - delegate_by_dec: HashMap>, control_by_group: ControlByGroup, client_by_group: ClientByGroup, } @@ -33,6 +32,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,12 +54,12 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { control_by_group: ControlByGroup::default(), client_by_group: ClientByGroup::default(), - delegate_by_dec: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -69,29 +69,12 @@ impl GroupManager { Ok(mgr) } - pub async fn register( - &self, - dec_id: DecAppId, - delegate_factory: Box, - ) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec - .insert(dec_id.object_id().clone(), delegate_factory); - Ok(()) - } - - pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec.remove(dec_id.object_id()); - Ok(()) - } - pub async fn find_rpath_control( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -204,7 +187,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, Some(&block), Some(&remote), ) @@ -220,7 +203,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -236,7 +219,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -252,7 +235,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -268,7 +251,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -284,7 +267,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -331,7 +314,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::No, + false, None, Some(&remote), ) @@ -378,7 +361,7 @@ impl GroupManager { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -398,7 +381,6 @@ impl GroupManager { { // write - let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); @@ -411,6 +393,7 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -424,40 +407,25 @@ impl GroupManager { let store = match store { Ok(store) => Some(store), Err(e) => { - if let IsCreateRPath::No = is_auto_create { - return Err(e); - } if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - None + + self.on_new_rpath_request(group_id, dec_id, rpath, block) + .await?; + + if !is_auto_create { + return Err(e); + } else { + None + } } else { return Err(e); } } }; - // TODO: query group - let group = non_driver - .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) - .await?; - let mut raw = self.write().await; - let delegate = { - let delegate_factory = raw.delegate_by_dec.get(dec_id); - if delegate_factory.is_none() { - return Err(BuckyError::new( - BuckyErrorCode::DecNotRunning, - "dec not running for the rpath-control", - )); - } - let delegate_factory = delegate_factory.unwrap(); - - delegate_factory - .create_rpath_delegate(&group, rpath, block) - .await? - }; - let store = match store { Some(store) => store, None => { @@ -489,7 +457,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - Arc::new(delegate), + event_notifier, network_sender, non_driver, store, @@ -501,4 +469,14 @@ impl GroupManager { } } } + + async fn on_new_rpath_request( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 8a43844b2..2ad717514 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,9 +1,11 @@ // dec framework +mod group_events; mod group_manager; mod rpath_client; mod rpath_control; +pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 8a1dd34a7..08be0f5a0 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -224,10 +224,10 @@ impl RPathClient { HotstuffMessage::Timeout(tc) => unreachable!(), HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), HotstuffMessage::LastStateRequest => unreachable!(), - HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffMessage::StateChangeNotify(header_block, qc) => { self.0 .state_sync - .on_state_change(header_block, qc_block, remote) + .on_state_change(header_block, qc, remote) .await } HotstuffMessage::ProposalResult(proposal_id, result) => { diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c3a25b060..593d82db4 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::RPathDelegate; +use cyfs_group_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, + PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; struct RPathControlRaw { @@ -26,7 +26,7 @@ impl RPathControl { local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, - delegate: Arc>, + event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, store: GroupStorage, @@ -46,7 +46,7 @@ impl RPathControl { network_sender.clone(), non_driver, pending_proposal_consumer, - delegate, + event_notifier, rpath.clone(), ); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 790429c6c..8fd67496b 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,13 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, - CHANNEL_CAPACITY, -}; +use crate::{storage::DecStorage, Committee, HotstuffMessage, CHANNEL_CAPACITY}; use super::{CallReplyNotifier, CallReplyWaiter}; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 7272b3882..e019db892 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -2,15 +2,12 @@ use std::{collections::HashSet, sync::Arc}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, -}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, Committee, CHANNEL_CAPACITY, @@ -21,13 +18,9 @@ use super::{CallReplyNotifier, CallReplyWaiter}; enum DecStateSynchronizerMessage { ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, ), - StateChange(GroupConsensusBlock, GroupConsensusBlock), + StateChange(GroupConsensusBlock, HotstuffBlockQC), DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } @@ -81,11 +74,7 @@ impl DecStateSynchronizer { pub async fn on_proposal_complete( &self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { self.0 @@ -100,13 +89,13 @@ impl DecStateSynchronizer { pub async fn on_state_change( &self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { self.0 .tx_dec_state_sync_message .send(( - DecStateSynchronizerMessage::StateChange(header_block, qc_block), + DecStateSynchronizerMessage::StateChange(header_block, qc), remote, )) .await; @@ -121,7 +110,7 @@ struct DecStateSynchronizerCache { struct UpdateNotifyInfo { header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remotes: HashSet, group_chunk_id: ObjectId, group: Group, @@ -178,15 +167,11 @@ impl DecStateSynchronizerRunner { async fn handle_proposal_complete( &mut self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { match result { - Ok((result, header_block, qc_block)) => { + Ok((result, header_block, qc)) => { if header_block .proposals() .iter() @@ -200,7 +185,7 @@ impl DecStateSynchronizerRunner { } if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_err() { @@ -226,11 +211,11 @@ impl DecStateSynchronizerRunner { async fn handle_state_change( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_ok() { @@ -251,11 +236,7 @@ impl DecStateSynchronizerRunner { for remote in notify_info.remotes.iter() { match self .store - .sync( - ¬ify_info.header_block, - ¬ify_info.qc_block, - remote.clone(), - ) + .sync(¬ify_info.header_block, ¬ify_info.qc, remote.clone()) .await { Ok(_) => { @@ -264,7 +245,7 @@ impl DecStateSynchronizerRunner { state_cache: DecStorageCache { state: notify_info.header_block.result_state_id().clone(), header_block: notify_info.header_block.clone(), - qc_block: notify_info.qc_block.clone(), + qc: notify_info.qc.clone(), }, group_chunk_id: notify_info.group_chunk_id, group: notify_info.group.clone(), @@ -316,14 +297,9 @@ impl DecStateSynchronizerRunner { async fn push_update_notify( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { - if qc_block.qc().is_none() { - log::warn!("the qc is none for qc-block({})", qc_block.block_id()); - return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); - } - if let Some(notify) = self.update_notifies.as_mut() { match notify.header_block.height().cmp(&header_block.height()) { std::cmp::Ordering::Less => {} @@ -338,11 +314,7 @@ impl DecStateSynchronizerRunner { if header_block.check() && self .committee - .verify_block_desc_with_qc( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - remote, - ) + .verify_block_desc_with_qc(header_block.named_object().desc(), &qc, remote) .await .is_ok() { @@ -354,7 +326,7 @@ impl DecStateSynchronizerRunner { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, - qc_block: qc_block, + qc: qc, remotes: HashSet::from([remote]), group_chunk_id, group, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b1506a192..571c1ca13 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -194,7 +194,11 @@ impl StateChanggeRunner { .post_message( HotstuffMessage::ProposalResult( exe_info.proposal, - Ok((receipt, block.clone(), qc_block.clone())), + Ok(( + receipt, + block.clone(), + qc_block.qc().as_ref().unwrap().clone(), + )), ), rpath.clone(), &proposer, @@ -320,7 +324,7 @@ impl StateChanggeRunner { let msg = HotstuffMessage::StateChangeNotify( progress.header_block.clone(), - progress.qc_block.clone(), + progress.qc_block.qc().as_ref().unwrap().clone(), ); if notify_targets.len() > 0 { diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index ce36043a3..4d3f1b1c6 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,5 +1,3 @@ mod timer; -mod verify; pub use timer::*; -pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs deleted file mode 100644 index ef3e34495..000000000 --- a/src/component/cyfs-group/src/helper/verify.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, -}; - -use crate::GroupRPathStatus; - -pub async fn verify_rpath_value( - value: &GroupRPathStatus, - sub_path: &str, - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - unimplemented!() -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index ba8e83569..c493f13c5 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -4,10 +4,8 @@ mod dec; mod dec_state; mod helper; mod network; -mod objects; mod statepath; mod storage; -mod utils; pub use consensus::*; pub use constant::*; @@ -15,7 +13,5 @@ pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; pub use network::*; -pub use objects::*; pub use statepath::*; pub(crate) use storage::*; -pub use utils::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index f79e67dd4..096bd0950 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,7 +1,9 @@ mod listener; mod non_driver; +mod protocol; mod sender; pub(crate) use listener::*; pub use non_driver::*; +pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs similarity index 70% rename from src/component/cyfs-group/src/objects/protocol.rs rename to src/component/cyfs-group/src/network/protocol.rs index 932e5cd46..7e32fdc4d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -1,16 +1,8 @@ -pub mod protos { - include!(concat!(env!("OUT_DIR"), "/mod.rs")); -} - use cyfs_base::*; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_group_lib::{GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; use itertools::Itertools; -use sha2::Digest; - -use crate::GroupRPathStatus; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { @@ -96,15 +88,11 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, - ), // (proposal-id, (ExecuteResult, block, qc-block)) + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, + ), // (proposal-id, (ExecuteResult, block, qc)) QueryState(String), VerifiableState(String, BuckyResult), } @@ -151,8 +139,8 @@ impl std::fmt::Debug for HotstuffMessage { "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest => { @@ -169,8 +157,8 @@ impl std::fmt::Debug for HotstuffMessage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) }) ) @@ -214,16 +202,12 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) LastStateRequest(ProtocolAddress), ProposalResult( ObjectId, Result< - ( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - ), + (Option, GroupConsensusBlock, HotstuffBlockQC), (BuckyError, ProtocolAddress), >, ), // (proposal-id, ExecuteResult) @@ -276,8 +260,8 @@ impl std::fmt::Debug for HotstuffPackage { "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest(_) => { @@ -296,8 +280,8 @@ impl std::fmt::Debug for HotstuffPackage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ); Ok(ok) } @@ -394,23 +378,25 @@ fn decode_with_length<'de, O: RawDecode<'de>>( impl RawEncode for HotstuffPackage { fn raw_measure(&self, purpose: &Option) -> BuckyResult { let len = match self { - HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::Block(b) => 3 + b.raw_measure(purpose)?, HotstuffPackage::BlockVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::TimeoutVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::Timeout(addr, tc) => { - 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + tc.raw_measure(purpose)? } HotstuffPackage::SyncRequest(addr, min, max) => { - addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + + min.raw_measure(purpose)? + + max.raw_measure(purpose)? } HotstuffPackage::StateChangeNotify(block, qc) => { - 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + 3 + qc.raw_measure(purpose)? } - HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::LastStateRequest(addr) => 2 + addr.raw_measure(purpose)?, HotstuffPackage::ProposalResult(id, result) => { id.raw_measure(purpose)? + match result { @@ -418,22 +404,23 @@ impl RawEncode for HotstuffPackage { non.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + + 3 + block_qc.raw_measure(purpose)? } Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } HotstuffPackage::QueryState(addr, sub_path) => { - addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } HotstuffPackage::VerifiableState(sub_path, result) => { sub_path.raw_measure(purpose)? + match result { - Ok(status) => status.raw_measure(purpose)?, + Ok(status) => 3 + status.raw_measure(purpose)?, Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } @@ -451,43 +438,43 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::Block(b) => { buf[0] = 0; let buf = &mut buf[1..]; - b.raw_encode(buf, purpose) + encode_with_length(buf, b, purpose, 3) } HotstuffPackage::BlockVote(addr, vote) => { buf[0] = 1; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::TimeoutVote(addr, vote) => { buf[0] = 2; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::Timeout(addr, tc) => { buf[0] = 3; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - tc.raw_encode(buf, purpose) + encode_with_length(buf, tc, purpose, 3) } HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; + encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; - let buf = max.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + max.raw_encode(buf, purpose) } HotstuffPackage::StateChangeNotify(block, qc) => { buf[0] = 5; let buf = &mut buf[1..]; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } HotstuffPackage::LastStateRequest(addr) => { buf[0] = 6; let buf = &mut buf[1..]; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; @@ -501,19 +488,19 @@ impl RawEncode for HotstuffPackage { Ok((non, block, qc)) => { let buf = non.raw_encode(buf, purpose)?; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } HotstuffPackage::QueryState(addr, sub_path) => { buf[0] = 8; let buf = &mut buf[1..]; - let buf = sub_path.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2)?; + sub_path.raw_encode(buf, purpose) } HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; @@ -523,10 +510,10 @@ impl RawEncode for HotstuffPackage { let buf = &mut buf[1..]; let buf = sub_path.raw_encode(buf, purpose)?; match result { - Ok(status) => status.raw_encode(buf, purpose), + Ok(status) => encode_with_length(buf, status, purpose, 3), Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } @@ -542,49 +529,49 @@ impl<'de> RawDecode<'de> for HotstuffPackage { match pkg_type { 0 => { let buf = &buf[1..]; - let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (b, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } @@ -596,7 +583,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { true => { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), @@ -605,7 +592,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } @@ -613,8 +600,8 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } 8 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } @@ -624,13 +611,13 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (sub_path, buf) = String::raw_decode(buf)?; match is_ok { true => { - let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + let (status, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), @@ -698,188 +685,5 @@ impl ProtocolAddress { } } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] -pub(crate) struct HotstuffBlockQCVote { - pub block_id: ObjectId, - pub prev_block_id: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let block_id = block.block_id().object_id(); - let round = block.round(); - - log::debug!( - "[block vote] local: {:?}, vote hash {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let hash = Self::hash_content(block_id, block.prev_block_id(), round); - - log::debug!( - "[block vote] local: {:?}, vote sign {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let signature = signer - .sign( - hash.as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - block_id: block_id.clone(), - round, - voter: local_device_id, - signature, - prev_block_id: block.prev_block_id().map(|id| id.clone()), - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) - } - - fn hash_content( - block_id: &ObjectId, - prev_block_id: Option<&ObjectId>, - round: u64, - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(block_id.as_slice()); - sha256.input(round.to_le_bytes()); - if let Some(prev_block_id) = prev_block_id { - sha256.input(prev_block_id.as_slice()); - } - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffBlockQCVote { - fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, - round: value.round, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), - None => None, - }, - }) - } -} - -impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { - fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { - let ret = crate::protos::HotstuffBlockQcVote { - block_id: value.block_id.to_vec()?, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(id.to_vec()?), - None => None, - }, - }; - - Ok(ret) - } -} - -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] -pub(crate) struct HotstuffTimeoutVote { - pub high_qc: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffTimeoutVote { - pub async fn new( - high_qc: Option, - round: u64, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let signature = signer - .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - high_qc, - round, - voter: local_device_id, - signature, - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) - } - - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(high_qc_round.to_le_bytes()); - sha256.input(round.to_le_bytes()); - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffTimeoutVote { - fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { - let high_qc = if value.high_qc().len() == 0 { - None - } else { - Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) - }; - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - round: value.round, - high_qc, - }) - } -} - -impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { - fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { - let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc.as_ref() { - Some(qc) => Some(qc.to_vec()?), - None => None, - }, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - }; - - Ok(ret) - } -} - #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs deleted file mode 100644 index 5d1a8b13f..000000000 --- a/src/component/cyfs-group/src/objects/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod group_decide_proposal; -mod group_rpath_status; -mod group_update_proposal; -mod protocol; - -pub use group_decide_proposal::*; -pub use group_rpath_status::*; -pub use group_update_proposal::*; -pub use protocol::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 60a45724f..0d937487c 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -5,16 +5,17 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; +use crate::STATE_PATH_SEPARATOR; #[derive(Clone)] pub struct DecStorageCache { pub state: Option, pub header_block: GroupConsensusBlock, - pub qc_block: GroupConsensusBlock, + pub qc: HotstuffBlockQC, } #[derive(Clone)] @@ -42,7 +43,7 @@ impl DecStorage { pub async fn sync( &self, header_block: &GroupConsensusBlock, - qc_block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index adf11c7e4..63158a865 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_lib::GroupObjectMapProcessor; +use cyfs_group_lib::GroupObjectMapProcessor; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index fa6f4930f..a1a681259 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; +use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, + STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs deleted file mode 100644 index 5d005a726..000000000 --- a/src/component/cyfs-group/src/utils.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cyfs_base::ObjectId; - -pub type Round = u64; - -pub enum IsCreateRPath { - No, - Yes, -} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index d2f02315a..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,7 +4,6 @@ mod base; mod crypto; mod default_app; mod events; -mod group; mod ndn; mod non; mod prelude; @@ -27,7 +26,6 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; -pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; From 335ff61762b5674449051ffc868e255365ae9dc5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 12:15:59 +0800 Subject: [PATCH 272/553] Implement the events with post_object --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- .../cyfs-group/src/dec/group_events.rs | 120 +++++++++++++++--- .../cyfs-group/src/dec/group_manager.rs | 50 ++++++-- .../cyfs-group/src/dec/rpath_client.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 19 ++- .../cyfs-stack/src/stack/group_non_driver.rs | 8 +- 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index cc555298b..eaaaed06e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -514,7 +514,7 @@ impl HotstuffRunner { self .event_notifier - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal.clone(), prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -831,14 +831,14 @@ impl HotstuffRunner { self.event_notifier .on_commited( - &proposal_obj, + proposal_obj, pre_state_id, &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, - &new_header, + new_header.clone(), ) .await; @@ -1613,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.event_notifier.on_execute(&proposal, result_state_id).await { + match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 67f79cfdd..fc3d12c63 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,42 +1,132 @@ use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_group_lib::ExecuteResult; +use cyfs_group_lib::{ + ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandVerify, +}; use cyfs_lib::NONObjectInfo; +use crate::NONDriverHelper; + #[derive(Clone)] -pub(crate) struct RPathEventNotifier {} +pub(crate) struct RPathEventNotifier { + non_driver: NONDriverHelper, +} impl RPathEventNotifier { - pub fn new() -> Self { - unimplemented!() + pub fn new(driver: NONDriverHelper) -> Self { + Self { non_driver: driver } } pub async fn on_execute( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, ) -> BuckyResult { - unimplemented!() + let cmd = GroupCommandExecute { + proposal, + prev_state_id, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_some()); + match result.as_ref() { + Some(result) => { + let (cmd, _remain) = GroupCommand::raw_decode(result.object_raw.as_slice())?; + assert_eq!(_remain.len(), 0); + let mut cmd = TryInto::::try_into(cmd)?; + Ok(ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }) + } + None => Err(BuckyError::new( + BuckyErrorCode::Unknown, + "expect some result from dec-app", + )), + } } pub async fn on_verify( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandVerify { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } pub async fn on_commited( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, - block: &GroupConsensusBlock, + block: GroupConsensusBlock, ) { - unimplemented!() + let cmd = GroupCommandCommited { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec().expect( + format!("on_commited {} failed for encode", self.non_driver.dec_id()) + .as_str(), + ), + object: None, + }, + None, + ) + .await + .map_err(|err| log::warn!("on_commited {} failed {:?}", self.non_driver.dec_id(), err)); + + assert!(result.is_err() || result.unwrap().is_none()); } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95bdbcd17..346e75d02 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,11 +2,13 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -32,7 +34,6 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, - event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,7 +55,6 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, - event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { @@ -393,7 +393,6 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -410,8 +409,13 @@ impl GroupManager { if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - self.on_new_rpath_request(group_id, dec_id, rpath, block) - .await?; + self.on_new_rpath_request( + group_id.clone(), + dec_id, + rpath.to_string(), + block.cloned(), + ) + .await?; if !is_auto_create { return Err(e); @@ -457,7 +461,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - event_notifier, + RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, store, @@ -472,11 +476,33 @@ impl GroupManager { async fn on_new_rpath_request( &self, - group_id: &ObjectId, + group_id: ObjectId, dec_id: &ObjectId, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, + rpath: String, + with_block: Option, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandNewRPath { + group_id, + rpath, + with_block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .local_info() + .non_driver + .post_object( + dec_id, + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 08be0f5a0..41db0c25c 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -100,7 +100,7 @@ impl RPathClient { match self .0 .non_driver - .post_object(non_proposal.clone(), ood) + .post_object(non_proposal.clone(), Some(ood)) .await { Ok(r) => post_result = Some(Ok(())), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 979451b79..c7f9e7d93 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, }; @@ -29,8 +29,8 @@ pub trait NONDriver: Send + Sync { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()>; + to: Option<&ObjectId>, + ) -> BuckyResult>; } #[derive(Clone)] @@ -49,6 +49,10 @@ impl NONDriverHelper { } } + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id + } + pub async fn get_object( &self, object_id: &ObjectId, @@ -74,12 +78,17 @@ impl NONDriverHelper { self.driver.put_object(&self.dec_id, obj).await } - pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object( + &self, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { self.driver.post_object(&self.dec_id, obj, to).await } pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { - futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), Some(to)))) + .await; } pub async fn get_block( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fcb0dd6da..f7f305a83 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -88,8 +88,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()> { + to: Option<&ObjectId>, + ) -> BuckyResult> { self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { @@ -107,12 +107,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { level: NONAPILevel::Router, - target: Some(to.clone()), + target: to.cloned(), flags: 0, }, object: obj, }) .await - .map(|_| ()) + .map(|resp| resp.object) } } From 61672a26205ff417b1ae5f70568928df2dba346a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 14:56:29 +0800 Subject: [PATCH 273/553] Rename `control` into `Service` --- .../cyfs-group/src/dec/group_manager.rs | 80 +++++++++---------- src/component/cyfs-group/src/dec/mod.rs | 4 +- .../{rpath_control.rs => rpath_service.rs} | 8 +- src/tests/group-example/src/main.rs | 20 ++--- 4 files changed, 56 insertions(+), 56 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_control.rs => rpath_service.rs} (96%) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 346e75d02..23202fddf 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,19 +12,19 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, + RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, }; -type ControlByRPath = HashMap; -type ControlByDec = HashMap; -type ControlByGroup = HashMap; +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; type ClientByRPath = HashMap; type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - control_by_group: ControlByGroup, + service_by_group: ServiceByGroup, client_by_group: ClientByGroup, } @@ -58,7 +58,7 @@ impl GroupManager { }; let raw = GroupRPathMgrRaw { - control_by_group: ControlByGroup::default(), + service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), }; @@ -69,14 +69,14 @@ impl GroupManager { Ok(mgr) } - pub async fn find_rpath_control( + pub async fn find_rpath_service( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, is_auto_create: bool, - ) -> BuckyResult { - self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + ) -> BuckyResult { + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -155,7 +155,7 @@ impl GroupManager { } // return - pub async fn enum_rpath_control( + pub async fn enum_rpath_service( &self, group_id: &ObjectId, ) -> BuckyResult> { @@ -182,8 +182,8 @@ impl GroupManager { match msg { HotstuffPackage::Block(block) => { let rpath = block.r_path(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -192,14 +192,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Block(block), remote) .await; } HotstuffPackage::BlockVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -208,14 +208,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; } HotstuffPackage::TimeoutVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -224,14 +224,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; } HotstuffPackage::Timeout(target, tc) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -240,14 +240,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Timeout(tc), remote) .await; } HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -256,14 +256,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; } HotstuffPackage::LastStateRequest(target) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -272,7 +272,7 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::LastStateRequest, remote) .await; } @@ -309,8 +309,8 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -320,9 +320,9 @@ impl GroupManager { ) .await; - match control { - Ok(control) => { - control + match service { + Ok(service) => { + service .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } @@ -356,7 +356,7 @@ impl GroupManager { Ok(()) } - async fn find_rpath_control_inner( + async fn find_rpath_service_inner( &self, group_id: &ObjectId, dec_id: &ObjectId, @@ -364,12 +364,12 @@ impl GroupManager { is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, - ) -> BuckyResult { + ) -> BuckyResult { { // read let raw = self.read().await; let found = raw - .control_by_group + .service_by_group .get(group_id) .map_or(None, |by_dec| by_dec.get(dec_id)) .map_or(None, |by_rpath| by_rpath.get(rpath)); @@ -446,7 +446,7 @@ impl GroupManager { }; let found = raw - .control_by_group + .service_by_group .entry(group_id.clone()) .or_insert_with(HashMap::new) .entry(dec_id.clone()) @@ -456,7 +456,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let control = RPathControl::load( + let service = RPathService::load( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -467,8 +467,8 @@ impl GroupManager { store, ) .await?; - entry.insert(control.clone()); - Ok(control) + entry.insert(service.clone()); + Ok(service) } } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 2ad717514..f881db19c 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod group_events; mod group_manager; mod rpath_client; -mod rpath_control; +mod rpath_service; pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; -pub use rpath_control::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_service.rs similarity index 96% rename from src/component/cyfs-group/src/dec/rpath_control.rs rename to src/component/cyfs-group/src/dec/rpath_service.rs index 593d82db4..b4b90972f 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -9,7 +9,7 @@ use crate::{ PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; -struct RPathControlRaw { +struct RPathServiceRaw { local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, @@ -18,9 +18,9 @@ struct RPathControlRaw { } #[derive(Clone)] -pub struct RPathControl(Arc); +pub struct RPathService(Arc); -impl RPathControl { +impl RPathService { pub(crate) async fn load( local_id: ObjectId, local_device_id: ObjectId, @@ -50,7 +50,7 @@ impl RPathControl { rpath.clone(), ); - let raw = RPathControlRaw { + let raw = RPathServiceRaw { network_sender, pending_proposal_handle, local_id, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 42544e51c..88450ac1b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,7 +505,7 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathControl; + use cyfs_group::RPathService; use cyfs_lib::{ DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, @@ -545,7 +545,7 @@ mod GroupDecService { } // pub struct PostProposalRoutine { - // controller: RPathControl, + // service: RPathService, // } // #[async_trait::async_trait] @@ -558,7 +558,7 @@ mod GroupDecService { // ) -> BuckyResult { // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // self.controller.push_proposal(proposal).await?; + // self.service.push_proposal(proposal).await?; // Ok(NONPostObjectInputResponse { object: None }) // } // } @@ -1037,9 +1037,9 @@ async fn main_run() { ) .await; - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1066,9 +1066,9 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1113,9 +1113,9 @@ async fn main_run() { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1125,7 +1125,7 @@ async fn main_run() { .unwrap(); async_std::task::spawn(async move { - control.push_proposal(proposal).await.unwrap(); + service.push_proposal(proposal).await.unwrap(); }); if i % 10 == 0 { From 7d75458acb0e8541761abad1c5d9332f12d5898c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 15:34:34 +0800 Subject: [PATCH 274/553] Interface in client for DecAPP --- src/component/cyfs-group-lib/src/delegate.rs | 6 +-- .../cyfs-group-lib/src/group_manager.rs | 37 ++++++++++++++++--- src/component/cyfs-group-lib/src/lib.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 23 ++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/rpath_service.rs diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 21b1e6346..645cd0656 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,4 @@ -use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, -}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -11,7 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()>; + ) -> BuckyResult>; } pub struct ExecuteResult { diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 8c82bc9e1..103807446 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,20 +1,47 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::DecAppId; +use cyfs_lib::SharedCyfsStack; -use crate::{DelegateFactory, RPathClient}; +use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; #[derive(Clone)] pub struct GroupManager; impl GroupManager { - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn open( + stack: SharedCyfsStack, + delegate_factory: Box, + ) -> BuckyResult { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn start_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + delegate: Box, + ) -> BuckyResult { + Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + } + + pub async fn find_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client( + &self, + group_id: ObjectId, + dec_id: DecAppId, + rpath: String, + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 199307bcc..34473bf07 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -2,8 +2,10 @@ mod delegate; mod group_manager; mod objects; mod rpath_client; +mod rpath_service; pub use delegate::*; pub use group_manager::*; pub use objects::*; pub use rpath_client::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs new file mode 100644 index 000000000..81225ed72 --- /dev/null +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupProposal, GroupRPath}; + +struct RPathServiceRaw {} + +#[derive(Clone)] +pub struct RPathService(Arc); + +impl RPathService { + pub(crate) async fn load() -> BuckyResult { + unimplemented!() + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + unimplemented!() + } +} From 3667c7ceb446a90c5d95232f484b4091f1ca330b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 21:21:44 +0800 Subject: [PATCH 275/553] Interface in client for DecAPP events --- .../cyfs-base/protos/standard_objects.proto | 4 +- src/component/cyfs-base/src/objects/group.rs | 20 +- .../cyfs-core/protos/core_objects.proto | 8 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 18 +- .../cyfs-core/src/group/group_rpath.rs | 14 +- src/component/cyfs-group-lib/Cargo.toml | 3 +- src/component/cyfs-group-lib/src/delegate.rs | 24 +- .../cyfs-group-lib/src/group_manager.rs | 442 +++++++++++++++++- .../cyfs-group-lib/src/rpath_client.rs | 45 +- .../cyfs-group-lib/src/rpath_service.rs | 122 ++++- .../src/consensus/hotstuff/hotstuff.rs | 4 +- .../cyfs-group/src/dec/group_events.rs | 10 +- .../cyfs-group/src/dec/group_manager.rs | 28 +- .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec_state/state_pusher.rs | 4 +- .../cyfs-group/src/network/protocol.rs | 6 +- .../engine/storage_engine_group_state.rs | 8 +- .../cyfs-group/src/storage/group_storage.rs | 6 +- src/component/cyfs-lib/src/stack/stack.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- 21 files changed, 689 insertions(+), 115 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index cfb722c62..4a9714958 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -72,7 +72,7 @@ message GroupMethodACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; double min_support_percent = 4; string permissions = 5; // ACL-String @@ -83,7 +83,7 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; string method = 4; double right_percent = 5; diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ed7686157..5c8cda714 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -436,7 +436,7 @@ impl TryFrom<&GroupMember> for protos::GroupMember { pub struct GroupMethodACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub min_support_percent: f64, pub permissions: String, // ACL-String } @@ -452,8 +452,8 @@ impl TryFrom for GroupMethodACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -475,8 +475,8 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.min_support_percent = value.min_support_percent; ret.permissions = value.permissions.clone(); @@ -489,7 +489,7 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { pub struct GroupRoleACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub method: String, pub right_percent: f64, @@ -508,8 +508,8 @@ impl TryFrom for GroupRoleACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -533,8 +533,8 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.method = value.method.clone(); ret.right_percent = value.right_percent; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 742c14904..8048b3951 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -333,12 +333,12 @@ message SyncResponseObjectMetaInfo { message GroupRPath { bytes group_id = 1; bytes dec_id = 2; - string r_path = 3; + string rpath = 3; } message GroupProposalDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; @@ -404,7 +404,7 @@ message HotstuffTimeout { message GroupConsensusBlockDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // input bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) @@ -437,7 +437,7 @@ message GroupConsensusBlockBodyContent { /* message GroupActionDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 35c418552..7d447ad15 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -10,7 +10,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path: GroupRPath, + rpath: GroupRPath, body_hash: HashValue, result_state_id: Option, height: u64, @@ -40,7 +40,7 @@ impl DescContent for GroupConsensusBlockDescContent { impl GroupConsensusBlockDescContent { pub fn rpath(&self) -> &GroupRPath { - &self.r_path + &self.rpath } pub fn result_state_id(&self) -> &Option { @@ -236,7 +236,7 @@ impl GroupConsensusBlockBodyContent { pub trait GroupConsensusBlockObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -248,7 +248,7 @@ pub trait GroupConsensusBlockObject { owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; @@ -266,7 +266,7 @@ pub trait GroupConsensusBlockObject { impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -280,7 +280,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { - r_path, + rpath, result_state_id, height, @@ -319,9 +319,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path(&self) -> &GroupRPath { + fn rpath(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path + &desc.rpath } fn proposals(&self) -> &Vec { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index bf28aafb2..508418f7b 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -6,7 +6,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, @@ -123,7 +123,7 @@ pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, meta_block_id: Option, @@ -131,7 +131,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path, + rpath, method, params, meta_block_id, @@ -158,7 +158,7 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -169,7 +169,7 @@ pub trait GroupProposalObject { effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -207,7 +207,7 @@ pub trait GroupProposalObject { #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -218,7 +218,7 @@ impl GroupProposalObject for GroupProposal { effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path, + rpath, method, params, meta_block_id, @@ -237,8 +237,8 @@ impl GroupProposalObject for GroupProposal { .owner(owner) } - fn r_path(&self) -> &GroupRPath { - &self.desc().content().r_path + fn rpath(&self) -> &GroupRPath { + &self.desc().content().rpath } fn method(&self) -> &str { diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 3b86fbc57..f177015bf 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,25 +1,25 @@ use cyfs_base::*; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq, Hash)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, - r_path: String, + rpath: String, } impl std::fmt::Debug for GroupRPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.rpath) } } impl GroupRPath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { Self { group_id, dec_id, - r_path, + rpath, } } @@ -31,7 +31,7 @@ impl GroupRPath { &self.dec_id } - pub fn r_path(&self) -> &str { - self.r_path.as_str() + pub fn rpath(&self) -> &str { + self.rpath.as_str() } } diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index e7cfda851..bad3d3112 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -31,4 +31,5 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 645cd0656..3cc99902b 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,6 @@ -use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SingleOpEnvStub}; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { @@ -23,30 +23,36 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult<()>; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ); } #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { - async fn create_single_op_env(&self) -> BuckyResult; - async fn create_sub_tree_op_env(&self) -> BuckyResult; + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult; + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 103807446..f93be45f0 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,37 +1,132 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::DecAppId; -use cyfs_lib::SharedCyfsStack; +use std::{collections::HashMap, sync::Arc}; -use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RawDecode, +}; +use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, + SharedCyfsStack, +}; +use cyfs_util::EventListenerAsyncRoutine; + +use crate::{ + DelegateFactory, ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandNewRPath, GroupCommandObject, GroupCommandType, + GroupCommandVerify, RPathClient, RPathDelegate, RPathService, +}; + +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupManagerRaw { + stack: SharedCyfsStack, + requestor: HttpRequestorRef, + delegate_factory: Option>, + clients: RwLock, + services: RwLock, + local_zone: Option, +} #[derive(Clone)] -pub struct GroupManager; +pub struct GroupManager(Arc); impl GroupManager { pub async fn open( stack: SharedCyfsStack, delegate_factory: Box, + requestor_type: &CyfsStackRequestorType, ) -> BuckyResult { - unimplemented!() + if stack.dec_id().is_none() { + let msg = "the stack should be opened with dec-id"; + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let dec_id = stack.dec_id().unwrap().clone(); + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + let router_handler_manager = stack.router_handlers().clone(); + + let mgr = Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: Some(delegate_factory), + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + })); + + // TODO: other filters? only local zone + let filter = format!( + "obj_type == {} && dec_id == {}", + CoreObjectType::GroupCommand as u16, + dec_id, + ); + + router_handler_manager + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-cmd-{}", dec_id).as_str(), + 0, + Some(filter), + None, + RouterHandlerAction::Pass, + Some(Box::new(mgr.clone())), + ) + .await?; + + Ok(mgr) } - pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { + pub async fn open_as_client( + stack: SharedCyfsStack, + requestor_type: &CyfsStackRequestorType, + ) -> BuckyResult { + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + + Ok(Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: None, + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + }))) + } + + pub async fn stop(&self) { unimplemented!() } + pub fn stack(&self) -> &SharedCyfsStack { + &self.0.stack + } + pub async fn start_rpath_service( &self, group_id: ObjectId, rpath: String, delegate: Box, ) -> BuckyResult { - Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + unimplemented!() } pub async fn find_rpath_service( &self, - group_id: ObjectId, - rpath: String, + group_id: &ObjectId, + rpath: &str, ) -> BuckyResult { unimplemented!() } @@ -40,8 +135,329 @@ impl GroupManager { &self, group_id: ObjectId, dec_id: DecAppId, - rpath: String, - ) -> BuckyResult { - unimplemented!() + rpath: &str, + ) -> RPathClient { + { + let clients = self.0.clients.read().await; + let found = clients + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id.object_id())) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return found.clone(); + } + } + + { + let client = RPathClient::new( + GroupRPath::new(group_id, dec_id.object_id().clone(), rpath.to_string()), + self.0.stack.dec_id().cloned(), + self.0.stack.non_service().clone(), + ); + + let mut clients = self.0.clients.write().await; + let client = clients + .entry(group_id) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert(client); + client.clone() + } + } + + async fn on_command( + &self, + cmd: GroupCommand, + ) -> BuckyResult> { + match cmd.into_cmd() { + crate::GroupCommandBodyContent::NewRPath(cmd) => { + self.on_new_rpath(cmd).await.map(|_| None) + } + crate::GroupCommandBodyContent::Execute(cmd) => { + self.on_execute(cmd).await.map(|r| Some(r)) + } + crate::GroupCommandBodyContent::ExecuteResult(_) => { + let msg = format!( + "should not get the cmd({:?}) in sdk", + GroupCommandType::ExecuteResult + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)) + } + crate::GroupCommandBodyContent::Verify(cmd) => self.on_verify(cmd).await.map(|_| None), + crate::GroupCommandBodyContent::Commited(cmd) => { + self.on_commited(cmd).await.map(|_| None) + } + } + } + + async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let group_id = &cmd.group_id; + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.rpath.as_str(); + + { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if found.is_some() { + return Ok(()); + } + } + + let delegate = factory + .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) + .await?; + + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(()); + } + }; + + new_service.start().await; + Ok(()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } + } + + async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try execute proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try execute proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let mut result = service + .on_execute(&cmd.proposal, &cmd.prev_state_id) + .await?; + + Ok(GroupCommandExecuteResult { + result_state_id: result.result_state_id.take(), + receipt: result.receipt.take(), + context: result.context.take(), + }) + } + + async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try verify proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try verify proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) + .await + } + + async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try commited proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try commited proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } +} + +#[async_trait::async_trait] +impl EventListenerAsyncRoutine + for GroupManager +{ + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + let req_common = ¶m.request.common; + if req_common.level != NONAPILevel::NOC + || req_common.source.zone.zone != self.0.local_zone + || self.0.local_zone.is_none() + || self.0.stack.dec_id().is_none() + { + log::warn!( + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id() + ); + + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let obj = ¶m.request.object; + match obj.object.as_ref() { + None => { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }) + } + Some(any_obj) => { + assert_eq!(any_obj.obj_type(), CoreObjectType::GroupCommand as u16); + if any_obj.obj_type() != CoreObjectType::GroupCommand as u16 { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let (cmd, remain) = GroupCommand::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + let resp_obj = self.on_command(cmd).await; + + let resp_cmd = resp_obj.map_or_else( + |err| Err(err), + |resp_obj| { + resp_obj.map_or(Ok(None), |resp_cmd| { + let resp_cmd = GroupCommand::from(resp_cmd); + resp_cmd.to_vec().map(|buf| { + Some(NONObjectInfo::new(resp_cmd.desc().object_id(), buf, None)) + }) + }) + }, + ); + + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: Some(resp_cmd.map(|cmd| NONPostObjectInputResponse { object: cmd })), + }) + } + } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 2fea6dcf7..ea032715b 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -1,26 +1,55 @@ use std::sync::Arc; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, - RawConvertTo, +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, }; -use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::NONObjectInfo; -struct RPathClientRaw {} +struct RPathClientRaw { + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, +} #[derive(Clone)] pub struct RPathClient(Arc); impl RPathClient { + pub(crate) fn new( + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, + ) -> Self { + Self(Arc::new(RPathClientRaw { + requestor, + rpath, + local_dec_id, + })) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + self.0 + .requestor + .post_object(NONPostObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: self.0.local_dec_id.clone(), + level: NONAPILevel::Router, + target: Some(proposal.rpath().group_id().clone()), + flags: 0, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), proposal.to_vec()?, None), + }) + .await + .map(|resp| resp.object) } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 81225ed72..cebe445dd 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,23 +1,133 @@ use std::sync::Arc; -use cyfs_base::BuckyResult; -use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, +}; -struct RPathServiceRaw {} +use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + +struct RPathServiceRaw { + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, +} #[derive(Clone)] pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load() -> BuckyResult { + pub fn rpath(&self) -> &GroupRPath { unimplemented!() } - pub fn rpath(&self) -> &GroupRPath { + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + // post http unimplemented!() } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub(crate) fn new( + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, + ) -> Self { + Self(Arc::new(RPathServiceRaw { + rpath, + requestor, + delegate, + stack, + })) + } + + pub(crate) async fn start(&self) -> BuckyResult { + // post create command unimplemented!() } + + pub(crate) async fn on_execute( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + ) -> BuckyResult { + self.0 + .delegate + .on_execute( + proposal, + prev_state_id, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_verify( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + self.0 + .delegate + .on_verify( + proposal, + prev_state_id, + execute_result, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_commited( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + self.0 + .delegate + .on_commited( + proposal, + prev_state_id, + execute_result, + block, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } +} + +struct GroupObjectMapProcessorImpl { + stack: SharedCyfsStack, +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorImpl { + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_single_op_env_with_access(access) + .await + } + + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_isolate_path_op_env_with_access(access) + .await + } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index eaaaed06e..d2dbcc517 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,7 +11,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; @@ -20,7 +20,7 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, }; /** diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index fc3d12c63..9bda7e340 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,6 @@ use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -130,3 +130,9 @@ impl RPathEventNotifier { assert!(result.is_err() || result.unwrap().is_none()); } } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 23202fddf..7a9708ccc 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -181,12 +181,12 @@ impl GroupManager { ) -> BuckyResult<()> { match msg { HotstuffPackage::Block(block) => { - let rpath = block.r_path(); + let rpath = block.rpath(); let service = self .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, Some(&block), Some(&remote), @@ -202,7 +202,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -218,7 +218,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -234,7 +234,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -250,7 +250,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -266,7 +266,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -278,9 +278,9 @@ impl GroupManager { } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { // TODO: unimplemented - // let rpath = header_block.r_path(); + // let rpath = header_block.rpath(); // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) // .await?; // client // .on_message( @@ -292,10 +292,10 @@ impl GroupManager { HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( @@ -313,7 +313,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -328,7 +328,7 @@ impl GroupManager { } _ => { let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) @@ -342,7 +342,7 @@ impl GroupManager { |status| status.block_desc.content().rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 41db0c25c..43fb8e559 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -78,13 +78,13 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.0.rpath); + assert_eq!(proposal.rpath(), &self.0.rpath); // TODO: signature let group = self .0 .non_driver - .get_group(proposal.r_path().group_id(), None, None) + .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 571c1ca13..99c3fed62 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -222,7 +222,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) @@ -248,7 +248,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 7e32fdc4d..1f2a46a73 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -321,16 +321,16 @@ impl std::fmt::Debug for HotstuffPackage { impl HotstuffPackage { pub(crate) fn rpath(&self) -> &GroupRPath { match self { - HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::Block(block) => block.rpath(), HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), - HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::StateChangeNotify(block, _) => block.rpath(), HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( |(_, addr)| addr.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 63158a865..029b09e78 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,12 +5,12 @@ use cyfs_base::{ ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_group_lib::GroupObjectMapProcessor; +use cyfs_core::GroupConsensusBlockObject; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a1a681259..3a762c1b6 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,12 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, - STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 2f162c331..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -94,7 +94,7 @@ pub struct SharedCyfsStack { // uni_stack uni_stack: Arc>, - requestor_holder: RequestorHolder, + requestor_holder: Arc>, } #[derive(Debug, Clone)] @@ -493,14 +493,15 @@ impl SharedCyfsStack { device_info: Arc::new(RwLock::new(None)), uni_stack: Arc::new(OnceCell::new()), - requestor_holder, + requestor_holder: Arc::new(RwLock::new(requestor_holder)), }; Ok(ret) } pub async fn stop(&self) { - self.requestor_holder.stop().await; + let requestor_holder = self.requestor_holder.read().unwrap(); + requestor_holder.stop().await; self.router_handlers.stop().await; @@ -744,6 +745,11 @@ impl SharedCyfsStack { pub fn uni_stack(&self) -> &UniCyfsStackRef { self.uni_stack.get_or_init(|| self.create_uni_stack()) } + + pub fn select_requestor(&self, requestor_type: &CyfsStackRequestorType) -> HttpRequestorRef { + let mut requestor_holder = self.requestor_holder.write().unwrap(); + requestor_holder.select_requestor(&self.param, requestor_type) + } } impl UniCyfsStack for SharedCyfsStack { diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index f7f305a83..431915a96 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: None, flags: 0, @@ -105,7 +105,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, From ee7c53c6646484f2c45d67f95bf2c67b599b848f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 16:49:16 +0800 Subject: [PATCH 276/553] Interface for client --- src/component/cyfs-group-lib/Cargo.toml | 1 + src/component/cyfs-group-lib/src/delegate.rs | 1 + .../cyfs-group-lib/src/group_manager.rs | 255 ++++++++---------- .../cyfs-group-lib/src/input_request.rs | 0 src/component/cyfs-group-lib/src/lib.rs | 12 + .../cyfs-group-lib/src/output_request.rs | 7 + src/component/cyfs-group-lib/src/processor.rs | 6 + src/component/cyfs-group-lib/src/request.rs | 0 .../cyfs-group-lib/src/request_codec.rs | 21 ++ src/component/cyfs-group-lib/src/requestor.rs | 210 +++++++++++++++ .../cyfs-group-lib/src/rpath_client.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 14 +- .../cyfs-lib/src/non/output_request.rs | 20 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- 14 files changed, 391 insertions(+), 162 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/input_request.rs create mode 100644 src/component/cyfs-group-lib/src/output_request.rs create mode 100644 src/component/cyfs-group-lib/src/processor.rs create mode 100644 src/component/cyfs-group-lib/src/request.rs create mode 100644 src/component/cyfs-group-lib/src/request_codec.rs create mode 100644 src/component/cyfs-group-lib/src/requestor.rs diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index bad3d3112..740b303cd 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' itertools = "0.10.3" +http-types = '2.12' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 3cc99902b..d678438c3 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -9,6 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult>; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f93be45f0..f442d5c55 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,7 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, @@ -195,98 +195,28 @@ impl GroupManager { } async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { - match self.0.delegate_factory.as_ref() { - Some(factory) => { - let group_id = &cmd.group_id; - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.rpath.as_str(); - - { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - if found.is_some() { - return Ok(()); - } - } - - let delegate = factory - .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) - .await?; - - let new_service = { - let mut is_new = false; - - let mut services = self.0.services.write().await; - let service = services - .entry(group_id.clone()) - .or_insert_with(HashMap::new) - .entry(dec_id.clone()) - .or_insert_with(HashMap::new) - .entry(rpath.to_string()) - .or_insert_with(|| { - is_new = true; - - RPathService::new( - GroupRPath::new( - group_id.clone(), - dec_id.clone(), - rpath.to_string(), - ), - self.0.requestor.clone(), - delegate, - self.0.stack.clone(), - ) - }); - - if is_new { - service.clone() - } else { - return Ok(()); - } - }; - - new_service.start().await; - Ok(()) - } - None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), - } + self.find_or_restart_service( + &cmd.group_id, + self.0.stack.dec_id().unwrap(), + cmd.rpath.as_str(), + &cmd.with_block, + true, + ) + .await + .map(|_| ()) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try execute proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try execute proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) @@ -300,36 +230,16 @@ impl GroupManager { } async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try verify proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try verify proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -343,47 +253,102 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; - if cmd.proposal.rpath().dec_id() != dec_id { + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } + + async fn find_or_restart_service( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: &Option, + is_new: bool, + ) -> BuckyResult { + if dec_id != self.0.stack.dec_id().unwrap() { let msg = format!( - "try commited proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id + "try find proposal in different dec {:?}, expected: {:?}", + dec_id, + self.0.stack.dec_id().unwrap() ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - let service = { + { let services = self.0.services.read().await; let found = services .get(group_id) .and_then(|by_dec| by_dec.get(dec_id)) .and_then(|by_rpath| by_rpath.get(rpath)); - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try commited proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } + if let Some(found) = found { + return Ok(found.clone()); } - }; + } - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let delegate = factory + .create_rpath_delegate(group_id, rpath, with_block.as_ref(), is_new) + .await?; - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; - Ok(()) + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(service.clone()); + } + }; + + new_service.start().await; + Ok(new_service.clone()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } } } diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 34473bf07..519a64040 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,11 +1,23 @@ mod delegate; mod group_manager; +mod input_request; mod objects; +mod output_request; +mod processor; +mod request; +mod request_codec; +mod requestor; mod rpath_client; mod rpath_service; pub use delegate::*; pub use group_manager::*; +pub use input_request::*; pub use objects::*; +pub use output_request::*; +pub use processor::*; +pub(crate) use request::*; +pub use request_codec::*; +pub use requestor::*; pub use rpath_client::*; pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs new file mode 100644 index 000000000..c847668df --- /dev/null +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -0,0 +1,7 @@ +use cyfs_base::ObjectId; + +#[derive(Debug)] +pub struct GroupStartServiceOutputRequest { + pub group_id: ObjectId, + pub rpath: String, +} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs new file mode 100644 index 000000000..925061f3e --- /dev/null +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +#[async_trait::async_trait] +pub trait GroupOutputProcessor: Send + Sync {} + +pub type GroupOutputProcessorRef = Arc; diff --git a/src/component/cyfs-group-lib/src/request.rs b/src/component/cyfs-group-lib/src/request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs new file mode 100644 index 000000000..c4f330efc --- /dev/null +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -0,0 +1,21 @@ +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use serde_json::{Map, Value}; + +use crate::output_request::GroupStartServiceOutputRequest; + +impl JsonCodec for GroupStartServiceOutputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs new file mode 100644 index 000000000..437a01184 --- /dev/null +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + CYFS_API_LEVEL, +}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, +}; +use http_types::{Method, Request, Url}; + +use crate::{ + output_request::GroupStartServiceOutputRequest, + processor::{GroupOutputProcessor, GroupOutputProcessorRef}, +}; + +#[derive(Clone)] +pub struct GroupRequestor { + dec_id: ObjectId, + requestor: HttpRequestorRef, + service_url: Url, +} + +impl GroupRequestor { + pub fn new(dec_id: ObjectId, requestor: HttpRequestorRef) -> Self { + let addr = requestor.remote_addr(); + + let url = format!("http://{}/group/", addr); + let url = Url::parse(&url).unwrap(); + + Self { + dec_id, + requestor, + service_url: url, + } + } + + pub fn clone_processor(&self) -> GroupOutputProcessorRef { + Arc::new(self.clone()) + } + + fn encode_common_headers( + &self, + // action: NONAction, + com_req: &NONOutputRequestCommon, + http_req: &mut Request, + ) { + let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); + http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); + + RequestorHelper::encode_opt_header_with_encoding( + http_req, + cyfs_base::CYFS_REQ_PATH, + com_req.req_path.as_deref(), + ); + + // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + + http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); + + if let Some(target) = &com_req.target { + http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); + } + + if let Some(source) = &com_req.source { + http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); + } + + http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); + } + + fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(dec_id), + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, + } + } + + pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + log::info!("will start group service: {:?}", rpath); + + let url = self.service_url.join("start-service").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + let req = GroupStartServiceOutputRequest { + group_id: rpath.group_id().clone(), + rpath: rpath.rpath().to_string(), + }; + + self.encode_common_headers( + &Self::make_default_common(rpath.dec_id().clone()), + &mut http_req, + ); + let body = req.encode_string(); + http_req.set_body(body); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group start service failed, read body string error! req={:?} {}", + req, e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!("group start service success"); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group start service failed: rpath={:?}, status={}, {}", + rpath, + code, + e + ); + Err(e) + } + } + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + let proposal_id = proposal.desc().object_id(); + log::info!( + "will push proposal: {:?}, {}", + proposal.rpath(), + proposal_id + ); + + let url = self.service_url.join("push-proposal").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + self.encode_common_headers( + &Self::make_default_common(proposal.rpath().dec_id().clone()), + &mut http_req, + ); + + NONRequestorHelper::encode_object_info( + &mut http_req, + NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + ); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group push proposal failed, read body string error! req={:?}/{} {}", + proposal.rpath(), + proposal_id, + e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!( + "group push proposal success, req={:?}/{}", + proposal.rpath(), + proposal_id + ); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group push proposal failed: rpath={:?}/{}, status={}, {}", + proposal.rpath(), + proposal_id, + code, + e + ); + Err(e) + } + } + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupRequestor {} diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index ea032715b..7d7c9a613 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -32,6 +32,8 @@ impl RPathClient { &self.0.rpath } + // post proposal to the admins, it's same as calling to non.post_object with default parameters; + // and you can call the non.post_object with more parameters. pub async fn post_proposal( &self, proposal: &GroupProposal, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index cebe445dd..95811e339 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -6,11 +6,11 @@ use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; +use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; struct RPathServiceRaw { rpath: GroupRPath, - requestor: HttpRequestorRef, + requestor: GroupRequestor, delegate: Box, stack: SharedCyfsStack, } @@ -20,12 +20,12 @@ pub struct RPathService(Arc); impl RPathService { pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - unimplemented!() + self.0.requestor.push_proposal(proposal).await } pub(crate) fn new( @@ -35,16 +35,16 @@ impl RPathService { stack: SharedCyfsStack, ) -> Self { Self(Arc::new(RPathServiceRaw { + requestor: GroupRequestor::new(rpath.dec_id().clone(), requestor), rpath, - requestor, delegate, stack, })) } - pub(crate) async fn start(&self) -> BuckyResult { + pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - unimplemented!() + self.0.requestor.start_group_service(self.rpath()).await } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-lib/src/non/output_request.rs b/src/component/cyfs-lib/src/non/output_request.rs index d4950ce33..b6e96dcb3 100644 --- a/src/component/cyfs-lib/src/non/output_request.rs +++ b/src/component/cyfs-lib/src/non/output_request.rs @@ -4,7 +4,7 @@ use cyfs_base::*; use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NONOutputRequestCommon { // 请求路径,可为空 pub req_path: Option, @@ -130,14 +130,22 @@ impl NONUpdateObjectMetaOutputRequest { Self::new(NONAPILevel::NOC, object_id, access) } - pub fn new_non(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_non( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::NON, object_id, access); ret.common.target = target.map(|v| v.into()); ret } - pub fn new_router(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_router( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::Router, object_id, access); ret.common.target = target; @@ -243,7 +251,6 @@ impl NONGetObjectOutputRequest { } } - impl fmt::Display for NONGetObjectOutputRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "common: {}", self.common)?; @@ -338,7 +345,6 @@ impl fmt::Display for NONPostObjectOutputResponse { } } - // select #[derive(Clone)] pub struct NONSelectObjectOutputRequest { @@ -392,7 +398,6 @@ impl fmt::Display for NONSelectObjectOutputRequest { } } - #[derive(Clone)] pub struct NONSelectObjectOutputResponse { pub objects: Vec, @@ -470,7 +475,6 @@ impl fmt::Display for NONDeleteObjectOutputRequest { } } - #[derive(Clone)] pub struct NONDeleteObjectOutputResponse { pub object: Option, @@ -479,7 +483,7 @@ pub struct NONDeleteObjectOutputResponse { impl fmt::Display for NONDeleteObjectOutputResponse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "object: {:?}", self.object)?; - + Ok(()) } } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 431915a96..9333e7981 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::NOC, target: None, flags: 0, From 20a09f324c64763854184664a7d47fc152cbfaed Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 21:35:56 +0800 Subject: [PATCH 277/553] Export to SDK --- .../cyfs-group-lib/src/input_request.rs | 10 + .../cyfs-group-lib/src/output_request.rs | 4 + src/component/cyfs-group-lib/src/processor.rs | 24 ++- .../cyfs-group-lib/src/request_codec.rs | 19 +- src/component/cyfs-group-lib/src/requestor.rs | 54 +++-- .../cyfs-group-lib/src/rpath_service.rs | 21 +- src/component/cyfs-stack/Cargo.toml | 1 + src/component/cyfs-stack/src/group/mod.rs | 5 + .../cyfs-stack/src/group/processor.rs | 25 +++ .../cyfs-stack/src/group/transform.rs | 190 ++++++++++++++++++ .../cyfs-stack/src/group_api/acl/group_acl.rs | 61 ++++++ .../cyfs-stack/src/group_api/acl/mod.rs | 3 + src/component/cyfs-stack/src/group_api/mod.rs | 7 + .../group_api/router/group_service_router.rs | 133 ++++++++++++ .../src/group_api/router/local_service.rs | 113 +++++++++++ .../cyfs-stack/src/group_api/router/mod.rs | 5 + .../src/group_api/service/group_handler.rs | 125 ++++++++++++ .../src/group_api/service/group_listener.rs | 77 +++++++ .../src/group_api/service/group_service.rs | 35 ++++ .../cyfs-stack/src/group_api/service/mod.rs | 7 + .../cyfs-stack/src/interface/http_listener.rs | 11 + .../src/interface/listener_manager.rs | 14 +- src/component/cyfs-stack/src/lib.rs | 2 + .../cyfs-stack/src/stack/cyfs_stack.rs | 12 +- 24 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/component/cyfs-stack/src/group/mod.rs create mode 100644 src/component/cyfs-stack/src/group/processor.rs create mode 100644 src/component/cyfs-stack/src/group/transform.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/group_acl.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/group_service_router.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/local_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_handler.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_listener.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/mod.rs diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index e69de29bb..0f861ea3c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -0,0 +1,10 @@ +use cyfs_base::ObjectId; + +pub struct GroupStartServiceInputRequest { + pub group_id: ObjectId, + pub rpath: String, +} + +pub struct GroupStartServiceInputResponse {} + +pub struct GroupPushProposalInputResponse {} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index c847668df..f65e02e3e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -5,3 +5,7 @@ pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, pub rpath: String, } + +pub struct GroupStartServiceOutputResponse {} + +pub struct GroupPushProposalOutputResponse {} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 925061f3e..9aec5a354 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -1,6 +1,26 @@ use std::sync::Arc; +use cyfs_base::BuckyResult; +use cyfs_core::GroupProposal; +use cyfs_lib::NONOutputRequestCommon; + +use crate::{ + GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, +}; + #[async_trait::async_trait] -pub trait GroupOutputProcessor: Send + Sync {} +pub trait GroupOutputProcessor: Send + Sync { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult; + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} -pub type GroupOutputProcessorRef = Arc; +pub type GroupOutputProcessorRef = Arc>; diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index c4f330efc..58404d6b0 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::output_request::GroupStartServiceOutputRequest; +use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { @@ -19,3 +19,20 @@ impl JsonCodec for GroupStartServiceOutputReques }) } } + +impl JsonCodec for GroupStartServiceInputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 437a01184..462b1df85 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -13,6 +13,7 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, + GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -37,7 +38,7 @@ impl GroupRequestor { } pub fn clone_processor(&self) -> GroupOutputProcessorRef { - Arc::new(self.clone()) + Arc::new(Box::new(self.clone())) } fn encode_common_headers( @@ -70,7 +71,7 @@ impl GroupRequestor { http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { NONOutputRequestCommon { req_path: None, source: None, @@ -81,21 +82,23 @@ impl GroupRequestor { } } - pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + pub async fn start_service( + &self, + req_common: NONOutputRequestCommon, + group_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); let url = self.service_url.join("start-service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { - group_id: rpath.group_id().clone(), - rpath: rpath.rpath().to_string(), + group_id: group_id.clone(), + rpath: rpath.to_string(), }; - self.encode_common_headers( - &Self::make_default_common(rpath.dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -123,7 +126,7 @@ impl GroupRequestor { log::debug!("group start service success"); - Ok(()) + Ok(GroupStartServiceOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -138,7 +141,11 @@ impl GroupRequestor { } } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + proposal: &GroupProposal, + ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", @@ -149,10 +156,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers( - &Self::make_default_common(proposal.rpath().dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, @@ -189,7 +193,7 @@ impl GroupRequestor { proposal_id ); - Ok(()) + Ok(GroupPushProposalOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -207,4 +211,20 @@ impl GroupRequestor { } #[async_trait::async_trait] -impl GroupOutputProcessor for GroupRequestor {} +impl GroupOutputProcessor for GroupRequestor { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupRequestor::push_proposal(self, req_common, &req).await + } +} diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 95811e339..66d0d83f4 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; @@ -25,7 +25,14 @@ impl RPathService { pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - self.0.requestor.push_proposal(proposal).await + self.0 + .requestor + .push_proposal( + GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal, + ) + .await + .map(|_| {}) } pub(crate) fn new( @@ -44,7 +51,15 @@ impl RPathService { pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - self.0.requestor.start_group_service(self.rpath()).await + self.0 + .requestor + .start_service( + GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + self.rpath().group_id(), + self.rpath().rpath(), + ) + .await + .map(|_| {}) } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 76148a72e..12e2b186f 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -16,6 +16,7 @@ cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-group = { path = "../../component/cyfs-group" } +cyfs-group-lib = { path = "../../component/cyfs-group-lib" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } diff --git a/src/component/cyfs-stack/src/group/mod.rs b/src/component/cyfs-stack/src/group/mod.rs new file mode 100644 index 000000000..da7603e40 --- /dev/null +++ b/src/component/cyfs-stack/src/group/mod.rs @@ -0,0 +1,5 @@ +mod processor; +mod transform; + +pub(crate) use processor::*; +pub(crate) use transform::*; \ No newline at end of file diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs new file mode 100644 index 000000000..b6fe1544b --- /dev/null +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -0,0 +1,25 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +#[async_trait::async_trait] +pub(crate) trait GroupInputProcessor: Sync + Send { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult; + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} + +pub(crate) type GroupInputProcessorRef = Arc; diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs new file mode 100644 index 000000000..50abe1afb --- /dev/null +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -0,0 +1,190 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, + GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +use super::{GroupInputProcessor, GroupInputProcessorRef}; + +// 实现从input到output的转换 +pub(crate) struct GroupInputTransformer { + processor: GroupOutputProcessorRef, +} + +impl GroupInputTransformer { + pub fn new(processor: GroupOutputProcessorRef) -> GroupInputProcessorRef { + let ret = Self { processor }; + Arc::new(ret) + } + + fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { + NONOutputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 来源DEC + dec_id: common.source.get_opt_dec().cloned(), + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source: common.source.zone.device, + } + } + + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let out_req = GroupStartServiceOutputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let out_resp = self + .processor + .start_service(Self::convert_common(req_common), out_req) + .await?; + + let resp = GroupStartServiceInputResponse {}; + + Ok(resp) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let out_resp = self + .processor + .push_proposal(Self::convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalInputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupInputTransformer { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + GroupInputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupInputTransformer::push_proposal(self, req_common, req).await + } +} + +// 实现从output到input的转换 +pub(crate) struct GroupOutputTransformer { + processor: GroupInputProcessorRef, + source: RequestSourceInfo, +} + +impl GroupOutputTransformer { + fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + let mut source = self.source.clone(); + if let Some(dec_id) = common.dec_id { + source.set_dec(dec_id); + } + + NONInputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source, + } + } + + pub fn new( + processor: GroupInputProcessorRef, + source: RequestSourceInfo, + ) -> GroupOutputProcessorRef { + let ret = Self { processor, source }; + Arc::new(Box::new(ret)) + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let in_resp = self + .processor + .push_proposal(self.convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalOutputResponse {}; + + Ok(resp) + } + + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + let in_req = GroupStartServiceInputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let in_resp = self + .processor + .start_service(self.convert_common(req_common), in_req) + .await?; + + let resp = GroupStartServiceOutputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupOutputTransformer { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupOutputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupOutputTransformer::push_proposal(self, req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs new file mode 100644 index 000000000..0e789c023 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -0,0 +1,61 @@ +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +pub struct GroupAclInnerInputProcessor { + next: GroupInputProcessorRef, +} + +impl GroupAclInnerInputProcessor { + pub(crate) fn new(next: GroupInputProcessorRef) -> GroupInputProcessorRef { + Arc::new(Self { next }) + } + + fn check_local_zone_permit( + &self, + service: &str, + source: &RequestSourceInfo, + ) -> BuckyResult<()> { + // TODO + // if !source.is_current_zone() { + // let msg = format!( + // "{} service valid only in current zone! source={:?}, category={}", + // service, + // source.zone.device, + // source.zone.zone_category.as_str() + // ); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, msg)); + // } + + Ok(()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupAclInnerInputProcessor { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.next.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.next.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/mod.rs b/src/component/cyfs-stack/src/group_api/acl/mod.rs new file mode 100644 index 000000000..53dad00b3 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/mod.rs @@ -0,0 +1,3 @@ +mod group_acl; + +pub use group_acl::*; diff --git a/src/component/cyfs-stack/src/group_api/mod.rs b/src/component/cyfs-stack/src/group_api/mod.rs new file mode 100644 index 000000000..29e257330 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/mod.rs @@ -0,0 +1,7 @@ +mod acl; +mod router; +mod service; + +pub(crate) use acl::*; +pub(crate) use router::*; +pub(crate) use service::*; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs new file mode 100644 index 000000000..2c1a2841f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyResult, DeviceId, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::{ + forward::ForwardProcessorManager, + group::{GroupInputProcessor, GroupInputProcessorRef, GroupInputTransformer}, + group_api::GroupAclInnerInputProcessor, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupServiceRouter { + processor: GroupInputProcessorRef, + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, +} + +impl GroupServiceRouter { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + processor: GroupInputProcessorRef, + ) -> GroupInputProcessorRef { + let processor = GroupAclInnerInputProcessor::new(processor); + let ret = Self { + processor, + zone_manager, + forward, + }; + Arc::new(ret) + } + + async fn get_forward( + &self, + dec_id: ObjectId, + target: DeviceId, + ) -> BuckyResult { + let requestor = self.forward.get(&target).await?; + let group_requestor = GroupRequestor::new(dec_id, requestor); + Ok(GroupInputTransformer::new( + group_requestor.clone_processor(), + )) + } + + // 不同于non/ndn的router,如果target为空,那么表示本地device + async fn get_target(&self, target: Option<&ObjectId>) -> BuckyResult> { + let ret = match target { + Some(object_id) => { + let info = self + .zone_manager + .target_zone_manager() + .resolve_target(Some(object_id)) + .await?; + if info.target_device == *self.zone_manager.get_current_device_id() { + None + } else { + Some(info.target_device) + } + } + None => None, + }; + + Ok(ret) + } + + async fn get_processor( + &self, + dec_id: ObjectId, + target: Option<&ObjectId>, + ) -> BuckyResult { + if let Some(device_id) = self.get_target(target).await? { + debug!("group target resolved: {:?} -> {}", target, device_id); + let processor = self.get_forward(dec_id, device_id).await?; + Ok(processor) + } else { + Ok(self.processor.clone()) + } + } + + pub async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + pub async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupServiceRouter { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs new file mode 100644 index 000000000..e14691b5e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc}; +use cyfs_core::{GroupProposal, GroupProposalObject}; +use cyfs_group::GroupManager; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; + +#[derive(Clone)] +pub(crate) struct LocalGroupService { + group_manager: GroupManager, +} + +impl LocalGroupService { + pub(crate) fn new(group_manager: GroupManager) -> Self { + Self { group_manager } + } + + pub fn clone_processor(&self) -> GroupInputProcessorRef { + Arc::new(self.clone()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for LocalGroupService { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.group_manager + .find_rpath_service( + &req.group_id, + &req_common.source.dec, + req.rpath.as_str(), + true, + ) + .await + .map(|_| GroupStartServiceInputResponse {}) + .map_err(|err| { + log::error!( + "group start service {}-{}-{} failed {:?}", + req.group_id, + req_common.source.dec, + req.rpath, + err + ); + err + }) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let proposal_id = req.desc().object_id(); + let rpath = req.rpath().clone(); + if &req_common.source.dec != rpath.dec_id() { + let msg = format!( + "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + req_common.source.dec + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let service = self + .group_manager + .find_rpath_service( + req.rpath().group_id(), + &req_common.source.dec, + rpath.rpath(), + true, + ) + .await + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed when find the service {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + })?; + + service + .push_proposal(req) + .await + .map(|_| GroupPushProposalInputResponse {}) + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + }) + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/mod.rs b/src/component/cyfs-stack/src/group_api/router/mod.rs new file mode 100644 index 000000000..877b4eff6 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/mod.rs @@ -0,0 +1,5 @@ +mod group_service_router; +mod local_service; + +pub use group_service_router::*; +pub(crate) use local_service::*; diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs new file mode 100644 index 000000000..f01f2eaa5 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -0,0 +1,125 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; + +use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; + +#[derive(Clone)] +pub(crate) struct GroupRequestHandler { + processor: GroupInputProcessorRef, +} + +impl GroupRequestHandler { + pub fn new(processor: GroupInputProcessorRef) -> Self { + Self { processor } + } + + // 解析通用header字段 + fn decode_common_headers( + req: &NONInputHttpRequest, + ) -> BuckyResult { + // req_path + let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( + &req.request, + cyfs_base::CYFS_REQ_PATH, + )?; + + // 尝试提取flags + let flags: Option = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; + + // 尝试提取default_action字段 + let level = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; + + // 尝试提取target字段 + let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; + + let ret = NONInputRequestCommon { + req_path, + source: req.source.clone(), + level: level.unwrap_or_default(), + target, + flags: flags.unwrap_or(0), + }; + + Ok(ret) + } + + // group/start-service + pub async fn process_start_service( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_start_service(req).await { + Ok(_resp) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_start_service( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + let common = Self::decode_common_headers(&req)?; + + // 提取body里面的object对象,如果有的话 + let body = req.request.body_json().await.map_err(|e| { + let msg = format!("group start service failed, read body bytes error! {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidParam, msg) + })?; + + let req = GroupStartServiceInputRequest::decode_json(&body)?; + + self.processor.start_service(common, req).await + } + + pub async fn process_push_proposal( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_push_proposal(req).await { + Ok(_) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_push_proposal( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + // 检查action + // let action = Self::decode_action(&req, NONAction::PutObject)?; + // if action != NONAction::PutObject { + // let msg = format!("invalid non put_object action! {:?}", action); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + // } + + let common = Self::decode_common_headers(&req)?; + let object = NONRequestorHelper::decode_object_info(&mut req.request).await?; + let (proposal, remain) = GroupProposal::raw_decode(object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + // let access: Option = + // RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_ACCESS)?; + // let access = access.map(|v| AccessString::new(v)); + + info!("recv push proposal: {}", object.object_id); + + self.processor.push_proposal(common, proposal).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs new file mode 100644 index 000000000..163228d1f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -0,0 +1,77 @@ +use cyfs_lib::RequestProtocol; +use tide::Response; + +use crate::{non::NONInputHttpRequest, ZoneManagerRef}; + +use super::GroupRequestHandler; + +enum GroupRequestType { + StartService, + PushProposal, +} + +pub(crate) struct GroupRequestHandlerEndpoint { + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, +} + +impl GroupRequestHandlerEndpoint { + fn new( + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, + ) -> Self { + Self { + zone_manager, + protocol, + req_type, + handler, + } + } + + async fn process_request(&self, req: tide::Request) -> Response { + let req = match NONInputHttpRequest::new(&self.zone_manager, &self.protocol, req).await { + Ok(v) => v, + Err(resp) => return resp, + }; + match self.req_type { + GroupRequestType::StartService => self.handler.process_start_service(req).await, + GroupRequestType::PushProposal => self.handler.process_push_proposal(req).await, + } + } + + pub fn register_server( + zone_manager: &ZoneManagerRef, + protocol: &RequestProtocol, + handler: &GroupRequestHandler, + server: &mut tide::Server<()>, + ) { + server.at("/group/start-service").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::StartService, + handler.clone(), + )); + + server.at("group/push-proposal").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::PushProposal, + handler.clone(), + )); + } +} + +#[async_trait::async_trait] +impl tide::Endpoint for GroupRequestHandlerEndpoint +where + State: Clone + Send + Sync + 'static, +{ + async fn call(&self, req: tide::Request) -> tide::Result { + let resp = self.process_request(req).await; + Ok(resp) + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_service.rs b/src/component/cyfs-stack/src/group_api/service/group_service.rs new file mode 100644 index 000000000..3a25e282e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_service.rs @@ -0,0 +1,35 @@ +use cyfs_group::GroupManager; + +use crate::{ + forward::ForwardProcessorManager, + group::GroupInputProcessorRef, + group_api::{GroupServiceRouter, LocalGroupService}, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupService { + router: GroupInputProcessorRef, + local_service: LocalGroupService, +} + +impl GroupService { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + group_manager: GroupManager, + ) -> Self { + let local_service = LocalGroupService::new(group_manager); + let router = + GroupServiceRouter::new(forward, zone_manager, local_service.clone_processor()); + + Self { + router, + local_service, + } + } + + pub(crate) fn clone_processor(&self) -> GroupInputProcessorRef { + self.router.clone() + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/mod.rs b/src/component/cyfs-stack/src/group_api/service/mod.rs new file mode 100644 index 000000000..1140a741d --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/mod.rs @@ -0,0 +1,7 @@ +mod group_service; +mod group_listener; +mod group_handler; + +pub(crate) use group_service::*; +pub(crate) use group_listener::*; +pub(crate) use group_handler::*; diff --git a/src/component/cyfs-stack/src/interface/http_listener.rs b/src/component/cyfs-stack/src/interface/http_listener.rs index 21b6e86e3..e9ef12523 100644 --- a/src/component/cyfs-stack/src/interface/http_listener.rs +++ b/src/component/cyfs-stack/src/interface/http_listener.rs @@ -1,6 +1,7 @@ use crate::acl::AclManagerRef; use crate::crypto_api::*; use crate::front::{FrontProtocolHandler, FrontRequestHandlerEndpoint}; +use crate::group_api::{GroupRequestHandler, GroupRequestHandlerEndpoint, GroupService}; use crate::name::NameResolver; use crate::ndn_api::*; use crate::non_api::*; @@ -75,6 +76,7 @@ impl ObjectHttpListener { global_state_meta: &GlobalStateMetaService, name_resolver: &NameResolver, zone_manager: &ZoneManagerRef, + group_service: &GroupService, ) -> Self { let mut server = new_server(); @@ -225,6 +227,15 @@ impl ObjectHttpListener { &mut server, ); + // group manager + let handler = GroupRequestHandler::new(group_service.clone_processor()); + GroupRequestHandlerEndpoint::register_server( + zone_manager, + &protocol, + &handler, + &mut server, + ); + Self { server } } diff --git a/src/component/cyfs-stack/src/interface/listener_manager.rs b/src/component/cyfs-stack/src/interface/listener_manager.rs index c6b5510be..76d3c4e9d 100644 --- a/src/component/cyfs-stack/src/interface/listener_manager.rs +++ b/src/component/cyfs-stack/src/interface/listener_manager.rs @@ -9,6 +9,7 @@ use crate::acl::AclManagerRef; use crate::app::AuthenticatedAppList; use crate::config::StackGlobalConfig; use crate::events::RouterEventsManager; +use crate::group_api::GroupService; use crate::interface::http_ws_listener::ObjectHttpWSService; use crate::name::NameResolver; use crate::rmeta_api::GlobalStateMetaService; @@ -18,7 +19,7 @@ use crate::stack::ObjectServices; use crate::zone::ZoneRoleManager; use cyfs_base::*; use cyfs_bdt::StackGuard; -use cyfs_lib::{RequestProtocol, BrowserSanboxMode}; +use cyfs_lib::{BrowserSanboxMode, RequestProtocol}; use cyfs_debug::Mutex; use std::net::SocketAddr; @@ -131,6 +132,7 @@ impl ObjectListenerManager { root_state: &GlobalStateService, local_cache: &GlobalStateLocalService, global_state_meta: &GlobalStateMetaService, + group_service: &GroupService, ) { assert!(self.listeners.is_empty()); @@ -151,6 +153,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); @@ -172,18 +175,14 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); let http_server = DefaultHttpServer::new(raw_handler.into(), default_handler.clone()); let http_server = match config.get_stack_params().front.browser_mode { BrowserSanboxMode::None => http_server.into(), - mode @ _ => { - BrowserSanboxHttpServer::new( - http_server.into(), - mode, - ).into() - } + mode @ _ => BrowserSanboxHttpServer::new(http_server.into(), mode).into(), }; self.http_tcp_server = Some(http_server); } @@ -202,6 +201,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); diff --git a/src/component/cyfs-stack/src/lib.rs b/src/component/cyfs-stack/src/lib.rs index c180fe861..832029d33 100644 --- a/src/component/cyfs-stack/src/lib.rs +++ b/src/component/cyfs-stack/src/lib.rs @@ -29,6 +29,8 @@ mod config; mod front; mod rmeta_api; mod rmeta; +mod group; +mod group_api; pub use stack::*; pub use storage::*; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 8cf9bcad0..493f6ace8 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -10,6 +10,7 @@ use crate::crypto_api::{CryptoService, ObjectCrypto, ObjectVerifier}; use crate::events::RouterEventsManager; use crate::forward::ForwardProcessorManager; use crate::front::FrontService; +use crate::group_api::GroupService; use crate::interface::{ ObjectListenerManager, ObjectListenerManagerParams, ObjectListenerManagerRef, }; @@ -105,7 +106,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupManager, + group_service: GroupService, } impl CyfsStackImpl { @@ -437,6 +438,8 @@ impl CyfsStackImpl { bdt_stack.clone(), global_state_manager.clone_processor(), )?; + let group_service = + GroupService::new(forward_manager.clone(), zone_manager.clone(), group_manager); let mut stack = Self { config, @@ -474,7 +477,7 @@ impl CyfsStackImpl { acl_manager, - group_manager, + group_service, }; // init an system-dec router-handler processor for later use @@ -564,6 +567,7 @@ impl CyfsStackImpl { &stack.root_state, &stack.local_cache, &stack.global_state_meta, + &stack.group_service, ); let interface = Arc::new(interface); @@ -1163,8 +1167,8 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupManager { - &self.stack.group_manager + pub fn group_service(&self) -> &GroupService { + &self.stack.group_service } // use system dec as default dec From 6d9f1e71b501d8f4206c94010cabd2f1e07e94dd Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Mar 2023 17:39:29 +0800 Subject: [PATCH 278/553] Remove several unused import --- src/component/cyfs-group-lib/src/request_codec.rs | 2 +- src/component/cyfs-group-lib/src/requestor.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 58404d6b0..4c7ddfe88 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 462b1df85..341bff3e3 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -4,7 +4,7 @@ use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, CYFS_API_LEVEL, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, }; @@ -116,7 +116,7 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupStartServiceOutputResponse::decode_string(&body).map_err(|e| { // error!( // "decode group start service resp from body string error: body={} {}", // body, e, @@ -179,9 +179,9 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { // error!( - // "decode group start service resp from body string error: body={} {}", + // "decode group push proposal resp from body string error: body={} {}", // body, e, // ); // e From fd8491bc73b1d36ed713b503acd484709d945898 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 19:19:00 +0800 Subject: [PATCH 279/553] Debug --- src/component/cyfs-group-lib/Cargo.toml | 1 - .../cyfs-group-lib/src/group_manager.rs | 138 +++++- src/component/cyfs-group-lib/src/requestor.rs | 11 +- .../cyfs-group/src/dec/group_events.rs | 43 +- .../cyfs-group/src/dec/group_manager.rs | 10 +- .../cyfs-group/src/dec/rpath_service.rs | 7 +- .../src/group_api/service/group_listener.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 21 +- .../cyfs-stack/src/zone/zone_manager.rs | 20 +- src/tests/group-example/Cargo.toml | 4 +- src/tests/group-example/src/main.rs | 436 ++++++++---------- 11 files changed, 407 insertions(+), 288 deletions(-) diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index 740b303cd..68931728c 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -32,5 +32,4 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f442d5c55..61a11698d 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -7,7 +7,7 @@ use cyfs_base::{ }; use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -68,11 +68,14 @@ impl GroupManager { // TODO: other filters? only local zone let filter = format!( - "obj_type == {} && dec_id == {}", + "obj_type == {} && source.dec_id == {} && source.zone_category == {}", CoreObjectType::GroupCommand as u16, dec_id, + DeviceZoneCategory::CurrentZone.to_string(), ); + // let filter = "*".to_string(); + router_handler_manager .post_object() .add_handler( @@ -80,7 +83,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - None, + Some("group-inner".to_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) @@ -120,7 +123,38 @@ impl GroupManager { rpath: String, delegate: Box, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap().clone(); + + { + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(&dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath.as_str())); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + RPathService::new( + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + Ok(service.clone()) + } } pub async fn find_rpath_service( @@ -128,7 +162,20 @@ impl GroupManager { group_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap(); + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + found.map_or( + Err(BuckyError::new( + BuckyErrorCode::NotFound, + "please start the service first", + )), + |service| Ok(service.clone()), + ) } pub async fn rpath_client( @@ -204,6 +251,16 @@ impl GroupManager { ) .await .map(|_| ()) + .map_err(|err| { + log::warn!( + "group on_new_rpath {}-{:?}-{} failed, err: {:?}", + cmd.group_id, + self.0.stack.dec_id(), + cmd.rpath, + err + ); + err + }) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { @@ -216,11 +273,27 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; Ok(GroupCommandExecuteResult { result_state_id: result.result_state_id.take(), @@ -239,7 +312,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_verify find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -250,6 +331,14 @@ impl GroupManager { service .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) .await + .map_err(|err| { + log::warn!( + "group on_verify {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + }) } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { @@ -262,7 +351,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_commited find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -361,27 +458,38 @@ impl EventListenerAsyncRoutine BuckyResult { let req_common = ¶m.request.common; - if req_common.level != NONAPILevel::NOC - || req_common.source.zone.zone != self.0.local_zone + let obj = ¶m.request.object; + + log::debug!( + "group-command handle, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) + ); + + if !req_common.source.zone.is_current_zone() || self.0.local_zone.is_none() + // || req_common.source.zone.zone != self.0.local_zone || self.0.stack.dec_id().is_none() { log::warn!( - "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", req_common.level, req_common.source.zone, self.0.local_zone, - self.0.stack.dec_id() + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) ); return Ok(RouterHandlerPostObjectResult { - action: RouterHandlerAction::Reject, + action: RouterHandlerAction::Pass, request: None, response: None, }); } - let obj = ¶m.request.object; match obj.object.as_ref() { None => { return Ok(RouterHandlerPostObjectResult { diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 341bff3e3..b77f93dad 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -6,7 +6,8 @@ use cyfs_base::{ }; use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ - HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, + HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, + RequestorHelper, }; use http_types::{Method, Request, Url}; @@ -43,7 +44,7 @@ impl GroupRequestor { fn encode_common_headers( &self, - // action: NONAction, + action: NONAction, com_req: &NONOutputRequestCommon, http_req: &mut Request, ) { @@ -56,7 +57,7 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); @@ -98,7 +99,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -156,7 +157,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 9bda7e340..a25accb19 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,9 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -32,13 +35,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -78,13 +86,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -111,16 +124,26 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd + .to_vec() + .expect(format!("on_commited {} failed for encode", self.non_driver.dec_id()).as_str()); + let any_obj = cyfs_base::AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(object_raw_buf.as_slice()).expect( + format!( + "on_commited {} failed for convert to any", + self.non_driver.dec_id() + ) + .as_str(), + ), + ); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec().expect( - format!("on_commited {} failed for encode", self.non_driver.dec_id()) - .as_str(), - ), - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7a9708ccc..579f63831 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawConvertTo, RsaCPUObjectSigner, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; @@ -488,6 +488,10 @@ impl GroupManager { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); let result = self .local_info() .non_driver @@ -495,8 +499,8 @@ impl GroupManager { dec_id, NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index b4b90972f..1f2e836a1 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -66,6 +66,11 @@ impl RPathService { } pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + log::info!( + "group({:?}) push proposal {}", + self.rpath(), + proposal.desc().object_id() + ); self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 163228d1f..47be52927 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").post(Self::new( + server.at("/group/start-service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").post(Self::new( + server.at("group/push-proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9333e7981..fa136b3fa 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::NOC, + level: NONAPILevel::Router, target: None, flags: 0, @@ -90,10 +90,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { obj: NONObjectInfo, to: Option<&ObjectId>, ) -> BuckyResult> { + let obj_type_code = obj.object_id.obj_type_code(); + let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some("group-inner".to_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -105,7 +108,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, @@ -114,5 +117,15 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) .await .map(|resp| resp.object) + .map_err(|err| { + log::warn!( + "group post object(type={:?}/{:?}) to {:?} failed {:?}", + obj_type_code, + obj_type, + to, + err + ); + err + }) } } diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 6819b991d..61f284bc4 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -652,7 +652,25 @@ impl ZoneManager { owner_id, work_mode, list ); - return Ok((work_mode, list.to_owned())); + if obj_type == ObjectTypeCode::People { + return Ok((work_mode, list.to_owned())); + } else if obj_type == ObjectTypeCode::Group { + let group = owner_object.into_group(); + // TODO: 先简单处理,找最近的OOD,后面可能要依据具体操作向不同身份发起请求; + // 比如:读操作向任意member请求即可 + let list = group + .ood_list_with_distance( + self.get_current_device_id().object_id(), + ) + .into_iter() + .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) + .map(|id| DeviceId::try_from(id).unwrap()) + .collect(); + return Ok((work_mode, list)); + } else { + unreachable!() + } + /* let ood_device_id = list[0].clone(); let obj_type = ood_device_id.object_id().obj_type_code(); diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 01094f12a..2cf31aba9 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -23,9 +23,9 @@ cyfs-core = { path = '../../component/cyfs-core' } cyfs-bdt = { path = '../../component/cyfs-bdt' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } -cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 88450ac1b..e74f3c5d6 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,36 +1,43 @@ -use std::{clone, sync::Arc, time::Duration}; +use std::{clone, collections::HashSet, sync::Arc, time::Duration}; +use async_std::sync::Mutex; use cyfs_base::{ AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_group::IsCreateRPath; +use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, - NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, + NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, + RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; +use crate::{ + Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}, + GroupDecService::MyRPathDelegate, +}; mod Common { - use std::{fmt::format, io::ErrorKind, sync::Arc}; + use std::{ + fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, + }; - use async_std::{fs, stream::StreamExt}; + use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId, DecAppObj}; - use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_core::{DecApp, DecAppId}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, @@ -348,6 +355,8 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, + rpc_port: u16, + ws_port: u16, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -369,13 +378,19 @@ mod Common { config: CyfsStackConfigParams { isolate: Some(device.desc().object_id().to_string()), sync_service: false, - shared_stack: false, + shared_stack: true, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], - tcp_listeners: vec![], - ws_listener: None, + tcp_listeners: vec![SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + rpc_port, + ))], + ws_listener: Some(SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + ws_port, + ))), }, meta: CyfsStackMetaParams { target: MetaMinerTarget::Dev, @@ -454,9 +469,20 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, - ) -> CyfsStack { - let params = - init_stack_params(people, private_key, device, admins, members, group, dec_app); + rpc_port: u16, + ws_port: u16, + ) -> (CyfsStack, SharedCyfsStack) { + let params = init_stack_params( + people, + private_key, + device, + admins, + members, + group, + dec_app, + rpc_port, + ws_port, + ); log::info!("cyfs-stack.open"); @@ -468,14 +494,23 @@ mod Common { }) .unwrap(); - stack + async_std::task::sleep(Duration::from_millis(1000)).await; + + let shared_stack = + SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) + .await + .unwrap(); + + shared_stack.wait_online(None).await.unwrap(); + + (stack, shared_stack) } } mod Client { // use cyfs_base::ObjectId; // use cyfs_core::GroupProposal; - // use cyfs_group::RPathClient; + // use cyfs_group_lib::RPathClient; // pub struct DecClient {} @@ -505,12 +540,14 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathService; + use cyfs_group_lib::{ + DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, + RPathService, + }; use cyfs_lib::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, - NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, SharedCyfsStack, }; - use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -518,16 +555,18 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { - let group_mgr = cyfs_stack.group_mgr(); - - group_mgr - .register( - dec_app_id.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), - ) - .await - .unwrap(); + pub async fn run( + cyfs_stack: &SharedCyfsStack, + local_name: String, + dec_app_id: DecAppId, + ) -> GroupManager { + let group_mgr = GroupManager::open( + cyfs_stack.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + &cyfs_lib::CyfsStackRequestorType::Http, + ) + .await + .unwrap(); // let source = RequestSourceInfo { // protocol: todo!(), @@ -541,6 +580,8 @@ mod GroupDecService { // .handlers(&RouterHandlerChain::PostRouter) // .post_object() // .add_handler(RouterHandler::new()); + + group_mgr } } @@ -570,7 +611,7 @@ mod GroupDecService { impl GroupRPathDelegateFactory { pub fn is_accept( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, ) -> bool { @@ -583,27 +624,18 @@ mod GroupDecService { impl DelegateFactory for GroupRPathDelegateFactory { async fn create_rpath_delegate( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { + if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } } pub struct MyRPathDelegate { @@ -621,73 +653,19 @@ mod GroupDecService { } impl MyRPathDelegate { - // pub async fn get_value_from_state_tree_with_single_op_envs( - // pre_state_id: Option, - // object_map_processor: &dyn GroupObjectMapProcessor, - // ) -> BuckyResult<( - // Option, - // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - // )> { - // let mut single_op_envs = vec![]; - // let mut parent_map_id = pre_state_id; - // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - // let single_op_env = object_map_processor.create_single_op_env().await.expect( - // format!( - // "create_single_op_env load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // parent_map_id = match parent_map_id { - // Some(parent_map_id) => { - // single_op_env.load(&parent_map_id).await.expect( - // format!( - // "load folder {} parent with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // single_op_env.get_by_key(folder).await.expect( - // format!( - // "load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ) - // } - // None => { - // single_op_env - // .create_new(ObjectMapSimpleContentType::Map) - // .await - // .expect( - // format!( - // "create folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // None - // } - // }; - // single_op_envs.push((single_op_env, folder, parent_map_id)); - // } - - // Ok((parent_map_id, single_op_envs)) - // } - pub async fn execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); - let pre_value = match pre_state_id { - Some(pre_state_id) => { - state_op_env.load(&pre_state_id).await?; + let prev_value = match prev_state_id { + Some(prev_state_id) => { + state_op_env.load(prev_state_id.to_owned()).await?; state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -708,13 +686,13 @@ mod GroupDecService { let result_value = { /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_value.map_or(0, |pre_value| { - let buf = pre_value.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + let prev_value = prev_value.map_or(0, |prev_value| { + let buf = prev_value.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let delta_buf = proposal.params().as_ref().unwrap().as_slice(); @@ -722,7 +700,7 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let value = pre_value + delta; + let value = prev_value + delta; ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() @@ -731,13 +709,13 @@ mod GroupDecService { let result_state_id = { state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) .await .expect( format!( "set_with_path {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), @@ -746,34 +724,11 @@ mod GroupDecService { format!( "commit {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), ) - // let mut sub_folder_value = result_value; - // for (parent_single_op_env, folder, sub_folder_prev_value) in - // single_op_envs.into_iter().rev() - // { - // parent_single_op_env - // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - // .await - // .expect( - // format!( - // "update folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // sub_folder_value = parent_single_op_env.commit().await.expect( - // format!( - // "commit folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // } - // sub_folder_value }; let receipt = { @@ -791,11 +746,11 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_value + proposal + context + * (result_state_id, return_object) = prev_value + proposal + context */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id), + result_state_id: Some(result_state_id.root), receipt, }) } @@ -803,21 +758,21 @@ mod GroupDecService { pub async fn verify( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult { + ) -> BuckyResult<()> { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context + * == prev_state_id + proposal + execute_result.context */ let result = self - .execute(proposal, pre_state_id, object_map_processor) + .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", - pre_state_id, + prev_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), @@ -830,7 +785,11 @@ mod GroupDecService { && execute_result.context.is_none() && execute_result.receipt.is_none(); - Ok(is_ok) + if is_ok { + Ok(()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "result unmatch")) + } } } @@ -839,31 +798,36 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id, object_map_processor) + self.execute(proposal, prev_state_id, object_map_processor) .await } async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, object_map_processor, execute_result) - .await + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<()> { + self.verify( + proposal, + prev_state_id, + object_map_processor, + execute_result, + ) + .await } async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 @@ -872,16 +836,16 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = match pre_state_id { - Some(pre_state_id) => { + let prev_value = match prev_state_id { + Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&pre_state_id) + .load(*prev_state_id) .await - .expect(format!("load {} failed", pre_state_id).as_str()); + .expect(format!("load {} failed", prev_state_id).as_str()); state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -892,21 +856,21 @@ mod GroupDecService { } None => None, } - .map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + .map_or(0, |prev_state_id| { + let buf = prev_state_id.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let result_value = match execute_result.result_state_id { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&result_state_id) + .load(result_state_id) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -932,7 +896,7 @@ mod GroupDecService { "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, - pre_value, + prev_value, result_value, proposal_id, block.block_id(), @@ -942,10 +906,6 @@ mod GroupDecService { let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); assert!(is_new_finished); } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() - } } } @@ -982,6 +942,7 @@ async fn main_run() { cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) .exit_on_panic(true) + .dingtalk_bug_report("any value to disable") .build() .start(); @@ -1004,9 +965,12 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec = vec![]; + let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; + let mut group_mgrs: Vec = vec![]; + let mut rpc_port = 32217_u16; + let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { - let cyfs_stack = create_stack( + let (cyfs_stack, shared_stack) = create_stack( admin, private_key, device, @@ -1020,33 +984,34 @@ async fn main_run() { .collect(), &group, &dec_app, + rpc_port, + ws_port, ) .await; - admin_stacks.push(cyfs_stack); + admin_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; } async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { - let stack = admin_stacks.get(i).unwrap(); + let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); - DecService::run( - &stack, - admin.name().unwrap().to_string(), - dec_app_id.clone(), - ) - .await; - - let service = stack - .group_mgr() - .find_rpath_service( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, + let local_name = admin.name().unwrap(); + let group_mgr = + DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; + + let service = group_mgr + .start_rpath_service( + group.desc().object_id(), + EXAMPLE_RPATH.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), ) .await .unwrap(); + + group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1057,7 +1022,8 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, @@ -1066,42 +1032,31 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); - let noc = stack.noc_manager().clone(); + let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); let proposal_any = Arc::new(AnyNamedObject::Core( TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), )); - let req = NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: dec_app_id.object_id().clone(), - verified: None, + let req = NONPutObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: None, + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: Some(AccessString::full().value()), + access: Some(AccessString::full()), }; - noc.put_object(&req).await; + noc.put_object(req).await; proposals.push(proposal); } @@ -1112,20 +1067,15 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); async_std::task::spawn(async move { - service.push_proposal(proposal).await.unwrap(); + service.push_proposal(&proposal).await.unwrap(); }); if i % 10 == 0 { @@ -1136,27 +1086,25 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - let client = admin_stacks - .get(0) - .unwrap() - .group_mgr() - .rpath_client( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - ) - .await - .unwrap(); - - let value_obj = client - .get_by_path(EXAMPLE_VALUE_PATH.as_str()) - .await - .unwrap(); - let buf = value_obj.as_ref().unwrap().object_id.data(); - let mut value = [0u8; 8]; - value.copy_from_slice(&buf[..8]); - - log::info!("value from client is: {}", u64::from_be_bytes(value)); + // let client = group_mgrs + // .get(0) + // .unwrap() + // .rpath_client( + // &group.desc().object_id(), + // dec_app_id.object_id(), + // &EXAMPLE_RPATH, + // ) + // .await; + + // let value_obj = client + // .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + // .await + // .unwrap(); + // let buf = value_obj.as_ref().unwrap().object_id.data(); + // let mut value = [0u8; 8]; + // value.copy_from_slice(&buf[..8]); + + // log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From 7b1907c7966588e33f7543f2285cbb1fb5162eb1 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 280/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/service/ood-daemon/src/config/system_config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index ceb3344e9..670ea5832 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -62,6 +62,13 @@ impl SystemConfig { let node = Self::load_as_toml(&config_file)?; + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) + } + self.parse_config(node).await } @@ -206,4 +213,3 @@ pub async fn reload_system_config() -> BuckyResult { pub fn get_system_config() -> Arc { SYSTEM_CONFIG.lock().unwrap().clone().unwrap() -} \ No newline at end of file From 157016a7e5360054b5edec414eb5869820a3d0e1 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 281/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/service/ood-daemon/src/config/system_config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 670ea5832..e27890656 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -3,6 +3,7 @@ use super::version::{ServiceListVersion, ServiceVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -64,8 +65,6 @@ impl SystemConfig { self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } From f062ba091a45dd83c60018dc5c04dd7c6f999073 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 282/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index e11695ad5..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1811,6 +1811,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1824,6 +1825,7 @@ dependencies = [ "semver 1.0.16", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1873,6 +1875,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.1" @@ -2226,6 +2287,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -3314,6 +3377,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.15" From fca07e7a474d148053c2fffb04a8e441a999da93 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 283/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From bf1d1b6465ab37da53c346bedfe1f578db92a239 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 14:48:12 +0800 Subject: [PATCH 284/553] Adapte to the buckyos --- .../engine/storage_engine_group_state.rs | 44 ++++++++++++++++--- .../cyfs-group/src/storage/group_storage.rs | 9 +++- src/meta/cyfs-meta/src/executor/view.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 029b09e78..cf04e93ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -19,6 +19,8 @@ const ACCESS: Option = None; #[derive(Clone)] pub struct StorageEngineGroupState { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, state_path: Arc, } @@ -183,18 +185,28 @@ impl StorageEngineGroupState { Ok(cache) } - pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + pub fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: GroupStatePath, + group_id: ObjectId, + dec_id: ObjectId, + ) -> Self { Self { state_mgr, state_path: Arc::new(state_path), + group_id, + dec_id, } } pub async fn create_writer(&self) -> BuckyResult { - Ok( - StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) - .await?, + Ok(StorageEngineGroupStateWriter::new( + self.state_mgr.clone(), + self.state_path.clone(), + self.group_id, + self.dec_id, ) + .await?) } pub fn root_cache(&self) -> &ObjectMapRootCacheRef { @@ -218,6 +230,8 @@ impl StorageEngine for StorageEngineGroupState { #[derive(Clone)] pub struct StorageEngineGroupStateWriter { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, op_env: ObjectMapPathOpEnvRef, prepare_op_env: ObjectMapSingleOpEnvRef, @@ -230,6 +244,8 @@ impl StorageEngineGroupStateWriter { async fn new( state_mgr: ObjectMapRootManagerRef, state_path: Arc, + group_id: ObjectId, + dec_id: ObjectId, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; @@ -237,7 +253,11 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(group_id), + Some(dec_id), + ) .await?; None } else { @@ -254,6 +274,8 @@ impl StorageEngineGroupStateWriter { state_mgr, prepare_map_id, write_result: Ok(()), + group_id, + dec_id, }) } @@ -264,7 +286,11 @@ impl StorageEngineGroupStateWriter { ) -> BuckyResult { let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; single_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(self.group_id), + Some(self.dec_id), + ) .await?; single_op_env .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) @@ -463,7 +489,11 @@ impl StorageEngineGroupStateWriter { } add_single_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new( + ObjectMapSimpleContentType::Set, + Some(self.group_id), + Some(self.dec_id), + ) .await?; } else { add_single_op_env diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a762c1b6..78af14c4b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -81,6 +81,8 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), + group_id.clone(), + dec_id.clone(), ), local_device_id, cache: StorageCacheInfo::new(None), @@ -138,7 +140,12 @@ impl GroupStorage { rpath: rpath.to_string(), non_driver, group_chunk_id: group_chunk_id.object_id(), - storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + state_path, + group_id.clone(), + dec_id.clone(), + ), local_device_id, cache, object_map_processor, diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 7d76e9fcc..47e3c8a7d 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -5,7 +5,7 @@ use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; use crate::stat::Stat; use crate::state_storage::{StateRef, StateWeakRef}; -use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base::{BuckyResult, RawConvertTo, ObjectId}; use cyfs_base_meta::*; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; From 81a6b138b49f50dba3cdb75f5eb13c2f63a727bb Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 18:53:20 +0800 Subject: [PATCH 285/553] Adapt interface of RootState, add param(owner) --- src/tests/group-example/src/main.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 361bfd35a..01d57996b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -547,8 +547,8 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, SharedCyfsStack, + CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, + RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -677,7 +677,12 @@ mod GroupDecService { } None => { state_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new_with_option( + ObjectMapSimpleContentType::Map, + &CreateObjectMapOption::new_with_owner( + proposal.rpath().group_id().clone(), + ), + ) .await .expect( format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), From 4105195a9a82404d7da315d769c232f3fb585d1d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 15:13:47 +0800 Subject: [PATCH 286/553] Testcase for client --- .../cyfs-core/src/group/group_proposal.rs | 1 - .../cyfs-group/src/dec/rpath_service.rs | 20 +- src/tests/group-example/src/main.rs | 231 ++++++++++++------ 3 files changed, 175 insertions(+), 77 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 508418f7b..e011afdf7 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,7 +1,6 @@ use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; -use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index 1f2e836a1..47bd1ffd7 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,8 +1,12 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{ + AnyNamedObject, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + RsaCPUObjectSigner, TypelessCoreObject, +}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; +use cyfs_lib::NONObjectInfo; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, @@ -15,6 +19,7 @@ struct RPathServiceRaw { network_sender: crate::network::Sender, pending_proposal_handle: PendingProposalHandler, hotstuff: Hotstuff, + non_driver: NONDriverHelper, } #[derive(Clone)] @@ -44,7 +49,7 @@ impl RPathService { store, signer, network_sender.clone(), - non_driver, + non_driver.clone(), pending_proposal_consumer, event_notifier, rpath.clone(), @@ -56,6 +61,7 @@ impl RPathService { local_id, rpath, hotstuff, + non_driver, }; Ok(Self(Arc::new(raw))) @@ -71,6 +77,16 @@ impl RPathService { self.rpath(), proposal.desc().object_id() ); + + let object_raw = proposal.to_vec()?; + let any_obj = + AnyNamedObject::Core(TypelessCoreObject::clone_from_slice(object_raw.as_slice())?); + let non_obj = NONObjectInfo::new( + proposal.desc().object_id(), + object_raw, + Some(Arc::new(any_obj)), + ); + self.0.non_driver.put_object(non_obj).await?; self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 01d57996b..b913490f2 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -8,9 +8,9 @@ use cyfs_base::{ use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, - NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, - RequestProtocol, RequestSourceInfo, SharedCyfsStack, + CyfsStackRequestorType, DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, + NONOutputRequestCommon, NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, + NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; @@ -473,7 +473,7 @@ mod Common { dec_app: &DecApp, rpc_port: u16, ws_port: u16, - ) -> (CyfsStack, SharedCyfsStack) { + ) -> (Box, Box) { let params = init_stack_params( people, private_key, @@ -488,20 +488,23 @@ mod Common { log::info!("cyfs-stack.open"); - let stack = CyfsStack::open(params.0, params.1, params.2) - .await - .map_err(|e| { - log::error!("stack start failed: {}", e); - e - }) - .unwrap(); + let stack = Box::new( + CyfsStack::open(params.0, params.1, params.2) + .await + .map_err(|e| { + log::error!("stack start failed: {}", e); + e + }) + .unwrap(), + ); async_std::task::sleep(Duration::from_millis(1000)).await; - let shared_stack = + let shared_stack = Box::new( SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) .await - .unwrap(); + .unwrap(), + ); shared_stack.wait_online(None).await.unwrap(); @@ -539,7 +542,7 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; use cyfs_group_lib::{ @@ -548,7 +551,8 @@ mod GroupDecService { }; use cyfs_lib::{ CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, - RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, + RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, + RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -561,50 +565,82 @@ mod GroupDecService { cyfs_stack: &SharedCyfsStack, local_name: String, dec_app_id: DecAppId, + group_id: ObjectId, + rpath: &str, ) -> GroupManager { let group_mgr = GroupManager::open( cyfs_stack.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), + Box::new(GroupRPathDelegateFactory { + local_name: local_name.clone(), + }), &cyfs_lib::CyfsStackRequestorType::Http, ) .await .unwrap(); - // let source = RequestSourceInfo { - // protocol: todo!(), - // zone: todo!(), - // dec: todo!(), - // verified: todo!(), - // }; + let filter = format!("obj_type == {}", CoreObjectType::GroupProposal as u16,); + let routine = ProposalListener { + service: group_mgr + .start_rpath_service( + group_id, + rpath.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), + ) + .await + .unwrap(), + local_name, + }; - // cyfs_stack - // .router_handlers() - // .handlers(&RouterHandlerChain::PostRouter) - // .post_object() - // .add_handler(RouterHandler::new()); + cyfs_stack + .router_handlers() + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-proposal-listener-{}", dec_app_id).as_str(), + 0, + Some(filter), + Some("group-proposal".to_string()), + RouterHandlerAction::Pass, + Some(Box::new(routine)), + ) + .await + .unwrap(); group_mgr } } - // pub struct PostProposalRoutine { - // service: RPathService, - // } + pub struct ProposalListener { + service: RPathService, + local_name: String, + } - // #[async_trait::async_trait] - // impl EventListenerAsyncRoutine - // for PostProposalRoutine - // { - // async fn call( - // &self, - // param: &NONPostObjectInputRequest, - // ) -> BuckyResult { - // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; - // assert_eq!(remain.len(), 0); - // self.service.push_proposal(proposal).await?; - // Ok(NONPostObjectInputResponse { object: None }) - // } - // } + #[async_trait::async_trait] + impl EventListenerAsyncRoutine + for ProposalListener + { + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + log::info!( + "recv proposal {} from {:?}, local: {}", + param.request.object.object_id, + param.request.common.source.zone, + self.local_name + ); + + let (proposal, remain) = + GroupProposal::raw_decode(param.request.object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + self.service.push_proposal(&proposal).await.unwrap(); + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: None, + }) + } + } pub struct GroupRPathDelegateFactory { local_name: String, @@ -939,6 +975,8 @@ fn create_proposal( async fn main_run() { log::info!("main_run"); + async_std::task::sleep(Duration::from_millis(10000)).await; + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -972,8 +1010,10 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; - let mut group_mgrs: Vec = vec![]; + let mut admin_stacks: Vec<(Box, Box)> = vec![]; + let mut admin_group_mgrs: Vec = vec![]; + let mut member_stacks: Vec<(Box, Box)> = vec![]; + let mut member_group_mgrs: Vec = vec![]; let mut rpc_port = 32217_u16; let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { @@ -1000,25 +1040,60 @@ async fn main_run() { ws_port += 1; } + for ((member, _), (device, private_key)) in members.iter() { + let (cyfs_stack, shared_stack) = create_stack( + member, + private_key, + device, + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + &group, + &dec_app, + rpc_port, + ws_port, + ) + .await; + member_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; + } + async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); let local_name = admin.name().unwrap(); - let group_mgr = - DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; - - let service = group_mgr - .start_rpath_service( - group.desc().object_id(), - EXAMPLE_RPATH.to_string(), - Box::new(MyRPathDelegate::new(local_name.to_string())), - ) - .await - .unwrap(); - group_mgrs.push(group_mgr); + let group_mgr = DecService::run( + &shared_stack, + local_name.to_string(), + dec_app_id.clone(), + group_id, + EXAMPLE_RPATH.as_str(), + ) + .await; + + admin_group_mgrs.push(group_mgr); + } + + for i in 0..member_stacks.len() { + let (_, shared_stack) = member_stacks.get(i).unwrap(); + let ((member, _), _) = members.get(i).unwrap(); + let group_mgr = GroupManager::open_as_client( + shared_stack.as_ref().clone(), + &CyfsStackRequestorType::WebSocket, + ) + .await + .unwrap(); + + member_group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1029,9 +1104,9 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let owner = &members.get(i % members.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, owner.desc().object_id(), @@ -1039,11 +1114,6 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); - let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); @@ -1073,16 +1143,29 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); + let stack = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let ((member, _), _) = members.get(i % members.len()).unwrap(); + let local_name = member.name().map(|n| n.to_string()); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); + let client = group_mgr + .rpath_client(group_id, dec_app_id.clone(), &EXAMPLE_RPATH) + .await; async_std::task::spawn(async move { - service.push_proposal(&proposal).await.unwrap(); + log::info!( + "client {:?} will post proposal {}", + local_name, + proposal.desc().object_id(), + ); + + let result = client.post_proposal(&proposal).await; + log::info!( + "client {:?} post proposal {}, result: {:?}", + local_name, + proposal.desc().object_id(), + result.map(|o| o.map(|o| o.object_id)) + ); }); if i % 10 == 0 { @@ -1093,7 +1176,7 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - // let client = group_mgrs + // let client = admin_group_mgrs // .get(0) // .unwrap() // .rpath_client( From ebbba0d6cc5830b6af96b3e6a0792b8700980080 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 16:50:54 +0800 Subject: [PATCH 287/553] Split the function AnyNamedObject::raw_decode to little. --- src/component/cyfs-base/src/objects/any.rs | 295 +++++++++++---------- 1 file changed, 159 insertions(+), 136 deletions(-) diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index 38698c7f9..09bfde2aa 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -340,6 +340,151 @@ impl AnyNamedObject { pub fn nonce(&self) -> &Option { match_any_obj!(self, o, { o.nonce() }, _chunk_id, { &None }) } + + fn raw_decode_device<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (device, buf) = Device::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/device error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Device(device)), + buf, + )) + } + + fn raw_decode_people<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (people, buf) = People::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/people error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::People(people)), + buf, + )) + } + + fn raw_decode_app_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::AppGroup(app_group)), + buf, + )) + } + + fn raw_decode_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (group, buf) = Group::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/group error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Group(group)), buf)) + } + + fn raw_decode_union_account<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/ua error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::UnionAccount(ua)), + buf, + )) + } + + fn raw_decode_file<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (file, buf) = File::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/file error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::File(file)), buf)) + } + + fn raw_decode_dir<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (dir, buf) = Dir::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/dir error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Dir(dir)), buf)) + } + + fn raw_decode_diff<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (diff, buf) = Diff::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/diff error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Diff(diff)), buf)) + } + + fn raw_decode_proof_of_service<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (prof, buf) = ProofOfService::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/prof error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::ProofOfService(prof)), + buf, + )) + } + + fn raw_decode_tx<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (tx, buf) = Tx::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/tx error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Tx(tx)), buf)) + } + + fn raw_decode_action<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (action, buf) = Action::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/action error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Action(action)), + buf, + )) + } + + fn raw_decode_object_map<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (relation, buf) = ObjectMap::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/relation error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::ObjectMap(relation)), + buf, + )) + } + + fn raw_decode_contract<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (contract, buf) = Contract::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/contract error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Contract(contract)), + buf, + )) + } + + fn raw_decode_custom<'de>( + buf: &'de [u8], + is_dec_app_object: bool, + ) -> Result<(Self, &'de [u8]), BuckyError> { + if is_dec_app_object { + // println!("is dec app object"); + + let (dec_obj, buf) = TypelessDECAppObject::raw_decode(buf)?; + Ok((AnyNamedObject::DECApp(dec_obj), buf)) + } else { + // println!("is core object"); + + let (core_obj, buf) = TypelessCoreObject::raw_decode(buf)?; + Ok((AnyNamedObject::Core(core_obj), buf)) + } + } } impl RawEncode for AnyNamedObject { @@ -372,146 +517,24 @@ impl<'de> RawDecode<'de> for AnyNamedObject { })?; match obj_type_info.obj_type_code() { - ObjectTypeCode::Device => { - let (device, buf) = Device::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/device error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Device(device)), - buf, - )); - } - ObjectTypeCode::People => { - let (people, buf) = People::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/people error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::People(people)), - buf, - )); - } - ObjectTypeCode::Org => { - let (org, buf) = Org::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/org error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); - } - ObjectTypeCode::AppGroup => { - let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::AppGroup(app_group)), - buf, - )); - } - ObjectTypeCode::SimpleGroup => { - let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), - buf, - )); - } - ObjectTypeCode::UnionAccount => { - let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/ua error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::UnionAccount(ua)), - buf, - )); - } + ObjectTypeCode::Device => Self::raw_decode_device(buf), + ObjectTypeCode::People => Self::raw_decode_people(buf), + ObjectTypeCode::AppGroup => Self::raw_decode_app_group(buf), + ObjectTypeCode::Group => Self::raw_decode_group(buf), + ObjectTypeCode::UnionAccount => Self::raw_decode_union_account(buf), ObjectTypeCode::Chunk => { unreachable!(); } - ObjectTypeCode::File => { - let (file, buf) = File::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/file error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::File(file)), buf)); - } - ObjectTypeCode::Dir => { - let (dir, buf) = Dir::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/dir error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Dir(dir)), buf)); - } - ObjectTypeCode::Diff => { - let (diff, buf) = Diff::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/diff error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Diff(diff)), buf)); - } - ObjectTypeCode::ProofOfService => { - let (prof, buf) = ProofOfService::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/prof error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::ProofOfService(prof)), - buf, - )); - } - ObjectTypeCode::Tx => { - let (tx, buf) = Tx::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/tx error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Tx(tx)), buf)); - } - ObjectTypeCode::Action => { - let (action, buf) = Action::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/action error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Action(action)), - buf, - )); - } - ObjectTypeCode::ObjectMap => { - let (relation, buf) = ObjectMap::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/relation error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::ObjectMap(relation)), - buf, - )); - } - ObjectTypeCode::Contract => { - let (contract, buf) = Contract::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/contract error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Contract(contract)), - buf, - )); - } + ObjectTypeCode::File => Self::raw_decode_file(buf), + ObjectTypeCode::Dir => Self::raw_decode_dir(buf), + ObjectTypeCode::Diff => Self::raw_decode_diff(buf), + ObjectTypeCode::ProofOfService => Self::raw_decode_proof_of_service(buf), + ObjectTypeCode::Tx => Self::raw_decode_tx(buf), + ObjectTypeCode::Action => Self::raw_decode_action(buf), + ObjectTypeCode::ObjectMap => Self::raw_decode_object_map(buf), + ObjectTypeCode::Contract => Self::raw_decode_contract(buf), ObjectTypeCode::Custom => { - return if obj_type_info.is_decapp_object() { - // println!("is dec app object"); - - let (dec_obj, buf) = TypelessDECAppObject::raw_decode(buf)?; - Ok((AnyNamedObject::DECApp(dec_obj), buf)) - } else { - // println!("is core object"); - - let (core_obj, buf) = TypelessCoreObject::raw_decode(buf)?; - Ok((AnyNamedObject::Core(core_obj), buf)) - }; + Self::raw_decode_custom(buf, obj_type_info.is_decapp_object()) } } } From 50b2bd3870416108724510e5fca0053d65444521 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 19:22:40 +0800 Subject: [PATCH 288/553] Change sync services packages from parallel to serial --- src/Cargo.lock | 142 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 32 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 55ede95d7..0d57f25d7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1514,7 +1514,7 @@ dependencies = [ "simple_logger 2.3.0", "sqlx", "url 2.3.0", - "zip 0.6.3", + "zip", ] [[package]] @@ -1769,6 +1769,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1781,6 +1782,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1830,6 +1832,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.8", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.8", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.0" @@ -2180,6 +2241,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -2197,7 +2260,7 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.3", + "prost 0.11.8", "prost-build 0.11.3", "protoc-bin-vendored", "rand 0.8.5", @@ -2208,7 +2271,7 @@ dependencies = [ "sqlx", "tide", "toml", - "zip 0.6.3", + "zip", ] [[package]] @@ -2352,7 +2415,7 @@ dependencies = [ "url 2.3.0", "walkdir", "winapi", - "zip 0.6.3", + "zip", ] [[package]] @@ -3229,6 +3292,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.8", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.14" @@ -4480,7 +4572,7 @@ dependencies = [ "serde_json", "tide", "toml", - "zip 0.6.3", + "zip", ] [[package]] @@ -4592,7 +4684,7 @@ dependencies = [ "sha2 0.8.2", "simple_logger 2.3.0", "walkdir", - "zip 0.6.3", + "zip", ] [[package]] @@ -5040,12 +5132,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.3" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b18e655c21ff5ac2084a5ad0611e827b3f92badf79f4910b5a5c58f4d87ff0" +checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" dependencies = [ "bytes 1.2.1", - "prost-derive 0.11.2", + "prost-derive 0.11.8", ] [[package]] @@ -5082,7 +5174,7 @@ dependencies = [ "multimap", "petgraph", "prettyplease", - "prost 0.11.3", + "prost 0.11.8", "prost-types 0.11.2", "regex", "syn", @@ -5105,9 +5197,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.2" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" +checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" dependencies = [ "anyhow", "itertools", @@ -5133,7 +5225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" dependencies = [ "bytes 1.2.1", - "prost 0.11.3", + "prost 0.11.8", ] [[package]] @@ -7605,23 +7697,9 @@ dependencies = [ [[package]] name = "zip" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" -dependencies = [ - "byteorder", - "bzip2", - "crc32fast", - "flate2", - "thiserror", - "time 0.1.44", -] - -[[package]] -name = "zip" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" dependencies = [ "aes 0.7.5", "byteorder", @@ -7639,13 +7717,13 @@ dependencies = [ [[package]] name = "zip-extract" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c5cc0309f6e81ab96c2b43d5e935025f8732c886690be8f78f68e06bad1d274" +checksum = "bb654964c003959ed64cbd0d7b329bcdcbd9690facd50c8617748d3622543972" dependencies = [ "log 0.4.17", "thiserror", - "zip 0.5.13", + "zip", ] [[package]] From 8bf966cdcca9018a799b3bf2a3692394cbdec06e Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 19:22:40 +0800 Subject: [PATCH 289/553] Change sync services packages from parallel to serial --- src/Cargo.lock | 1 - src/service/ood-daemon/Cargo.toml | 1 - .../ood-daemon/src/service/service_manager.rs | 36 +++++++++---------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 0d57f25d7..d52e953bf 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4556,7 +4556,6 @@ dependencies = [ "cyfs-debug", "cyfs-lib", "cyfs-meta-lib", - "cyfs-stack-loader", "cyfs-util", "fs_extra", "futures", diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index cd8398ccb..c0c092df8 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -18,7 +18,6 @@ cyfs-meta-lib = { path = "../../component/cyfs-meta-lib" } cyfs-client = { path = "../../tools/cyfs-client" } cyfs-lib = { path = "../../component/cyfs-lib" } ood-control = { path = "../ood-control" } -cyfs-stack-loader = { path = "../../component/cyfs-stack-loader" } lazy_static = "1.4" serde = "1.0" serde_json = "1.0" diff --git a/src/service/ood-daemon/src/service/service_manager.rs b/src/service/ood-daemon/src/service/service_manager.rs index 15a9d35b2..2d1540057 100644 --- a/src/service/ood-daemon/src/service/service_manager.rs +++ b/src/service/ood-daemon/src/service/service_manager.rs @@ -1,13 +1,3 @@ -use async_std::sync::Mutex as AsyncMutex; -use cyfs_lib::ZoneRole; -use futures::future::join_all; -use lazy_static::lazy_static; -use std::fmt; -use std::fmt::Formatter; -use std::path::PathBuf; -use std::sync::Arc; -use std::{collections::HashMap, str::FromStr}; - use super::service::Service; use super::service_info::ServicePackageLocalState; use crate::config::*; @@ -15,6 +5,15 @@ use crate::daemon::GATEWAY_MONITOR; use crate::status::*; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult}; use cyfs_debug::Mutex; +use cyfs_lib::ZoneRole; + +use async_std::sync::Mutex as AsyncMutex; +use lazy_static::lazy_static; +use std::fmt; +use std::fmt::Formatter; +use std::path::PathBuf; +use std::sync::Arc; +use std::{collections::HashMap, str::FromStr}; #[derive(Clone)] pub struct ServiceItem { @@ -465,26 +464,25 @@ impl ServiceManager { debug!("will sync all service packages"); - let mut futures = Vec::new(); - let service_list = self.service_list.lock().unwrap().clone(); for (name, service_info) in service_list { if service_info.service.is_none() { - error!("service not init! name={}", name); + error!("service not init yet! name={}", name); continue; } if service_info.target_state() == ServiceState::Run { - futures.push(Self::sync_service_package(service_info)); + if let Err(e) = Self::sync_service_package(&service_info).await { + error!( + "sync service package failed! service={}, {}", + service_info.config.name, e + ); + } } } - - if !futures.is_empty() { - let _ret = join_all(futures).await; - } } - async fn sync_service_package(service_info: ServiceItem) -> BuckyResult<()> { + async fn sync_service_package(service_info: &ServiceItem) -> BuckyResult<()> { let service = service_info.service.as_ref().unwrap(); match service.sync_package().await { Ok(changed) => { From b373905a9da00d653ff50ca2f8a6aa54568516d5 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 21 Feb 2023 20:07:44 +0800 Subject: [PATCH 290/553] Add check mechanism to noc meta db in case of main table missing --- src/component/cyfs-noc/src/meta/sqlite/db.rs | 96 +++++++++++++++++-- src/component/cyfs-noc/src/meta/sqlite/mod.rs | 3 + .../cyfs-noc/src/meta/sqlite/test.rs | 29 ++++++ src/component/cyfs-noc/src/noc/test.rs | 2 +- src/component/cyfs-util/src/util/db_helper.rs | 5 +- 5 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 src/component/cyfs-noc/src/meta/sqlite/test.rs diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index bad4aa5d1..c68074401 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -58,9 +58,26 @@ impl SqliteMetaStorage { conn: SqliteConnectionHolder::new(data_file), }; - if !file_exists { + let valid = if file_exists { + ret.check_db_valid().map_err(|e| { + error!( + "check noc sqlite meta db valid but got error! file={}, {}", + ret.data_file.display(), + e + ); + e + })? + } else { + false + }; + + if !valid { if let Err(e) = ret.init_db() { - error!("init noc sqlite meta db error! now will delete file, {}", e); + error!( + "init noc sqlite meta db error! now will delete file, file={}, {}", + ret.data_file.display(), + e + ); Self::remove_db_file(&ret.data_file, &ret.data_dir); return Err(e); @@ -84,11 +101,52 @@ impl SqliteMetaStorage { } } + fn check_db_valid(&self) -> BuckyResult { + let sql = + "SELECT name FROM sqlite_master WHERE type='table' AND name='data_namedobject_meta'"; + let ret = { + let (conn, _lock) = self.conn.get_read_conn()?; + + conn.query_row(&sql, [], |row| { + let name: String = row.get(0).unwrap(); + Ok(name) + }) + .optional() + .map_err(|e| { + let msg = format!("noc meta check tables error! sql={}, {}", sql, e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::SqliteError, msg) + })? + }; + + match ret { + Some(name) => { + info!( + "check noc meta db file success! file={}, table={}", + self.data_file.display(), + name + ); + Ok(true) + } + None => { + error!( + "check noc meta db file but main table not exists! file={}", + self.data_file.display() + ); + Ok(false) + } + } + } + fn init_db(&self) -> BuckyResult<()> { let (mut conn, _lock) = self.conn.get_write_conn()?; let tx = conn.transaction().map_err(|e| { - let msg = format!("noc meta db transaction error: {}", e); + let msg = format!( + "noc meta db transaction error: file={}, {}", + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) @@ -98,7 +156,12 @@ impl SqliteMetaStorage { for sql in INIT_NAMEDOBJECT_META_SQL_LIST.iter() { info!("will exec: {}", sql); tx.execute(&sql, []).map_err(|e| { - let msg = format!("init noc table error! sql={}, {}", sql, e); + let msg = format!( + "init noc table error! sql={}, file={}, {}", + sql, + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; @@ -109,15 +172,25 @@ impl SqliteMetaStorage { if ret.is_ok() { tx.commit().map_err(|e| { - let msg = format!("commit init transaction error: {}", e); + let msg = format!( + "commit init transaction error: file={}, {}", + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; - info!("init noc sqlite meta db success!"); - + info!( + "init noc sqlite meta db success! file={}", + self.data_file.display() + ); } else { tx.rollback().map_err(|e| { - let msg = format!("rollback init transaction error: {}", e); + let msg = format!( + "rollback init transaction error: file={}, {}", + self.data_file.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::SqliteError, msg) })?; @@ -133,7 +206,12 @@ impl SqliteMetaStorage { let old = Self::get_db_version(&conn)?; if old < CURRENT_VERSION { - info!("will update noc meta db: {} -> {}", old, CURRENT_VERSION); + info!( + "will update noc meta db: file={}, {} -> {}", + self.data_file.display(), + old, + CURRENT_VERSION + ); self.backup_db_file(old)?; diff --git a/src/component/cyfs-noc/src/meta/sqlite/mod.rs b/src/component/cyfs-noc/src/meta/sqlite/mod.rs index 017760bc3..93cf2f05c 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/mod.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/mod.rs @@ -2,5 +2,8 @@ mod sql; mod db; mod data; +#[cfg(test)] +mod test; + pub(crate) use db::*; pub(crate) use data::*; \ No newline at end of file diff --git a/src/component/cyfs-noc/src/meta/sqlite/test.rs b/src/component/cyfs-noc/src/meta/sqlite/test.rs new file mode 100644 index 000000000..2a70326d2 --- /dev/null +++ b/src/component/cyfs-noc/src/meta/sqlite/test.rs @@ -0,0 +1,29 @@ +use super::db::*; +use crate::meta::*; +use cyfs_base::*; +use cyfs_lib::*; + +async fn test_meta() { + let dir = cyfs_util::get_temp_path().join("test_noc_meta"); + if !dir.is_dir() { + std::fs::create_dir_all(&dir).unwrap(); + } + + let meta = SqliteMetaStorage::new(&dir).unwrap(); + + let req = NamedObjectMetaExistsObjectRequest { + source: RequestSourceInfo::new_local_system(), + object_id: ObjectId::default(), + }; + let ret = meta.exists_object(&req).await.unwrap(); + assert!(!ret); +} + +#[test] +fn main() { + cyfs_base::init_simple_log("cyfs-noc-test-meta", Some("debug")); + + async_std::task::block_on(async move { + test_meta().await; + }); +} diff --git a/src/component/cyfs-noc/src/noc/test.rs b/src/component/cyfs-noc/src/noc/test.rs index 835d8fc30..63184f65d 100644 --- a/src/component/cyfs-noc/src/noc/test.rs +++ b/src/component/cyfs-noc/src/noc/test.rs @@ -244,7 +244,7 @@ async fn test_error_blob() { let resp = noc.get_object(&get_req).await.unwrap(); let data = resp.unwrap(); - let data = Storage::raw_decode(&data.object.object_raw).unwrap(); + let _data = Storage::raw_decode(&data.object.object_raw).unwrap(); info!("test complete!"); } diff --git a/src/component/cyfs-util/src/util/db_helper.rs b/src/component/cyfs-util/src/util/db_helper.rs index 0c0d4f2e8..b6a1c1c2f 100644 --- a/src/component/cyfs-util/src/util/db_helper.rs +++ b/src/component/cyfs-util/src/util/db_helper.rs @@ -64,9 +64,10 @@ impl SqliteConnectionHolder { })?; info!( - "open db for thread={:?}, file={}", + "open db for thread={:?}, file={}, read={}", std::thread::current().id(), - self.data_file.display() + self.data_file.display(), + read_only, ); assert!(conn.is_autocommit()); From cc6dc584c2d92ae1d4c0390babd4dbc8fc391cfc Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 13:27:04 +0800 Subject: [PATCH 291/553] Add api edition relate header to requestors --- src/component/cyfs-base/src/base/protocol_fields.rs | 2 ++ src/component/cyfs-lib/src/base/protocol.rs | 1 + src/component/cyfs-lib/src/requestor/bdt.rs | 5 ++++- src/component/cyfs-lib/src/requestor/requestor.rs | 10 ++++++++-- src/component/cyfs-lib/src/requestor/surf.rs | 4 +++- src/component/cyfs-lib/src/requestor/tcp.rs | 4 +++- src/component/cyfs-lib/src/requestor/ws.rs | 1 + 7 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-base/src/base/protocol_fields.rs b/src/component/cyfs-base/src/base/protocol_fields.rs index 378e505c9..e3de57561 100644 --- a/src/component/cyfs-base/src/base/protocol_fields.rs +++ b/src/component/cyfs-base/src/base/protocol_fields.rs @@ -1,3 +1,5 @@ +pub const CYFS_API_EDITION: &str = "cyfs-api-edition"; + pub const CYFS_OBJECT_ID: &str = "cyfs-object-id"; pub const CYFS_OBJECT: &str = "cyfs-object"; diff --git a/src/component/cyfs-lib/src/base/protocol.rs b/src/component/cyfs-lib/src/base/protocol.rs index be3e8981d..67dd57f3c 100644 --- a/src/component/cyfs-lib/src/base/protocol.rs +++ b/src/component/cyfs-lib/src/base/protocol.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +pub const CYFS_CURRENT_API_EDITION: u32 = 1; // pub const CYFS_OBJECT_MIME_STRING: &str = "application/cyfs-object"; diff --git a/src/component/cyfs-lib/src/requestor/bdt.rs b/src/component/cyfs-lib/src/requestor/bdt.rs index 2107c4653..e836dfe97 100644 --- a/src/component/cyfs-lib/src/requestor/bdt.rs +++ b/src/component/cyfs-lib/src/requestor/bdt.rs @@ -74,7 +74,10 @@ impl HttpRequestor for BdtHttpRequestor { ); // bdt_stream.display_ref_count(); - match async_h1::connect(bdt_stream, req.take().unwrap()).await { + let req = req.take().unwrap(); + let req = self.add_default_headers(req); + + match async_h1::connect(bdt_stream, req).await { Ok(resp) => { info!( "http-bdt request to {} success! during={}ms, seq={:?}", diff --git a/src/component/cyfs-lib/src/requestor/requestor.rs b/src/component/cyfs-lib/src/requestor/requestor.rs index d4b311dd0..9afb2eb59 100644 --- a/src/component/cyfs-lib/src/requestor/requestor.rs +++ b/src/component/cyfs-lib/src/requestor/requestor.rs @@ -1,8 +1,9 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, DeviceId, Endpoint}; +use crate::base::CYFS_CURRENT_API_EDITION; +use cyfs_base::*; -use http_types::{Request, Response}; use async_std::net::SocketAddr; use async_trait::async_trait; +use http_types::{Request, Response}; use std::sync::Arc; use std::time::Duration; @@ -17,6 +18,11 @@ pub trait HttpRequestor: Send + Sync { fn remote_addr(&self) -> String; fn remote_device(&self) -> Option; + fn add_default_headers(&self, mut req: Request) -> Request { + req.insert_header(CYFS_API_EDITION, CYFS_CURRENT_API_EDITION.to_string()); + req + } + async fn request(&self, req: Request) -> BuckyResult { self.request_ext(&mut Some(req), None).await } diff --git a/src/component/cyfs-lib/src/requestor/surf.rs b/src/component/cyfs-lib/src/requestor/surf.rs index aa4eefd7f..0df32a8b9 100644 --- a/src/component/cyfs-lib/src/requestor/surf.rs +++ b/src/component/cyfs-lib/src/requestor/surf.rs @@ -54,7 +54,9 @@ impl HttpRequestor for SurfHttpRequestor { ); let begin = std::time::Instant::now(); - match self.client.send(req.take().unwrap()).await { + let req = req.take().unwrap(); + let req = self.add_default_headers(req); + match self.client.send(req).await { Ok(resp) => { info!( "http request to {} success! during={}ms", diff --git a/src/component/cyfs-lib/src/requestor/tcp.rs b/src/component/cyfs-lib/src/requestor/tcp.rs index d1d4fa3a5..b76c176a6 100644 --- a/src/component/cyfs-lib/src/requestor/tcp.rs +++ b/src/component/cyfs-lib/src/requestor/tcp.rs @@ -56,7 +56,9 @@ impl HttpRequestor for TcpHttpRequestor { )); } - match async_h1::connect(tcp_stream, req.take().unwrap()).await { + let req = req.take().unwrap(); + let req = self.add_default_headers(req); + match async_h1::connect(tcp_stream, req).await { Ok(resp) => { info!( "http-tcp request to {} success! during={}ms", diff --git a/src/component/cyfs-lib/src/requestor/ws.rs b/src/component/cyfs-lib/src/requestor/ws.rs index 21bfdc87f..17a856bc9 100644 --- a/src/component/cyfs-lib/src/requestor/ws.rs +++ b/src/component/cyfs-lib/src/requestor/ws.rs @@ -88,6 +88,7 @@ impl HttpRequestor for WSHttpRequestor { // request编码到buffer let req = req.take().unwrap(); + let req = self.add_default_headers(req); let mut encoder = async_h1::client::Encoder::new(req); let mut buf = vec![]; encoder.read_to_end(&mut buf).await.map_err(|e| { From 023883bdcc2d7255915d2b270e4e29ca24f346a0 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 20:11:41 +0800 Subject: [PATCH 292/553] Fix the panic that may be caused by check db in cyfs-noc --- src/component/cyfs-noc/src/meta/sqlite/db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index c68074401..bcd8aeb1e 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -105,7 +105,7 @@ impl SqliteMetaStorage { let sql = "SELECT name FROM sqlite_master WHERE type='table' AND name='data_namedobject_meta'"; let ret = { - let (conn, _lock) = self.conn.get_read_conn()?; + let (conn, _lock) = self.conn.get_write_conn()?; conn.query_row(&sql, [], |row| { let name: String = row.get(0).unwrap(); From 1c8479a5cd3323f68de7442a3d34aebf74c0d614 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 22 Feb 2023 20:46:54 +0800 Subject: [PATCH 293/553] App-tool support change preview service version, pack script add preview version to service --- scripts/pack.js | 64 +--- src/tools/app-tool/Cargo.toml | 1 - src/tools/app-tool/src/main.rs | 569 ++++++++++----------------------- 3 files changed, 180 insertions(+), 454 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index 71acbc68e..f3676ea57 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -129,58 +129,15 @@ async function run() { } console.log(`get file repo account ${file_repo_id} balance ${balance}`) - if (type.includes("apps")) { - try { fs.rmSync('dist/app_config.cfg') } catch (error) { } - let app_config = [] - - for (const app of apps) { - if (!app.pub) { - continue - } - if (onlyput !== "onlyput") { - for (const target of targets) { - if (app.exclude && app.exclude.includes(target)) { - continue - } - if (app.include && !app.include.includes(target)) { - continue - } - let project_path = app.path || `app/${app.name}` - let config_path = app.config_file[target] || app.config_file.default - fs.copyFileSync(`${project_path}/${config_path}`, `dist/apps/${app.name}/${target}/package.cfg`) - - if (app.assets && app.assets[target]) { - for (const asset of app.assets[target]) { - fs.copyFileSync(asset.from, `dist/apps/${app.name}/${target}/${asset.to}`) - } - } - } - - child_process.execSync(`bash -c "./pack-tools -d apps/${app.name}"`, { cwd: 'dist', stdio: 'inherit' }) - } - - child_process.execSync(`cyfs-client ${action} apps/${app.name}.zip -f fid -o ${file_repo_path}`, { cwd: 'dist', stdio: 'inherit' }) - let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}); - app_config.apps.push({ "id": app.appid, "ver": `${version}`, "status": 1 }) - - // 运行app-tool,添加版本和fid - if (app.appid !== undefined) { - let cmd = `app-tool app set -v ${version} -s ${fid} ${app.appid} -o ${repo_path}`; - console.log("will run app tool cmd:", cmd) - child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) - } - - } - - fs.writeJSONSync('dist/app_config.cfg', app_config) - } - - if (type.includes("services")) { try { fs.removeSync('dist/device_config.cfg') } catch (error) { } let device_config = []; for (const service of services) { + if (!service.id) { + console.error(`service ${service.name} has no id!`); + process.exit(1); + } if (!service.pub) { continue } @@ -208,16 +165,15 @@ async function run() { } child_process.execSync(`cyfs-client ${action} services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) + + // 运行app-tool,添加版本和fid + let app_version = version + "-preview"; + let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; + console.log("will run app tool cmd:", cmd) + child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) - - // 运行app-tool,添加版本和fid - if (service.id !== undefined) { - let cmd = `app-tool app set -v ${version} -s ${fid} ${service.id} -o ${repo_path}`; - console.log("will run app tool cmd:", cmd) - child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) - } } fs.writeFileSync('dist/device-config.cfg', JSON.stringify(device_config)) diff --git a/src/tools/app-tool/Cargo.toml b/src/tools/app-tool/Cargo.toml index fbbb9619d..c938dced3 100644 --- a/src/tools/app-tool/Cargo.toml +++ b/src/tools/app-tool/Cargo.toml @@ -14,7 +14,6 @@ cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-base-meta = { path = "../../component/cyfs-base-meta" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-meta-lib = { path = "../../component/cyfs-meta-lib" } -cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-util = { path = "../../component/cyfs-util" } async-std = { version = "1.11", features = ["unstable", "attributes"] } clap = "2.34.0" diff --git a/src/tools/app-tool/src/main.rs b/src/tools/app-tool/src/main.rs index 3c3440024..a5111ce91 100644 --- a/src/tools/app-tool/src/main.rs +++ b/src/tools/app-tool/src/main.rs @@ -6,9 +6,6 @@ use cyfs_base::{ }; use cyfs_base_meta::{Data, SavedMetaObject}; use cyfs_core::{AppList, AppListObj, AppStatus, AppStatusObj, DecApp, DecAppId, DecAppObj}; -use cyfs_lib::{ - NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPutObjectRequest, SharedCyfsStack, -}; use cyfs_meta_lib::{MetaClient, MetaMinerTarget}; use lazy_static::lazy_static; use log::*; @@ -58,58 +55,6 @@ fn add_id_or_file_arg<'a, 'b>(cmd: App<'a, 'b>) -> App<'a, 'b> { ) } -async fn put_object(stack: &SharedCyfsStack, obj: &N) -where - D: ObjectType, - T: RawEncode, - N: RawConvertTo, - N: NamedObject, - ::ContentType: BodyContent, -{ - let object_id = obj.desc().calculate_id(); - match stack - .non_service() - .put_object(NONPutObjectRequest { - common: NONOutputRequestCommon::new(NONAPILevel::Router), - object: NONObjectInfo::new_from_object_raw(obj.to_vec().unwrap()).unwrap(), - access: None - }) - .await - { - Ok(_) => { - info!("put obj [{}] to ood success!", &object_id); - } - Err(e) => { - if e.code() != BuckyErrorCode::Ignored { - error!("put obj [{}] to ood failed! {}", &object_id, e); - } else { - info!("put obj [{}] to ood success!", &object_id); - } - } - } -} - -async fn put_object_ex(obj: &N) -where - D: ObjectType, - T: RawEncode, - N: RawConvertTo, - N: NamedObject, - ::ContentType: BodyContent, -{ - let cyfs_stack = match SharedCyfsStack::open_default(None).await { - Ok(stack) => Some(stack), - Err(e) => { - warn!("cannot open local stack, err {}", e); - None - } - }; - - if let Some(stack) = cyfs_stack { - put_object(&stack, obj).await; - } -} - fn get_owner(matches: &ArgMatches<'_>) -> Option<(StandardObject, PrivateKey)> { if let Some(owner_path) = matches.value_of("owner") { let ret = cyfs_util::get_desc_from_file( @@ -184,38 +129,50 @@ async fn get_list(matches: &ArgMatches<'_>) -> BuckyResult<(AppList, SaveTarget) } } +async fn get_app_from_meta(id: &ObjectId, target: &SaveTarget) -> BuckyResult { + match target { + SaveTarget::Meta(client, _) => { + match client.get_desc(&id).await { + Ok(data) => { + if let SavedMetaObject::Data(data) = data { + let app = DecApp::clone_from_slice(&data.data).unwrap(); + Ok(app) + } else { + error!("get {} from meta failed, unmatch", &id); + Err(BuckyError::from(BuckyErrorCode::NotMatch)) + } + } + Err(e) => { + error!("get {} from meta failed, err {}", &id, e); + Err(e) + } + } + }, + SaveTarget::File(_, _) => { + Err(BuckyError::from(BuckyErrorCode::NotSupport)) + } + } +} + async fn get_app(matches: &ArgMatches<'_>) -> BuckyResult<(DecApp, SaveTarget)> { + let owner = get_owner(matches); if let Some(id_str) = matches.value_of("id") { + let id = ObjectId::from_str(id_str).unwrap(); let meta_client = MetaClient::new_target( MetaMinerTarget::from_str(matches.value_of("meta_target").unwrap()).unwrap(), ); - let id = ObjectId::from_str(id_str).unwrap(); - return match meta_client.get_desc(&id).await { - Ok(data) => { - if let SavedMetaObject::Data(data) = data { - let app = DecApp::clone_from_slice(&data.data).unwrap(); - let owner = get_owner(matches); - Ok((app, SaveTarget::Meta(meta_client, owner))) - } else { - error!("get {} from meta failed, unmatch", &id); - Err(BuckyError::from(BuckyErrorCode::NotMatch)) - } - } - Err(e) => { - error!("get {} from meta failed, err {}", &id, e); - Err(e) - } - }; + let target = SaveTarget::Meta(meta_client, owner); + let app = get_app_from_meta(&id, &target).await?; + Ok((app, target)) } else if let Some(file_path) = matches.value_of("file") { let (app, _) = DecApp::decode_from_file(file_path.as_ref(), &mut vec![])?; - let owner = get_owner(matches); return Ok((app, SaveTarget::File(file_path.to_owned(), owner))); } else { let meta_client = MetaClient::new_target( MetaMinerTarget::from_str(matches.value_of("meta_target").unwrap()).unwrap(), ); - let owner = get_owner(matches); + if owner.is_none() { error!("must use owner and name when no id or file!"); return Err(BuckyError::from(BuckyErrorCode::InvalidInput)); @@ -255,55 +212,54 @@ impl SaveTarget { SaveTarget::File(_, owner) => owner.as_ref().map(|(obj, _)| obj.calculate_id()), } } -} -async fn save_obj(target: SaveTarget, obj: &N) -> BuckyResult<()> -where - D: ObjectType, - N: RawEncode, - N: NamedObject, - ::ContentType: BodyContent, -{ - match target { - SaveTarget::Meta(meta_client, owner) => { - let upload_data = SavedMetaObject::Data(Data { - id: obj.desc().calculate_id(), - data: obj.to_vec().unwrap(), - }); - - match meta_client - .update_desc( - &owner.as_ref().unwrap().0, - &upload_data, - None, - None, - &owner.as_ref().unwrap().1, - ) - .await - { - Ok(txid) => { - info!("upload obj to meta success, TxId {}", &txid); + async fn save_obj(&self, obj: &N) -> BuckyResult<()> + where + D: ObjectType, + N: RawEncode, + N: NamedObject, + ::ContentType: BodyContent, + { + match self { + SaveTarget::Meta(meta_client, owner) => { + let upload_data = SavedMetaObject::Data(Data { + id: obj.desc().calculate_id(), + data: obj.to_vec().unwrap(), + }); + + if let Some((owner, secret)) = owner { + match meta_client.update_desc(owner,&upload_data,None,None, secret).await + { + Ok(txid) => { + info!("upload obj to meta success, TxId {}", &txid); + } + Err(e) => { + error!("upload obj to meta fail, err {}", e); + return Err(e); + } + } + } else { + error!("save obj to meta but no owner desc!"); + return Err(BuckyError::from(BuckyErrorCode::InvalidParam)) + } + } + SaveTarget::File(path, _) => match obj.encode_to_file(path.as_ref(), false) { + Ok(_) => { + info!("write obj to {} success", path); } Err(e) => { - error!("upload obj to meta fail, err {}", e); - return Err(e); + info!("write obj to {} failed, err {}", path, e); + return Err(e) } - } + }, } - SaveTarget::File(path, _) => match obj.encode_to_file(path.as_ref(), false) { - Ok(_) => { - info!("write obj to {} success", path); - } - Err(e) => { - info!("write obj to {} failed, err {}", path, e); - return Err(e) - } - }, - } - Ok(()) + Ok(()) + } } + + lazy_static! { static ref DEFAULT_TARGET: String = MetaMinerTarget::default().to_string(); } @@ -320,201 +276,127 @@ async fn main_run() -> BuckyResult<()> { .long("meta_target") .default_value(&DEFAULT_TARGET) .help("meta target"); - let matches = App::new("app-tool") + let app = App::new("app-tool") .version(cyfs_base::get_version()) .about("manage app list") .subcommand( SubCommand::with_name("list") .about("create/modify/show app list object") - .subcommand( - SubCommand::with_name("create") + .subcommand(SubCommand::with_name("create") .about("create app list object") - .arg( - Arg::with_name("owner") - .short("o") - .long("owner") - .takes_value(true) - .required(true) - .help("app list owner desc/sec file"), - ) - .arg( - Arg::with_name("name") - .short("n") - .long("name") + .arg(Arg::with_name("owner") + .short("o").long("owner") + .takes_value(true).required(true) + .help("app list owner desc/sec file")) + .arg(Arg::with_name("name") + .short("n").long("name") .default_value("") - .help("app list name, default empty string"), - ) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .help("app list name, default empty string")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) - .arg( - Arg::with_name("upload") - .short("u") - .long("upload") - .help("upload app list to chain, use owner account"), - ) + .possible_values(&["app", "service"])) + .arg(Arg::with_name("upload") + .short("u").long("upload") + .help("upload app list to chain, use owner account")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("put").about("put app to app list")) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("put").about("put app to app list")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) - .arg( - Arg::with_name("appid") + .possible_values(&["app", "service"])) + .arg(Arg::with_name("appid") .short("i") - .required(true) - .takes_value(true) - .help("app id add to app list"), - ) - .arg( - Arg::with_name("appver") + .required(true).takes_value(true) + .help("app id add to app list")) + .arg(Arg::with_name("appver") .short("v") - .required(true) - .takes_value(true) - .help("app ver add to app list"), - ) - .arg( - Arg::with_name("status") - .short("s") - .long("start") - .help("start app, default false"), - ) + .required(true).takes_value(true) + .help("app ver add to app list")) + .arg(Arg::with_name("status") + .short("s").long("start") + .help("start app, default false")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg( - SubCommand::with_name("remove").about("remove app from list"), - ) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("remove").about("remove app from list")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) - .arg( - Arg::with_name("appid") + .possible_values(&["app", "service"])) + .arg(Arg::with_name("appid") .short("i") - .takes_value(true) - .required(true) - .help("remove app id"), - ) + .takes_value(true).required(true) + .help("remove app id")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("clear").about("clean all apps")) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("clear").about("clean all apps")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) + .possible_values(&["app", "service"])) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("show").about("show app list obj")) - .arg( - Arg::with_name("type") - .short("t") - .long("type") + .subcommand(add_id_or_file_arg(SubCommand::with_name("show").about("show app list obj")) + .arg(Arg::with_name("type") + .short("t").long("type") .default_value("app") - .possible_values(&["app", "service"]), - ) + .possible_values(&["app", "service"])) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg( - SubCommand::with_name("update").about("update app list from json"), - ) - .arg( - Arg::with_name("config") - .short("c") - .long("config") + .subcommand(add_id_or_file_arg(SubCommand::with_name("update").about("update app list from json")) + .arg(Arg::with_name("config") + .short("c").long("config") .takes_value(true) - .required(true), - ) - .arg( - Arg::with_name("type") - .short("t") - .long("type") - .default_value("app") - .possible_values(&["app", "service"]), - ).arg( - Arg::with_name("clear") - .long("clear") - .help("cleat list before update") - ) + .required(true)) + .arg(Arg::with_name("type").short("t").long("type").default_value("app").possible_values(&["app", "service"])) + .arg(Arg::with_name("clear").long("clear") + .help("cleat list before update")) + .arg(Arg::with_name("unpreview").long("unpreview") + .help("change app preview version to normal version")) .arg(meta_arg.clone()), ), ) - .subcommand( - SubCommand::with_name("app") + .subcommand(SubCommand::with_name("app") .about("create/modify/show app object") - .subcommand( - SubCommand::with_name("create") + .subcommand(SubCommand::with_name("create") .about("create app object") - .arg( - Arg::with_name("owner") + .arg(Arg::with_name("owner") .short("o") .long("owner") .takes_value(true) .required(true) - .help("app owner desc/sec file"), - ) - .arg( - Arg::with_name("id") + .help("app owner desc/sec file")) + .arg(Arg::with_name("id") .index(1) .takes_value(true) .required(true) - .help("app id"), - ) - .arg( - Arg::with_name("upload") + .help("app id")) + .arg(Arg::with_name("upload") .short("u") .long("upload") - .help("upload app list to chain, use owner account"), - ) + .help("upload app list to chain, use owner account")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg(SubCommand::with_name("set").about("add source to app")) - .arg( - Arg::with_name("appver") + .subcommand(add_id_or_file_arg(SubCommand::with_name("set").about("add source to app")) + .arg(Arg::with_name("appver") .short("v") .required(true) .takes_value(true) - .help("ver add to app source"), - ) - .arg( - Arg::with_name("source") + .help("ver add to app source")) + .arg(Arg::with_name("source") .short("s") .required(true) .takes_value(true) - .help("fileid add to app source"), - ) + .help("fileid add to app source")) .arg(meta_arg.clone()), ) - .subcommand( - add_id_or_file_arg( - SubCommand::with_name("remove").about("remove source from app"), - ) - .arg( - Arg::with_name("appver") + .subcommand(add_id_or_file_arg(SubCommand::with_name("remove").about("remove source from app")) + .arg(Arg::with_name("appver") .short("v") .takes_value(true) .required(true) - .help("remove app ver"), - ) + .help("remove app ver")) .arg(meta_arg.clone()), ) .subcommand( @@ -525,117 +407,8 @@ async fn main_run() -> BuckyResult<()> { add_id_or_file_arg(SubCommand::with_name("show").about("show app obj")) .arg(meta_arg.clone()), ), - ) - .subcommand( - SubCommand::with_name("cmd") - .about("add/install/uninstall/start/stop/setpermission/setquota") - .subcommand( - SubCommand::with_name("add") - .about("add app") - .arg( - Arg::with_name("owner") - .short("o") - .long("owner") - .takes_value(true) - .required(true) - .help("app owner id"), - ) - .arg( - Arg::with_name("id") - .index(1) - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("install") - .about("install app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg( - Arg::with_name("version") - .short("value") - .long("version") - .takes_value(true) - .required(true) - .help("app version"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("start") - .about("install app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("stop") - .about("stop app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("remove") - .about("remove app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("uninstall") - .about("uninstall app") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("setpermission") - .about("set app permission") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ) - .subcommand( - SubCommand::with_name("setquota") - .about("set app quota") - .arg( - Arg::with_name("id") - .takes_value(true) - .required(true) - .help("app id"), - ) - .arg(meta_arg.clone()), - ), - ) - .get_matches(); + ); + let matches = app.get_matches(); match matches.subcommand() { ("list", Some(matches)) => { @@ -715,7 +488,7 @@ async fn main_run() -> BuckyResult<()> { matches.is_present("status"), ); list.put(status); - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -728,7 +501,7 @@ async fn main_run() -> BuckyResult<()> { DecAppId::from_str(matches.value_of("appid").unwrap()).unwrap(); list.remove(&app_id); - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -739,7 +512,7 @@ async fn main_run() -> BuckyResult<()> { list.clear(); - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -777,38 +550,36 @@ async fn main_run() -> BuckyResult<()> { } // 需要config格式:[{id, ver, status}] for service in config.as_array().unwrap() { + let service = service.as_object().unwrap(); let app_id = DecAppId::from_str( - service - .as_object() - .unwrap() - .get("id") - .unwrap() - .as_str() - .unwrap(), + service.get("id").unwrap().as_str().unwrap(), ) .unwrap(); - let ver = service - .as_object() - .unwrap() - .get("ver") - .unwrap() - .as_str() - .unwrap() - .to_owned(); - let status = service - .as_object() - .unwrap() - .get("status") - .unwrap() - .as_i64() - .unwrap() - == 1; + let ver = service.get("ver").unwrap().as_str().unwrap(); + let status = service.get("status").unwrap().as_i64().unwrap() == 1; + + if matches.is_present("unpreview") { + info!("check preview version {} for app {}", ver, &app_id); + + if let Ok(mut app) = get_app_from_meta(app_id.object_id(), &target).await { + let pre_version = format!("{}-preview", ver); + if let Ok(id) = app.find_source(&pre_version) { + info!("find preview version {}, change to normal", &pre_version); + let desc = app.find_source_desc(&pre_version).map(|s|s.to_owned()); + app.remove_source(&pre_version); + app.set_source(ver.to_owned(), id, desc); + + target.save_obj(&app).await; + } + } + } + let status = - AppStatus::create(target.owner_id().unwrap(), app_id, ver, status); + AppStatus::create(target.owner_id().unwrap(), app_id, ver.to_owned(), status); list.put(status); } - save_obj(target, &list).await + target.save_obj(&list).await }) .await } @@ -878,7 +649,7 @@ async fn main_run() -> BuckyResult<()> { let ver = matches.value_of("appver").unwrap().to_owned(); app.set_source(ver, source, None); - save_obj(target, &app).await + target.save_obj(&app).await }) .await } @@ -890,7 +661,7 @@ async fn main_run() -> BuckyResult<()> { let ver = matches.value_of("appver").unwrap(); app.remove_source(&ver); - save_obj(target, &app).await + target.save_obj(&app).await }) .await } @@ -901,7 +672,7 @@ async fn main_run() -> BuckyResult<()> { app.clear_source(); - save_obj(target, &app).await + target.save_obj(&app).await }) .await } From 2e2dd12352eae8de4af3a7bb1412697f31d0b7f4 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 21:28:04 +0800 Subject: [PATCH 294/553] Add semver support into dec_app core object and with test cases --- src/Cargo.lock | 1 + src/component/cyfs-core/Cargo.toml | 3 +- src/component/cyfs-core/src/app/dec_app.rs | 209 ++++++++++++++++-- .../cyfs-core/src/trans/trans_context.rs | 2 +- 4 files changed, 200 insertions(+), 15 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index d52e953bf..3605f70fd 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1780,6 +1780,7 @@ dependencies = [ "protoc-bin-vendored", "protoc-rust", "rand 0.8.5", + "semver 1.0.14", "serde", "serde_json", "sha2 0.8.2", diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index 67b8928b1..d478a8d58 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -30,4 +30,5 @@ hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } sha2 = { version = '0.8' } -generic-array = { version = '0.12', default-features = false, features = ['serde'] } \ No newline at end of file +generic-array = { version = '0.12', default-features = false, features = ['serde'] } +semver = "1.0" diff --git a/src/component/cyfs-core/src/app/dec_app.rs b/src/component/cyfs-core/src/app/dec_app.rs index 83ca8aab2..1a32ccc1c 100644 --- a/src/component/cyfs-core/src/app/dec_app.rs +++ b/src/component/cyfs-core/src/app/dec_app.rs @@ -1,6 +1,6 @@ +use crate::codec::protos; use crate::coreobj::CoreObjectType; use cyfs_base::*; -use crate::codec::protos; use serde::Serialize; use std::collections::hash_map::RandomState; @@ -34,7 +34,7 @@ pub struct DecAppContent { icon: Option, desc: Option, source_desc: HashMap, - tags: HashMap + tags: HashMap, } impl BodyContent for DecAppContent { @@ -65,7 +65,7 @@ impl ProtobufTransform for DecAppContent { source_desc, icon: None, desc: None, - tags + tags, }; if value.icon.is_some() { @@ -83,19 +83,23 @@ impl ProtobufTransform<&DecAppContent> for protos::DecAppContent { let source_map: BTreeMap = value.source.clone().into_iter().collect(); let mut source = vec![]; for (k, v) in source_map { - source.push(protos::StringBytesMapItem{key: k, value: v.to_vec()?}); + source.push(protos::StringBytesMapItem { + key: k, + value: v.to_vec()?, + }); } - let source_desc_map: BTreeMap = value.source_desc.clone().into_iter().collect(); + let source_desc_map: BTreeMap = + value.source_desc.clone().into_iter().collect(); let mut source_desc = vec![]; for (k, v) in source_desc_map { - source_desc.push(protos::StringStringMapItem {key: k, value: v}); + source_desc.push(protos::StringStringMapItem { key: k, value: v }); } - let tags_map: BTreeMap = value.tags.clone().into_iter().collect(); + let tags_map: BTreeMap = value.tags.clone().into_iter().collect(); let mut tags = vec![]; for (k, v) in tags_map { - tags.push(protos::StringStringMapItem {key: k, value: v}); + tags.push(protos::StringStringMapItem { key: k, value: v }); } let mut ret = Self { @@ -103,7 +107,7 @@ impl ProtobufTransform<&DecAppContent> for protos::DecAppContent { source_desc, icon: None, desc: None, - tags + tags, }; if let Some(icon) = &value.icon { @@ -129,8 +133,15 @@ pub trait DecAppObj { fn name(&self) -> &str; fn app_desc(&self) -> Option<&str>; fn icon(&self) -> Option<&str>; + + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str>; + + fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult; fn find_source(&self, version: &str) -> BuckyResult; + + fn find_source_desc_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult>; fn find_source_desc(&self, version: &str) -> Option<&str>; + fn remove_source(&mut self, version: &str); fn clear_source(&mut self); fn set_source(&mut self, version: String, id: ObjectId, desc: Option); @@ -144,6 +155,31 @@ pub trait DecAppObj { fn generate_id(owner: ObjectId, id: &str) -> ObjectId; } +pub struct SemVerHelper {} + +impl SemVerHelper { + // x.y.?.z => x.y.z + // x.y.?.z-? => x.y.z-? + pub fn fix_semver(ver: &str) -> String { + let mut top: Vec<&str> = ver.split('-').collect(); + let mut ret: Vec<&str> = top[0].split('.').collect(); + if ret.len() == 4 { + ret.remove(2); + } + + let ret = ret.join("."); + let ret = if top.len() > 1 { + top[0] = &ret; + top.join("-") + } else { + ret + }; + + // println!("{} -> {}", ver, ret); + ret + } +} + // 同owner, 同id的AppId应该始终相同,允许不同的话会造成混乱 impl DecAppObj for DecApp { fn create(owner: ObjectId, id: &str) -> Self { @@ -173,6 +209,90 @@ impl DecAppObj for DecApp { self.body_expect("").content().icon.as_deref() } + // https://nodesource.com/blog/semver-tilde-and-caret/ + // When pre is specified, all matching prerelease versions will be included; + // otherwise, only all versions that do not contain any prerelease will be matched + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str> { + let name = self.name(); + let id = self.desc().calculate_id(); + + let req_version = semver::VersionReq::parse(req_semver).map_err(|e| { + let msg = format!( + "invalid semver request string! id={}, name={}, value={}, {}", + id, name, req_semver, e + ); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + let list: Vec<_> = self + .body_expect("") + .content() + .source + .keys() + .map(|key| { + let new_version = SemVerHelper::fix_semver(&key); + (key, new_version) + }) + .collect(); + + let mut semver_list = vec![]; + for (version, new_version) in list { + let mut semver = semver::Version::parse(&new_version).map_err(|e| { + let msg = format!( + "invalid semver string! id={}, name={}, value={}, {}", + id, name, version, e, + ); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + if !semver.pre.is_empty() { + if let Some(pre) = pre { + if semver.pre.as_str() != pre { + continue; + } + semver.pre = semver::Prerelease::EMPTY; + } else { + continue; + } + } + + semver_list.push((version, semver)); + } + + semver_list.sort_by(|left, right| right.1.partial_cmp(&left.1).unwrap()); + + let ret = semver_list.iter().find(|(version, semver)| { + if req_version.matches(semver) { + info!( + "app version matched: id={}, name={}, req={}, got={}", + id, name, req_semver, version + ); + true + } else { + false + } + }); + + if ret.is_none() { + let msg = format!( + "no matching semver found for app: id={}, name={}, req={}", + id, name, req_semver + ); + warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); + } + + let (version, _) = ret.unwrap(); + Ok(version) + } + + fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult { + let version = self.find_version(req_semver, pre)?; + self.find_source(&version) + } + fn find_source(&self, version: &str) -> BuckyResult { self.body_expect("") .content() @@ -182,6 +302,11 @@ impl DecAppObj for DecApp { .ok_or(BuckyError::from(BuckyErrorCode::NotFound)) } + fn find_source_desc_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult> { + let version = self.find_version(req_semver, pre)?; + Ok(self.find_source_desc(&version)) + } + fn find_source_desc(&self, version: &str) -> Option<&str> { self.body_expect("") .content() @@ -248,10 +373,7 @@ impl DecAppObj for DecApp { } fn remove_tag(&mut self, tag: &str) { - self.body_mut_expect("") - .content_mut() - .tags - .remove(tag); + self.body_mut_expect("").content_mut().tags.remove(tag); } fn tags(&self) -> &HashMap { @@ -261,4 +383,65 @@ impl DecAppObj for DecApp { fn generate_id(owner: ObjectId, id: &str) -> ObjectId { Self::create(owner, id).desc().calculate_id() } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test() { + let owner = ObjectId::default(); + let mut dec_app = DecApp::create(owner.clone(), "test-dec-app"); + dec_app.set_source("1.0.0".to_owned(), owner.clone(), None); + dec_app.set_source("1.0.1".to_owned(), owner.clone(), None); + dec_app.set_source("1.0.2".to_owned(), owner.clone(), None); + dec_app.set_source("1.1.2".to_owned(), owner.clone(), None); + dec_app.set_source("1.1.5".to_owned(), owner.clone(), None); + + dec_app.set_source("1.3.7".to_owned(), owner.clone(), None); + dec_app.set_source("1.3.10".to_owned(), owner.clone(), None); + dec_app.set_source("1.4.0.20".to_owned(), owner.clone(), None); + dec_app.set_source("1.4.1.21-preview".to_owned(), owner.clone(), None); + dec_app.set_source("1.5.1.22-preview".to_owned(), owner.clone(), None); + + dec_app.set_source("2.5.28".to_owned(), owner.clone(), None); + dec_app.set_source("2.5.30".to_owned(), owner.clone(), None); + + let ret = dec_app.find_version("*", None).unwrap(); + assert_eq!(ret, "2.5.30"); + + let ret = dec_app.find_version("2.5.28", None).unwrap(); + assert_eq!(ret, "2.5.30"); + + let ret = dec_app.find_version("=1.0", None).unwrap(); + assert_eq!(ret, "1.0.2"); + + // ^ first none zero version seg, and is default if not present + + dec_app.find_version("=1.4.21-preview", None).unwrap_err(); + + let ret = dec_app.find_version("=1.4.21", Some("preview")).unwrap(); + assert_eq!(ret, "1.4.1.21-preview"); + let ret = dec_app.find_version("1.4", Some("preview")).unwrap(); + assert_eq!(ret, "1.5.1.22-preview"); + let ret = dec_app.find_version("1.0", Some("preview")).unwrap(); + assert_eq!(ret, "1.5.1.22-preview"); + + let ret = dec_app.find_version("~1.4", None).unwrap(); + assert_eq!(ret, "1.4.0.20"); + + // ~ second none zero version seg + let ret = dec_app.find_version("~1.1", None).unwrap(); + assert_eq!(ret, "1.1.5"); + + let ret = dec_app.find_version("<1.3", None).unwrap(); + assert_eq!(ret, "1.1.5"); + + let ret = dec_app.find_version("=1.3", None).unwrap(); + assert_eq!(ret, "1.3.10"); + + let ret = dec_app.find_version("<=1.3.8", None).unwrap(); + assert_eq!(ret, "1.3.7"); + } } \ No newline at end of file diff --git a/src/component/cyfs-core/src/trans/trans_context.rs b/src/component/cyfs-core/src/trans/trans_context.rs index 9f2e9328f..ad657cd24 100644 --- a/src/component/cyfs-core/src/trans/trans_context.rs +++ b/src/component/cyfs-core/src/trans/trans_context.rs @@ -308,7 +308,7 @@ mod test { #[test] fn test() { let id = ObjectId::from_str("5r4MYfFdfQ5dvAvD2WZ8wd7iKPFpWLSiAnMuTui912xL").unwrap(); - let mut context = TransContext::new(id, "/a/b/c"); + let mut context = TransContext::new(Some(id), "/a/b/c"); let device = TransContextDevice { target: DeviceId::from_str("5bnZHzXvMmqiiua3iodiaYqWR24QbZE5o8r35bH8y9Yh").unwrap(), From d876450869a65b37382567eaf91eaeff2c8388d7 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 295/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/Cargo.lock | 1 + src/service/ood-daemon/Cargo.toml | 3 +- .../src/config/device_config_manager.rs | 2 +- .../ood-daemon/src/config/system_config.rs | 76 +++++++---- src/service/ood-daemon/src/config/version.rs | 70 +++++++++-- .../ood-daemon/src/config_repo/meta.rs | 119 +++++++++--------- 6 files changed, 172 insertions(+), 99 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3605f70fd..defb043ee 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4568,6 +4568,7 @@ dependencies = [ "once_cell", "ood-control", "rand 0.7.3", + "semver 1.0.14", "serde", "serde_json", "tide", diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index c0c092df8..dad44f82a 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -35,4 +35,5 @@ toml = "0.5" http-types = "2.12" hex = "0.4" tide = "0.16" -rand = '0.7' \ No newline at end of file +rand = '0.7' +semver = "1.0" \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 179db7c86..9667a5e30 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -38,7 +38,7 @@ impl DeviceConfigManager { Box::new(repo) as Box } else if desc == "cyfs_repo" || desc == "device" { let mut repo = DeviceConfigMetaRepo::new(); - if let Err(e) = repo.init(&desc, &get_system_config().version) { + if let Err(e) = repo.init(&desc, &get_system_config().service_list_version) { return Err(e); } diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 0b5fc2bba..fa50b80f4 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -1,10 +1,11 @@ use super::path::PATHS; -use super::version::ServiceListVersion; +use super::version::{ServiceVersion, ServiceListVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; use std::path::Path; +use std::str::FromStr; use std::sync::Arc; #[derive(Debug)] @@ -13,8 +14,14 @@ pub struct SystemConfig { // ServiceList对象会使用该id+version,来计算当前依赖的ServiceList对象,并从链上拉取 pub config_desc: String, - // 版本 - pub version: ServiceListVersion, + // service list version + pub service_list_version: ServiceListVersion, + + // service version + pub service_version: ServiceVersion, + + // enable preview + pub preview: bool, // 当前平台对应的target pub target: String, @@ -25,8 +32,11 @@ impl SystemConfig { Self { config_desc: String::from("cyfs_repo"), - // now all the channels should use Nightly version, not support any other version anymore! - version: ServiceListVersion::Nightly, + service_list_version: ServiceListVersion::default(), + + service_version: ServiceVersion::default(), + preview: false, + target: String::from(""), } } @@ -47,19 +57,34 @@ impl SystemConfig { let node = self.load_as_json(&config_file).await?; - self.parse_config(node).await + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) } async fn load_as_json(&self, file_path: &Path) -> BuckyResult { - let content = async_std::fs::read_to_string(&file_path).await.map_err(|e| { - let msg = format!("load system config to string error! file={}, {}", file_path.display(), e); - error!("{}", msg); - - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let content = async_std::fs::read_to_string(&file_path) + .await + .map_err(|e| { + let msg = format!( + "load system config to string error! file={}, {}", + file_path.display(), + e + ); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; let node = toml::from_str(&content).map_err(|e| { - let msg = format!("load system config invalid format! content={}, file={}, {}", content, file_path.display(), e); + let msg = format!( + "load system config invalid format! content={}, file={}, {}", + content, + file_path.display(), + e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -91,9 +116,7 @@ impl SystemConfig { } "repository" => { if v.is_array() { - REPO_MANAGER - .load(v.as_array().unwrap()) - .await?; + REPO_MANAGER.load(v.as_array().unwrap()).await?; } else { let msg = format!("config invalid repository node format"); error!("{}", msg); @@ -115,10 +138,18 @@ impl SystemConfig { "config_desc" => { self.config_desc = TomlHelper::decode_from_string(v)?; } - "version" => { - warn!("version field will be ignored! version={:?}", v); - // let v: String = TomlHelper::decode_from_string(v)?; - // self.version = ServiceListVersion::from_str(&v)?; + "service_list_version" => { + let v: String = TomlHelper::decode_from_string(v)?; + + self.service_list_version = ServiceListVersion::from_str(v.trim())?; + } + "service_version" => { + let v: String = TomlHelper::decode_from_string(v)?; + + self.service_version = ServiceVersion::from_str(v.trim())?; + } + "preview" => { + self.preview = TomlHelper::decode_from_boolean(v)?; } "target" => { self.target = TomlHelper::decode_from_string(v)?; @@ -148,15 +179,14 @@ static SYSTEM_CONFIG: OnceCell> = OnceCell::new(); // 只在进程初始化时候调用一次 pub async fn init_system_config() -> BuckyResult<()> { - let mut system_config = SystemConfig::new(); system_config.load_config().await?; SYSTEM_CONFIG.set(Arc::new(system_config)).unwrap(); - + Ok(()) } pub fn get_system_config() -> Arc { SYSTEM_CONFIG.get().unwrap().clone() -} \ No newline at end of file +} diff --git a/src/service/ood-daemon/src/config/version.rs b/src/service/ood-daemon/src/config/version.rs index fcbd57cf8..fd8a7a1e3 100644 --- a/src/service/ood-daemon/src/config/version.rs +++ b/src/service/ood-daemon/src/config/version.rs @@ -2,13 +2,10 @@ use cyfs_base::*; use std::str::FromStr; -// 版本列表定义 #[derive(Debug)] pub enum ServiceListVersion { - Nightly, - Latest, - Stable, - Specific(String), + Nightly, // default version + Specific(String), // user confined } // FIXME 默认使用nightly,以后会切换成stable @@ -22,8 +19,6 @@ impl ToString for ServiceListVersion { fn to_string(&self) -> String { match *self { Self::Nightly => "nightly", - Self::Latest => "latest", - Self::Stable => "stable", Self::Specific(ref v) => v.as_str(), } .to_owned() @@ -33,11 +28,64 @@ impl ToString for ServiceListVersion { impl FromStr for ServiceListVersion { type Err = BuckyError; fn from_str(s: &str) -> BuckyResult { - let ret = match s { + let ret = match s.trim() { "nightly" => Self::Nightly, - "latest" => Self::Latest, - "stable" => Self::Stable, - _ => Self::Specific(s.to_owned()), + v @ _ => { + Self::Specific(v.to_owned()) + } + }; + + Ok(ret) + } +} + + +// 版本列表定义 +#[derive(Debug)] +pub enum ServiceVersion { + Default, // use the version config in service list + Specific(String), // semver, * as the newest version +} + +impl ServiceVersion { + pub fn is_default(&self) -> bool { + match self { + Self::Default => true, + _ => false, + } + } +} + +impl Default for ServiceVersion { + fn default() -> Self { + Self::Default + } +} + +impl ToString for ServiceVersion { + fn to_string(&self) -> String { + match *self { + Self::Default => "default", + Self::Specific(ref v) => v.as_str(), + } + .to_owned() + } +} + +impl FromStr for ServiceVersion { + type Err = BuckyError; + fn from_str(s: &str) -> BuckyResult { + let ret = match s.trim() { + "default" => Self::Default, + v @ _ => { + let _req_version = semver::VersionReq::parse(v).map_err(|e| { + let msg = format!("invalid semver request string! value={}, {}", v, e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + Self::Specific(v.to_owned()) + } }; Ok(ret) diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 7aa460dca..e57133587 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -78,59 +78,37 @@ impl DeviceConfigGenerator { }); } - pub fn update_service(&mut self, service: &DecApp, fid: &str) { + pub fn update_service(&mut self, service: &DecApp, fid: &str, version: &str) { let id = service.desc().calculate_id().to_string(); let name = service.name(); - info!("will update service: id={}, name={}, fid={}", id, name, fid); + info!( + "will update service: id={}, name={}, fid={}, version={}", + id, name, fid, version + ); for item in self.service.iter_mut() { if item.name == name { item.id = id.clone(); item.fid = fid.to_owned(); + item.version = version.to_owned(); } else if item.id == id { item.name = name.to_owned(); item.fid = fid.to_owned(); + item.version = version.to_owned(); } } } - pub fn update_service_status(&mut self, status: &AppStatus) -> bool { + fn add_service(&mut self, status: &AppStatus) { let id = status.app_id().to_string(); let version = status.version(); + let target_state = match status.status() { true => ServiceState::Run, false => ServiceState::Stop, }; - for item in self.service.iter_mut() { - if item.id == id { - let mut version_changed = false; - - // 检查状态是不是发生改变 - if item.target_state != target_state { - item.target_state = target_state; - info!( - "service target state changed! id={}, name={} target state: {} -> {}", - item.id, item.name, item.target_state, target_state - ); - } - - // 检查版本是不是发生改变 - if item.version != version { - info!( - "service version changed! id={}, name={} version: {} -> {}", - item.id, item.name, item.version, version - ); - item.version = version.to_owned(); - - // 版本更新后,需要拉取最新的fid - version_changed = true; - } - return version_changed; - } - } - - info!("new service item: id={}, version={}", id, version); + debug!("new service item: id={}, version={}", id, version); let mut service = ServiceConfig::new(); service.id = id; service.version = version.to_owned(); @@ -139,8 +117,6 @@ impl DeviceConfigGenerator { self.service.push(service); // fid+name需要从DecApp对象获取 - - true } } @@ -175,11 +151,7 @@ impl DeviceConfigMetaRepo { } } - pub fn init( - &mut self, - config_desc: &str, - version: &ServiceListVersion, - ) -> Result<(), BuckyError> { + pub fn init(&mut self, config_desc: &str, version: &ServiceListVersion) -> Result<(), BuckyError> { assert!(self.desc.len() == 0); self.desc = config_desc.to_owned(); @@ -195,7 +167,7 @@ impl DeviceConfigMetaRepo { ); info!( - "device config repo: device_id={}, app_list_id={}, version={}", + "device config repo: device_id={}, service_list_id={}, version={}", device_id, service_list_id, version ); @@ -328,7 +300,7 @@ impl DeviceConfigMetaRepo { let fid = format!("{}/{}", dir_id, target); - info!("get fid from dir, dir={}, fid={}", dir_id, fid); + debug!("get fid from dir, dir={}, fid={}", dir_id, fid); Ok(fid) } @@ -345,15 +317,38 @@ impl DeviceConfigMetaRepo { &self, device_config: &mut DeviceConfigGenerator, service_id: &ObjectId, - version: &str, + version_in_service_list: &str, ) -> BuckyResult<()> { let service = self.load_service(service_id).await?; - let ret = service.find_source(version); + // first find the correct version + let config_version = match &get_system_config().service_version { + ServiceVersion::Default => version_in_service_list.to_owned(), + ServiceVersion::Specific(v) => v.clone(), + }; + + let preview = match get_system_config().preview { + true => Some("preview"), + false => None, + }; + + let version = service.find_version(&config_version, preview).map_err(|e| { + let msg = format!( + "find version from service object failed! id={}, configed version={}, preview={:?}, {}", + service_id, config_version, preview, e, + ); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::NotFound, msg) + })?; + + let ret = service.find_source(&version); if ret.is_err() { let msg = format!( - "get version from service object failed! id={}, version={}", - service_id, version + "get version from service object failed! id={}, version={}, {}", + service_id, + version, + ret.unwrap_err(), ); error!("{}", msg); @@ -369,7 +364,7 @@ impl DeviceConfigMetaRepo { let fid = self.load_fid(&dir_id, dir)?; // 更新 - device_config.update_service(&service, &fid); + device_config.update_service(&service, &fid, version); Ok(()) } @@ -380,22 +375,19 @@ impl DeviceConfigMetaRepo { ) -> BuckyResult { let mut device_config = DeviceConfigGenerator::new(); for (id, status) in service_list.app_list() { - debug!("got service item from service list: {}", id); - - let version_changed = device_config.update_service_status(status); - if version_changed { - let version = status.version(); - - self.load_service_fid(&mut device_config, id.object_id(), version) - .await - .map_err(|e| { - error!( - "load service fid failed! id={}, version={}, {}", - id, version, e - ); - e - })?; - } + device_config.add_service(status); + + let version = status.version(); + + self.load_service_fid(&mut device_config, id.object_id(), version) + .await + .map_err(|e| { + error!( + "load service fid failed! id={}, version={}, {}", + id, version, e + ); + e + })?; } // info!("list {:?}", self.device_config.lock().uwnrap().service); @@ -438,7 +430,8 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { // 从mete-chain拉取对应的service_list let service_list = self.load_service_list().await?; - { + // Only in the default version case, it will use the cache of servicelist + if get_system_config().service_version.is_default() { let cache = self.cache.lock().unwrap(); if let Some(cache) = &*cache { if Self::compare_service_list(&cache.service_list, &service_list) { From f514fe0943c6ddb94479fdb6bc024264c7323d11 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 01:53:06 +0800 Subject: [PATCH 296/553] Add meta client helper with object cache --- src/Cargo.lock | 1 + src/component/cyfs-meta-lib/Cargo.toml | 1 + src/component/cyfs-meta-lib/src/client.rs | 463 +++++++++++++--------- src/component/cyfs-meta-lib/src/helper.rs | 121 ++++++ src/component/cyfs-meta-lib/src/lib.rs | 6 + 5 files changed, 399 insertions(+), 193 deletions(-) create mode 100644 src/component/cyfs-meta-lib/src/helper.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index defb043ee..ca2a714ee 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2003,6 +2003,7 @@ dependencies = [ "hex", "http-types", "log 0.4.17", + "lru_time_cache", "primitive-types", "rand 0.7.3", "serde_json", diff --git a/src/component/cyfs-meta-lib/Cargo.toml b/src/component/cyfs-meta-lib/Cargo.toml index 4aeac29db..d19e44fbe 100644 --- a/src/component/cyfs-meta-lib/Cargo.toml +++ b/src/component/cyfs-meta-lib/Cargo.toml @@ -18,3 +18,4 @@ log = '0.4' serde_json = '1.0' rand = '0.7.3' primitive-types = { version = '0.9' } +lru_time_cache = "0.11" diff --git a/src/component/cyfs-meta-lib/src/client.rs b/src/component/cyfs-meta-lib/src/client.rs index 6cc154064..6b2524d35 100644 --- a/src/component/cyfs-meta-lib/src/client.rs +++ b/src/component/cyfs-meta-lib/src/client.rs @@ -1,12 +1,12 @@ +use crate::MetaMinerTarget; use cyfs_base::*; use cyfs_base_meta::*; -use crate::MetaMinerTarget; use http_types::{Method, Request, Url}; use log::*; +use primitive_types::H256; use serde_json::Value; use std::convert::TryFrom; -use primitive_types::H256; use std::time::Duration; pub struct MetaClient { @@ -22,7 +22,11 @@ impl MetaClient { pub fn new_target(target: MetaMinerTarget) -> Self { let url = target.miner_url(); - info!("will select meta service url: target={}, url={}", target.to_string(), &url); + info!( + "will select meta service url: target={}, url={}", + target.to_string(), + &url + ); Self::new(&url) } @@ -47,7 +51,11 @@ impl MetaClient { self.miner_host.join(path).unwrap() } - pub async fn get_balance(&self, account: &ObjectId, coin_id: u8) -> BuckyResult { + pub async fn get_balance( + &self, + account: &ObjectId, + coin_id: u8, + ) -> BuckyResult { let req = self.get_balance_request(account, coin_id); let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?; if let ViewResponse::ViewBalance(br) = resp { @@ -96,7 +104,8 @@ impl MetaClient { ctid: CoinTokenId::Coin(coin_id), to: vec![(to.clone(), v)], }), - 10,10, + 10, + 10, Vec::new(), ) .await @@ -117,7 +126,8 @@ impl MetaClient { ctid: CoinTokenId::Coin(coin_id), to: vec![(to.clone(), v)], }), - 10,10, + 10, + 10, Vec::new(), ) .await @@ -133,7 +143,8 @@ impl MetaClient { tx_data: Vec, ) -> BuckyResult { let caller = TxCaller::try_from(caller)?; - self.create_tx_and_sign_ex(caller, secret, body, gas_price, max_fee, tx_data).await + self.create_tx_and_sign_ex(caller, secret, body, gas_price, max_fee, tx_data) + .await } async fn create_tx_and_sign_ex( @@ -164,7 +175,17 @@ impl MetaClient { ) -> BuckyResult { let mut nonce = self.get_nonce(&caller.id()?).await?; nonce += 1; - let tx = Tx::new(nonce, caller, 0, gas_price, max_fee, None, vec![body].to_vec()?, tx_data).build(); + let tx = Tx::new( + nonce, + caller, + 0, + gas_price, + max_fee, + None, + vec![body].to_vec()?, + tx_data, + ) + .build(); Ok(tx) } @@ -178,7 +199,17 @@ impl MetaClient { ) -> BuckyResult { let mut nonce = self.get_nonce(&caller.id()?).await?; nonce += 1; - let tx = Tx::new(nonce, caller, 0, gas_price, max_fee, None, bodys.to_vec()?, tx_data).build(); + let tx = Tx::new( + nonce, + caller, + 0, + gas_price, + max_fee, + None, + bodys.to_vec()?, + tx_data, + ) + .build(); Ok(tx) } @@ -199,7 +230,9 @@ impl MetaClient { max_fee: u32, data: Vec, ) -> BuckyResult { - let signed_tx = self.create_tx_and_sign(caller, secret, body, gas_price, max_fee, data).await?; + let signed_tx = self + .create_tx_and_sign(caller, secret, body, gas_price, max_fee, data) + .await?; self.commit_signed_tx(signed_tx) } @@ -350,7 +383,8 @@ impl MetaClient { desc_hash: desc.hash()?, price, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -375,7 +409,8 @@ impl MetaClient { desc_hash: desc.hash()?, price, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -389,7 +424,9 @@ impl MetaClient { coin_id: Option, secret: &PrivateKey, ) -> BuckyResult { - let req = self.update_desc_request(owner, desc, price, coin_id, secret).await?; + let req = self + .update_desc_request(owner, desc, price, coin_id, secret) + .await?; self.request_miner(req, &mut Vec::new()).await } @@ -426,7 +463,8 @@ impl MetaClient { }), desc_hash: desc.hash()?, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -451,7 +489,8 @@ impl MetaClient { }), desc_hash: desc.hash()?, }), - 10,10, + 10, + 10, desc.to_vec()?, ) .await @@ -476,7 +515,8 @@ impl MetaClient { name_price: price, price: rent, }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -518,7 +558,8 @@ impl MetaClient { info, write_flag, }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -540,7 +581,8 @@ impl MetaClient { sub_name: sub_name.map(|str| str.to_owned()), new_owner: new_owner.clone(), }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -573,7 +615,7 @@ impl MetaClient { Err(async_std::future::TimeoutError { .. }) => { let msg = format!("meta request tx timeout!"); error!("{}", msg); - + Err(BuckyError::new(BuckyErrorCode::Timeout, msg)) } } @@ -652,12 +694,14 @@ impl MetaClient { buf: &'de mut Vec, ) -> BuckyResult { if let Some(timeout) = &self.request_timeout { - match async_std::future::timeout(timeout.to_owned(), self.request_miner_impl(req, buf)).await { + match async_std::future::timeout(timeout.to_owned(), self.request_miner_impl(req, buf)) + .await + { Ok(ret) => ret, Err(async_std::future::TimeoutError { .. }) => { let msg = format!("meta request timeout!"); error!("{}", msg); - + Err(BuckyError::new(BuckyErrorCode::Timeout, msg)) } } @@ -695,16 +739,11 @@ impl MetaClient { err })?; */ - let ret_hex = resp.body_string() - .await - .map_err(|err| { - error!("recv body error! err={}", err); - err - })?; - let ret = Result::::clone_from_hex( - ret_hex.as_str(), - buf, - )?; + let ret_hex = resp.body_string().await.map_err(|err| { + error!("recv body error! err={}", err); + err + })?; + let ret = Result::::clone_from_hex(ret_hex.as_str(), buf)?; match ret { Ok(t) => Ok(t), @@ -729,7 +768,8 @@ impl MetaClient { caller, secret, MetaTxBody::CreateUnion(create_union_tx), - 10,10, + 10, + 10, vec![], ) .await?; @@ -743,7 +783,14 @@ impl MetaClient { secret: &PrivateKey, ) -> BuckyResult { let req = self - .commit_request(caller, secret, MetaTxBody::DeviateUnion(deviate_tx), 10,10, vec![]) + .commit_request( + caller, + secret, + MetaTxBody::DeviateUnion(deviate_tx), + 10, + 10, + vec![], + ) .await?; self.request_miner(req, &mut Vec::new()).await } @@ -765,7 +812,8 @@ impl MetaClient { union: union_id.clone(), value, }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -787,7 +835,8 @@ impl MetaClient { key: key.to_owned(), value: value.to_owned(), }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -809,7 +858,8 @@ impl MetaClient { name: name.to_owned(), price: startting_price, }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -829,7 +879,8 @@ impl MetaClient { MetaTxBody::CancelAuctionName(CancelAuctionNameTx { name: name.to_owned(), }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -849,7 +900,8 @@ impl MetaClient { MetaTxBody::BuyBackName(BuyBackNameTx { name: name.to_owned(), }), - 10,10, + 10, + 10, vec![], ) .await?; @@ -869,7 +921,8 @@ impl MetaClient { MetaTxBody::RemoveDesc(RemoveDescTx { id: desc_id.clone(), }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -893,7 +946,8 @@ impl MetaClient { id: file_id.clone(), value: v, }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -911,7 +965,8 @@ impl MetaClient { caller, secret, MetaTxBody::CreateSubChainAccount(miner_group), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -930,7 +985,8 @@ impl MetaClient { caller, secret, MetaTxBody::WithdrawFromSubChain(WithdrawFromSubChainTx { coin_id, value }), - 10,10, + 10, + 10, Vec::new(), ) .await?; @@ -945,7 +1001,14 @@ impl MetaClient { tx_data: Vec, ) -> BuckyResult { let req = self - .commit_request_ex(caller, secret, MetaTxBody::Extension(extension_tx), 10,10, tx_data) + .commit_request_ex( + caller, + secret, + MetaTxBody::Extension(extension_tx), + 10, + 10, + tx_data, + ) .await?; self.request_miner(req, &mut Vec::new()).await } @@ -955,75 +1018,120 @@ impl MetaClient { self.request_miner(req, &mut Vec::new()).await } - pub async fn create_contract(&self, caller: &StandardObject, secret: &PrivateKey, value: u64, init_data: Vec, gas_price: u16, max_fee: u32) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::CreateContract(CreateContractTx { - value, - init_data - }), - gas_price, max_fee, - Vec::new(), - ).await?; + pub async fn create_contract( + &self, + caller: &StandardObject, + secret: &PrivateKey, + value: u64, + init_data: Vec, + gas_price: u16, + max_fee: u32, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::CreateContract(CreateContractTx { value, init_data }), + gas_price, + max_fee, + Vec::new(), + ) + .await?; info!("create request"); self.request_miner(req, &mut vec![]).await } - pub async fn create_contract2(&self, caller: &StandardObject, secret: &PrivateKey, value: u64, init_data: Vec, salt: [u8;32], gas_price: u16, max_fee: u32) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::CreateContract2(CreateContract2Tx::new(value, init_data, salt)), - gas_price, max_fee, - Vec::new(), - ).await?; + pub async fn create_contract2( + &self, + caller: &StandardObject, + secret: &PrivateKey, + value: u64, + init_data: Vec, + salt: [u8; 32], + gas_price: u16, + max_fee: u32, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::CreateContract2(CreateContract2Tx::new(value, init_data, salt)), + gas_price, + max_fee, + Vec::new(), + ) + .await?; self.request_miner(req, &mut vec![]).await } - pub async fn call_contract(&self, caller: &StandardObject, secret: &PrivateKey, address: ObjectId, value: u64, data: Vec, gas_price: u16, max_fee: u32) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::CallContract(CallContractTx { - address, - value, - data - }), - gas_price, max_fee, - Vec::new(), - ).await?; + pub async fn call_contract( + &self, + caller: &StandardObject, + secret: &PrivateKey, + address: ObjectId, + value: u64, + data: Vec, + gas_price: u16, + max_fee: u32, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::CallContract(CallContractTx { + address, + value, + data, + }), + gas_price, + max_fee, + Vec::new(), + ) + .await?; self.request_miner(req, &mut vec![]).await } - pub async fn view_contract(&self, address: ObjectId, data: Vec) -> BuckyResult { + pub async fn view_contract( + &self, + address: ObjectId, + data: Vec, + ) -> BuckyResult { let view = ViewRequest { block: ViewBlockEnum::Tip, - method: ViewMethodEnum::ViewContract(ViewContract { - address, - data - }), + method: ViewMethodEnum::ViewContract(ViewContract { address, data }), }; let req = self.view_request(view); let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?; if let ViewResponse::ViewContract(br) = resp { Ok(br) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } - pub async fn set_benefi(&self, address: &ObjectId, benefi: &ObjectId, caller: &StandardObject, secret: &PrivateKey) -> BuckyResult { - let req = self.commit_request( - caller, - secret, - MetaTxBody::SetBenefi(SetBenefiTx { - address: address.clone(), - to: benefi.clone() - }), - 10, 10, - Vec::new(), - ).await?; + pub async fn set_benefi( + &self, + address: &ObjectId, + benefi: &ObjectId, + caller: &StandardObject, + secret: &PrivateKey, + ) -> BuckyResult { + let req = self + .commit_request( + caller, + secret, + MetaTxBody::SetBenefi(SetBenefiTx { + address: address.clone(), + to: benefi.clone(), + }), + 10, + 10, + Vec::new(), + ) + .await?; self.request_miner(req, &mut vec![]).await } @@ -1039,18 +1147,27 @@ impl MetaClient { if let ViewResponse::ViewBenefi(br) = resp { Ok(br.address) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } - pub async fn get_logs(&self, address: ObjectId, topics: Vec>, from: i64, to: i64) -> BuckyResult, Vec)>> { + pub async fn get_logs( + &self, + address: ObjectId, + topics: Vec>, + from: i64, + to: i64, + ) -> BuckyResult, Vec)>> { let view = ViewRequest { block: ViewBlockEnum::Tip, method: ViewMethodEnum::ViewLog(ViewLog { address, topics, from, - to + to, }), }; let req = self.view_request(view); @@ -1058,26 +1175,28 @@ impl MetaClient { if let ViewResponse::ViewLog(br) = resp { Ok(br.logs) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } - pub async fn nft_create(&self, - caller: TxCaller, - secret: &PrivateKey, - desc: NFTDesc, - name: String, - state: NFTState) -> BuckyResult { + pub async fn nft_create( + &self, + caller: TxCaller, + secret: &PrivateKey, + desc: NFTDesc, + name: String, + state: NFTState, + ) -> BuckyResult { let req = self .commit_request_ex( caller, secret, - MetaTxBody::NFTCreate(NFTCreateTx { - desc, - name, - state - }), - 10, 10, + MetaTxBody::NFTCreate(NFTCreateTx { desc, name, state }), + 10, + 10, Vec::new(), ) .await?; @@ -1097,7 +1216,10 @@ impl MetaClient { if let ViewResponse::ViewNFT(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1116,7 +1238,10 @@ impl MetaClient { if let ViewResponse::ViewNFTApplyBuyList(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1135,7 +1260,10 @@ impl MetaClient { if let ViewResponse::ViewNFTBidList(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1145,14 +1273,17 @@ impl MetaClient { ) -> BuckyResult> { let view = ViewRequest { block: ViewBlockEnum::Tip, - method: ViewMethodEnum::ViewNFTLargestBuyValue(nft_id) + method: ViewMethodEnum::ViewNFTLargestBuyValue(nft_id), }; let req = self.view_request(view); let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?; if let ViewResponse::ViewNFTLargestBuyValue(ret) = resp { Ok(ret) } else { - Err(BuckyError::new(BuckyErrorCode::NotMatch, "view result type not match")) + Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "view result type not match", + )) } } @@ -1163,7 +1294,8 @@ impl MetaClient { nft_id: ObjectId, price: u64, coin_id: CoinTokenId, - duration_block_num: u64) -> BuckyResult { + duration_block_num: u64, + ) -> BuckyResult { let req = self .commit_request_ex( caller, @@ -1172,9 +1304,10 @@ impl MetaClient { nft_id, price, coin_id, - duration_block_num + duration_block_num, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1187,7 +1320,7 @@ impl MetaClient { secret: &PrivateKey, nft_id: ObjectId, price: u64, - coin_id: CoinTokenId + coin_id: CoinTokenId, ) -> BuckyResult { let req = self .commit_request_ex( @@ -1198,7 +1331,8 @@ impl MetaClient { price, coin_id, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1211,7 +1345,7 @@ impl MetaClient { secret: &PrivateKey, nft_id: ObjectId, price: u64, - coin_id: CoinTokenId + coin_id: CoinTokenId, ) -> BuckyResult { let req = self .commit_request_ex( @@ -1222,7 +1356,8 @@ impl MetaClient { price, coin_id, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1246,9 +1381,10 @@ impl MetaClient { nft_id, price, coin_id, - duration_block_num + duration_block_num, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1261,7 +1397,7 @@ impl MetaClient { secret: &PrivateKey, nft_id: ObjectId, price: u64, - coin_id: CoinTokenId + coin_id: CoinTokenId, ) -> BuckyResult { let req = self .commit_request_ex( @@ -1272,7 +1408,8 @@ impl MetaClient { price, coin_id, }), - 10, 10, + 10, + 10, Vec::new(), ) .await?; @@ -1289,10 +1426,9 @@ impl MetaClient { .commit_request_ex( caller, secret, - MetaTxBody::NFTCancelApplyBuyTx(NFTCancelApplyBuyTx { - nft_id, - }), - 10, 10, + MetaTxBody::NFTCancelApplyBuyTx(NFTCancelApplyBuyTx { nft_id }), + 10, + 10, Vec::new(), ) .await?; @@ -1310,11 +1446,9 @@ impl MetaClient { .commit_request_ex( caller, secret, - MetaTxBody::NFTAgreeApply(NFTAgreeApplyTx { - nft_id, - user_id, - }), - 10, 10, + MetaTxBody::NFTAgreeApply(NFTAgreeApplyTx { nft_id, user_id }), + 10, + 10, Vec::new(), ) .await?; @@ -1331,17 +1465,15 @@ impl MetaClient { .commit_request_ex( caller, secret, - MetaTxBody::NFTLike(NFTLikeTx { - nft_id, - }), - 10, 10, + MetaTxBody::NFTLike(NFTLikeTx { nft_id }), + 10, + 10, Vec::new(), ) .await?; self.request_miner(req, &mut Vec::new()).await } - // pub async fn public_sn_service(&self, caller: TxCaller, service: SNService, secret: &PrivateKey) -> BuckyResult { // let req = self.commit_request_ex(caller, secret, MetaTxBody::SNService(SNServiceTx::Publish(service)), Vec::new()).await?; // self.request_miner(req, &mut Vec::new()).await @@ -1362,59 +1494,4 @@ impl MetaClient { // let req = Request::new(Method::Get, url); // self.request_miner(req, &mut Vec::new()).await // } -} - - -pub struct MetaClientHelper; - -impl MetaClientHelper { - pub async fn get_object( - meta_client: &MetaClient, - object_id: &ObjectId, - ) -> BuckyResult)>> { - let object_raw = match meta_client.get_raw_data(object_id).await { - Ok(v) => v, - Err(e) => { - if e.code() == BuckyErrorCode::NotFound { - warn!( - "get object from meta chain but not found! obj={} err={}", - object_id, e - ); - - return Ok(None); - } else { - let msg = format!( - "load object from meta chain failed! obj={} err={}", - object_id, e - ); - error!("{}", msg); - return Err(BuckyError::new(e.code(), msg)); - } - } - }; - - info!("get object from meta success: {}", object_id); - let (object, _) = AnyNamedObject::raw_decode(&object_raw).map_err(|e| { - let msg = format!("invalid object format! obj={} err={}", object_id, e); - error!("{}", msg); - - BuckyError::new(BuckyErrorCode::InvalidFormat, msg) - })?; - - // 校验一下对象id,看是否匹配 - let id = object.calculate_id(); - if id != *object_id { - let msg = format!( - "get object from meta but got unmatch object id! expected={}, got={}", - object_id, id - ); - error!("{}", msg); - - return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); - } - - let resp = (object, object_raw); - - Ok(Some(resp)) - } -} +} \ No newline at end of file diff --git a/src/component/cyfs-meta-lib/src/helper.rs b/src/component/cyfs-meta-lib/src/helper.rs new file mode 100644 index 000000000..6185450d4 --- /dev/null +++ b/src/component/cyfs-meta-lib/src/helper.rs @@ -0,0 +1,121 @@ +use super::client::*; +use cyfs_base::*; + +use async_std::sync::Mutex as AsyncMutex; +use std::sync::Arc; + +pub struct MetaClientHelper; + +impl MetaClientHelper { + pub async fn get_object( + meta_client: &MetaClient, + object_id: &ObjectId, + ) -> BuckyResult)>> { + let object_raw = match meta_client.get_raw_data(object_id).await { + Ok(v) => v, + Err(e) => { + if e.code() == BuckyErrorCode::NotFound { + warn!( + "get object from meta chain but not found! obj={} err={}", + object_id, e + ); + + return Ok(None); + } else { + let msg = format!( + "load object from meta chain failed! obj={} err={}", + object_id, e + ); + error!("{}", msg); + return Err(BuckyError::new(e.code(), msg)); + } + } + }; + + info!("get object from meta success: {}", object_id); + let (object, _) = AnyNamedObject::raw_decode(&object_raw).map_err(|e| { + let msg = format!("invalid object format! obj={} err={}", object_id, e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + // 校验一下对象id,看是否匹配 + let id = object.calculate_id(); + if id != *object_id { + let msg = format!( + "get object from meta but got unmatch object id! expected={}, got={}", + object_id, id + ); + error!("{}", msg); + + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let resp = (object, object_raw); + + Ok(Some(resp)) + } +} + +struct MetaClientObjectItem { + object_raw: Option>, +} + +impl MetaClientObjectItem { + pub fn into_object_raw(&self) -> Option> { + self.object_raw + .as_ref() + .map(|object_raw| object_raw.clone()) + } +} + +#[derive(Clone)] +pub struct MetaClientHelperWithObjectCache { + objects: Arc>>, +} + +impl MetaClientHelperWithObjectCache { + pub fn new(timeout: std::time::Duration, capacity: usize) -> Self { + Self { + objects: Arc::new(AsyncMutex::new( + lru_time_cache::LruCache::with_expiry_duration_and_capacity(timeout, capacity), + )), + } + } + + pub async fn get_object( + &self, + meta_client: &MetaClient, + object_id: &ObjectId, + ) -> BuckyResult)>> { + Ok(self + .get_object_raw(meta_client, object_id) + .await? + .map(|object_raw| { + let (object, _) = AnyNamedObject::raw_decode(&object_raw).unwrap(); + (object, object_raw) + })) + } + + pub async fn get_object_raw( + &self, + meta_client: &MetaClient, + object_id: &ObjectId, + ) -> BuckyResult>> { + let mut list = self.objects.lock().await; + if let Some(item) = list.peek(object_id) { + return Ok(item.into_object_raw()); + } + + let ret = MetaClientHelper::get_object(meta_client, object_id).await?; + let ret = ret.map(|(_, object_raw)| object_raw); + let item = MetaClientObjectItem { + object_raw: ret.as_ref().map(|object_raw| object_raw.clone()), + }; + + list.insert(object_id.to_owned(), item); + + Ok(ret) + } +} diff --git a/src/component/cyfs-meta-lib/src/lib.rs b/src/component/cyfs-meta-lib/src/lib.rs index bc74ccc7e..2c043b6c9 100644 --- a/src/component/cyfs-meta-lib/src/lib.rs +++ b/src/component/cyfs-meta-lib/src/lib.rs @@ -1,4 +1,10 @@ mod client; +mod helper; mod meta_target; + +#[macro_use] +extern crate log; + pub use client::*; +pub use helper::*; pub use meta_target::*; \ No newline at end of file From e91227842ff2bdf5b61cb1b8cae02d5f45ae3373 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 13:43:42 +0800 Subject: [PATCH 297/553] Add cache for meta config repo in ood-daemon --- src/service/ood-daemon/src/config_repo/meta.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index e57133587..96a4be439 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -3,7 +3,7 @@ use crate::config::*; use cyfs_base::*; use cyfs_core::*; use cyfs_debug::Mutex; -use cyfs_meta_lib::{MetaClient, MetaClientHelper, MetaMinerTarget}; +use cyfs_meta_lib::{MetaClient, MetaClientHelper, MetaClientHelperWithObjectCache, MetaMinerTarget}; use cyfs_util::LOCAL_DEVICE_MANAGER; use async_trait::async_trait; @@ -135,6 +135,9 @@ pub struct DeviceConfigMetaRepo { meta_client: MetaClient, cache: Mutex>, + + service_objects: MetaClientHelperWithObjectCache, + service_dir_objects: MetaClientHelperWithObjectCache, } impl DeviceConfigMetaRepo { @@ -148,6 +151,8 @@ impl DeviceConfigMetaRepo { service_list_id: None, meta_client, cache: Mutex::new(None), + service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), + service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24), 16), } } @@ -227,7 +232,7 @@ impl DeviceConfigMetaRepo { } async fn load_service(&self, service_id: &ObjectId) -> BuckyResult { - let ret = MetaClientHelper::get_object(&self.meta_client, service_id).await?; + let ret = self.service_objects.get_object_raw(&self.meta_client, service_id).await?; if ret.is_none() { let msg = format!( "load service object from meta chain but not found! id={}", @@ -238,7 +243,7 @@ impl DeviceConfigMetaRepo { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - let (_, object_raw) = ret.unwrap(); + let object_raw = ret.unwrap(); // 解码 let service = DecApp::clone_from_slice(&object_raw).map_err(|e| { @@ -252,7 +257,7 @@ impl DeviceConfigMetaRepo { } async fn load_service_dir(&self, dir_id: &ObjectId) -> BuckyResult { - let ret = MetaClientHelper::get_object(&self.meta_client, dir_id).await?; + let ret = self.service_dir_objects.get_object_raw(&self.meta_client, dir_id).await?; if ret.is_none() { let msg = format!( "load service dir from meta chain but not found! id={}", @@ -263,7 +268,7 @@ impl DeviceConfigMetaRepo { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - let (_, object_raw) = ret.unwrap(); + let object_raw = ret.unwrap(); // 解码 let dir = Dir::clone_from_slice(&object_raw).map_err(|e| { @@ -332,7 +337,7 @@ impl DeviceConfigMetaRepo { false => None, }; - let version = service.find_version(&config_version, preview).map_err(|e| { + let (version, semver) = service.find_version(&config_version, preview).map_err(|e| { let msg = format!( "find version from service object failed! id={}, configed version={}, preview={:?}, {}", service_id, config_version, preview, e, From 7b6c84fc98d08b11ff7776f8fb0ea1bd8a00c37f Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 15:12:03 +0800 Subject: [PATCH 298/553] Add semver epoch check into ood-daemon --- src/component/cyfs-core/src/app/dec_app.rs | 17 ++++---- src/service/ood-daemon/src/config/version.rs | 39 ++++++++++++++++--- .../ood-daemon/src/config_repo/meta.rs | 3 ++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/component/cyfs-core/src/app/dec_app.rs b/src/component/cyfs-core/src/app/dec_app.rs index 1a32ccc1c..e5a0d9b8a 100644 --- a/src/component/cyfs-core/src/app/dec_app.rs +++ b/src/component/cyfs-core/src/app/dec_app.rs @@ -134,7 +134,8 @@ pub trait DecAppObj { fn app_desc(&self) -> Option<&str>; fn icon(&self) -> Option<&str>; - fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str>; + // return (origin version, semversion); + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<(&str, String)>; fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult; fn find_source(&self, version: &str) -> BuckyResult; @@ -212,7 +213,7 @@ impl DecAppObj for DecApp { // https://nodesource.com/blog/semver-tilde-and-caret/ // When pre is specified, all matching prerelease versions will be included; // otherwise, only all versions that do not contain any prerelease will be matched - fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<&str> { + fn find_version(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult<(&str, String)> { let name = self.name(); let id = self.desc().calculate_id(); @@ -284,13 +285,13 @@ impl DecAppObj for DecApp { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - let (version, _) = ret.unwrap(); - Ok(version) + let (version, semver) = ret.unwrap(); + Ok((version, semver.to_string())) } fn find_source_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult { - let version = self.find_version(req_semver, pre)?; - self.find_source(&version) + let ret = self.find_version(req_semver, pre)?; + self.find_source(&ret.0) } fn find_source(&self, version: &str) -> BuckyResult { @@ -303,8 +304,8 @@ impl DecAppObj for DecApp { } fn find_source_desc_by_semver(&self, req_semver: &str, pre: Option<&str>) -> BuckyResult> { - let version = self.find_version(req_semver, pre)?; - Ok(self.find_source_desc(&version)) + let ret = self.find_version(req_semver, pre)?; + Ok(self.find_source_desc(&ret.0)) } fn find_source_desc(&self, version: &str) -> Option<&str> { diff --git a/src/service/ood-daemon/src/config/version.rs b/src/service/ood-daemon/src/config/version.rs index fd8a7a1e3..1822f6403 100644 --- a/src/service/ood-daemon/src/config/version.rs +++ b/src/service/ood-daemon/src/config/version.rs @@ -4,7 +4,7 @@ use std::str::FromStr; #[derive(Debug)] pub enum ServiceListVersion { - Nightly, // default version + Nightly, // default version Specific(String), // user confined } @@ -30,16 +30,13 @@ impl FromStr for ServiceListVersion { fn from_str(s: &str) -> BuckyResult { let ret = match s.trim() { "nightly" => Self::Nightly, - v @ _ => { - Self::Specific(v.to_owned()) - } + v @ _ => Self::Specific(v.to_owned()), }; Ok(ret) } } - // 版本列表定义 #[derive(Debug)] pub enum ServiceVersion { @@ -91,3 +88,35 @@ impl FromStr for ServiceVersion { Ok(ret) } } + +pub struct SemVerEpochCheck; + +impl SemVerEpochCheck { + pub fn get_semver_epoch_patch_version() -> u64 { + match cyfs_base::get_channel() { + CyfsChannel::Nightly => 719, + CyfsChannel::Beta => 75, + CyfsChannel::Stable => 0, + } + } + + pub fn check_version_with_semver_epoch(semver: &str) -> BuckyResult<()> { + let version = semver::Version::parse(semver).map_err(|e| { + let msg = format!("invalid semver string! value={}, {}", semver, e,); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::InvalidFormat, msg) + })?; + + if version.patch < Self::get_semver_epoch_patch_version() { + let msg = format!( + "version that does not support semver! version={}, epoch patch={}", + semver, + Self::get_semver_epoch_patch_version(), + ); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotSupport, msg)) + } + + Ok(()) + } +} diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 96a4be439..7d2babe91 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -347,6 +347,9 @@ impl DeviceConfigMetaRepo { BuckyError::new(BuckyErrorCode::NotFound, msg) })?; + // check if the target service version is valid + SemVerEpochCheck::check_version_with_semver_epoch(&semver)?; + let ret = service.find_source(&version); if ret.is_err() { let msg = format!( From 06bdf307983c97bf6df3f1a5dbc30c0b972b01dd Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 18:02:20 +0800 Subject: [PATCH 299/553] Add app repo downloader for ood-installer --- .../ood-installer/src/app_repo_downloader.rs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/tools/ood-installer/src/app_repo_downloader.rs diff --git a/src/tools/ood-installer/src/app_repo_downloader.rs b/src/tools/ood-installer/src/app_repo_downloader.rs new file mode 100644 index 000000000..b7fa7ca18 --- /dev/null +++ b/src/tools/ood-installer/src/app_repo_downloader.rs @@ -0,0 +1,91 @@ +use std::path::PathBuf; +use std::time::Duration; +use app_manager::package::AppPackage; +use cyfs_base::{AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, FileDecoder, NamedObject, ObjectId, OwnerObjectDesc, RawFrom}; +use cyfs_base_meta::SavedMetaObject; +use cyfs_client::{NamedCacheClient, NamedCacheClientConfig}; +use cyfs_core::{AppList, APPLIST_APP_CATEGORY, AppListObj, AppStatusObj, DecApp, DecAppObj}; +use cyfs_meta_lib::{MetaClient, MetaMinerTarget}; +use cyfs_util::get_cyfs_root_path; +use crate::asset::{OODAsset}; + +pub(crate) struct AppRepoDownloader { + repo_path: PathBuf, + client: NamedCacheClient, + meta_client: MetaClient +} + +impl AppRepoDownloader { + pub fn new() -> Self { + // service desc确保它有固定外网地址,连接不走sn。这里sn_list就可以传None + let mut config = NamedCacheClientConfig::default(); + config.retry_times = 3; + config.timeout = Duration::from_secs(10*60); + config.tcp_file_manager_port = 5312; + config.tcp_chunk_manager_port = 5310; + config.conn_strategy = cyfs_client::ConnStrategy::TcpFirst; + Self { + repo_path: get_cyfs_root_path().join("app_repo"), + client: NamedCacheClient::new(config), + meta_client: MetaClient::new_target(MetaMinerTarget::default()) + } + } + + pub async fn init(&mut self) -> BuckyResult<()> { + if let Err(e) = self.client.init().await { + let msg = format!("init named cache client for repo failed! err={}", e); + error!("{}", msg); + + return Err(BuckyError::new(e.code(), msg)); + } + + Ok(()) + } + + pub async fn download(&self, asset: &OODAsset) -> BuckyResult<()> { + asset.extract_app_repo()?; + + let sys_app_list_id = self.get_sys_app_list_id()?; + info!("try get sys app list {}", sys_app_list_id); + + let list = if let SavedMetaObject::Data(data) = self.meta_client.get_desc(&sys_app_list_id).await? { + AppList::clone_from_slice(&data.data) + } else { + Err(BuckyError::new(BuckyErrorCode::NotMatch, format!("app list {} from meta type mismatch!", &sys_app_list_id))) + }?; + + for (id, status) in list.app_list() { + info!("download app {} version {}", id.object_id(), status.version()); + let dec_app = if let SavedMetaObject::Data(data) = self.meta_client.get_desc(id.object_id()).await? { + DecApp::clone_from_slice(&data.data) + } else { + Err(BuckyError::new(BuckyErrorCode::NotMatch, format!("app {} from meta type mismatch!", &id.object_id()))) + }?; + + let owner = dec_app.desc().owner().as_ref().ok_or(BuckyError::from(BuckyErrorCode::InvalidInput))?; + let dir = dec_app.find_source(status.version())?; + + let target_path = self.repo_path.join(dir.to_string()); + AppPackage::download(&dir, owner, &self.client, &target_path).await.map_err(|e| { + error!("download app {} dir {} err {}",id.object_id(), &dir, e); + e + })? + } + + info!("sync app repo from {} success!", &sys_app_list_id); + + Ok(()) + } + + fn get_sys_app_list_id(&self) -> BuckyResult { + let mut repo_path = get_cyfs_root_path(); + repo_path.push("etc"); + repo_path.push("desc"); + repo_path.push("app_repo.desc"); + let (obj, _) = AnyNamedObject::decode_from_file(&repo_path, &mut vec![])?; + let id = obj.calculate_id(); + + Ok(AppList::generate_id(id.clone(), "", APPLIST_APP_CATEGORY)) + + } +} \ No newline at end of file From 5adb07dfb8c9b154a0305e9d64f23ebe8188fccb Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 18:16:56 +0800 Subject: [PATCH 300/553] Fix: Missing app-manager lib.rs --- .../cyfs-perf-client/build_ios_perfclient.js | 23 ------------------- .../cyfs-perf-client/build_perfclient.js | 17 -------------- .../cyfs-perf/cyfs-perf-client/cbindgen.toml | 7 ------ .../cyfs-perf-client/header/perf_client.h | 23 ------------------- src/service/app-manager/src/lib.rs | 1 + 5 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml delete mode 100644 src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h create mode 100644 src/service/app-manager/src/lib.rs diff --git a/src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js b/src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js deleted file mode 100644 index 4254c77ac..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/build_ios_perfclient.js +++ /dev/null @@ -1,23 +0,0 @@ -const child_process = require('child_process'); - -const env = process.env; - -child_process.execSync('cargo update', { stdio: 'inherit', cwd: __dirname}) -child_process.execSync('rustup target add aarch64-apple-ios x86_64-apple-ios', { stdio: 'inherit', cwd: __dirname}) - -// 编译通用库 -child_process.execSync('cargo install cargo-lipo', { stdio: 'inherit', cwd: __dirname}) -child_process.execSync('cargo lipo -p perf-client --release', { stdio: 'inherit', cwd: __dirname}) - -// 编译模拟器库 -child_process.execSync('cargo build -p perf-client --lib --target x86_64-apple-ios --release', { stdio: 'inherit', cwd: __dirname, env: env }) - -// 编译真机库 -child_process.execSync('cargo build -p perf-client --lib --target aarch64-apple-ios --release', { stdio: 'inherit', cwd: __dirname, env: env }) - -// 生成头文件 -//child_process.execSync('sudo cargo install --force cbindgen', { stdio: 'inherit', cwd: __dirname}) -// cbindgen 可以导出指定crate的pub方法或类型 -//child_process.execSync('sudo cbindgen --config cbindgen.toml --crate perf-client --output header/perf_client.h', { stdio: 'inherit', cwd: __dirname}) - - diff --git a/src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js b/src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js deleted file mode 100644 index 98314ee7a..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/build_perfclient.js +++ /dev/null @@ -1,17 +0,0 @@ -const child_process = require('child_process'); - -const env = process.env; -const ndk_home = "C:\Users\Bucky\AppData\Local\Android\Sdk\ndk-bundle" - -env["AR_aarch64-linux-android"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android-ar.exe` -env["CC_aarch64-linux-android"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android21-clang.cmd` -env["AR_armv7-linux-androideabi"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\arm-linux-androideabi-ar.exe` -env["CC_armv7-linux-androideabi"] = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\armv7a-linux-androideabi21-clang.cmd` -const aarch64_linux_android_strip = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android-strip.exe` -const armv7_linux_androideabi_strip = `C:\\Users\\Bucky\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\arm-linux-androideabi-strip.exe` - -child_process.execSync('cargo update', { stdio: 'inherit', cwd: __dirname}) - -child_process.execSync('cargo build -p perf-client --lib --target aarch64-linux-android --release', { stdio: 'inherit', cwd: __dirname, env: env }) - -// child_process.execSync(`${aarch64_linux_android_strip} target/aarch64-linux-android/release/libimclient.so`) \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml b/src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml deleted file mode 100644 index 906d84437..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/cbindgen.toml +++ /dev/null @@ -1,7 +0,0 @@ -#language = "c++"或language = "c" -language = "c" -#是否不导入头文件 -no_includes = false - -[export] -prefix = "" diff --git a/src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h b/src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h deleted file mode 100644 index 32a731e1e..000000000 --- a/src/component/cyfs-perf/cyfs-perf-client/header/perf_client.h +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -#include "ios_logger.h" -void startPerfClient(const char *cowner_id, - const char *cdec_id, - const char *cclient_addr, - const char *cbase_path, - const char *cnon_addr, - const char *cws_addr, - int cbdt_port, - const char *cloglevel, - const char *cwifi_addr, - LogCallback log); - -void statPerf(const char *id, - const char *key, - int bytes, - int error_code, - const char *name, - const char *value); diff --git a/src/service/app-manager/src/lib.rs b/src/service/app-manager/src/lib.rs new file mode 100644 index 000000000..8559986ca --- /dev/null +++ b/src/service/app-manager/src/lib.rs @@ -0,0 +1 @@ +pub mod package; \ No newline at end of file From e1dad96da71228c7c9c209f6c990b9348df7c94f Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 18:34:21 +0800 Subject: [PATCH 301/553] Fix: pack script error --- scripts/pack.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pack.js b/scripts/pack.js index f3676ea57..34432d425 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -166,13 +166,14 @@ async function run() { child_process.execSync(`cyfs-client ${action} services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) + let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) + // 运行app-tool,添加版本和fid let app_version = version + "-preview"; let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; console.log("will run app tool cmd:", cmd) child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) - let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) } From 185ed45afd9ba77189b50385bf54f7346c786f5e Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 15:32:20 +0800 Subject: [PATCH 302/553] Switch meta repo to dynamic dependency on system config --- .../src/config/device_config_manager.rs | 4 +- .../ood-daemon/src/config_repo/meta.rs | 58 +++++++------------ 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 9667a5e30..7e52b619e 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -37,8 +37,8 @@ impl DeviceConfigManager { let repo = DeviceConfigLocalRepo::new(); Box::new(repo) as Box } else if desc == "cyfs_repo" || desc == "device" { - let mut repo = DeviceConfigMetaRepo::new(); - if let Err(e) = repo.init(&desc, &get_system_config().service_list_version) { + let repo = DeviceConfigMetaRepo::new(); + if let Err(e) = repo.init() { return Err(e); } diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 7d2babe91..d2e4ee67c 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -126,12 +126,6 @@ struct LocalCache { } pub struct DeviceConfigMetaRepo { - desc: String, - - device_id: Option, - - service_list_id: Option, - meta_client: MetaClient, cache: Mutex>, @@ -146,9 +140,6 @@ impl DeviceConfigMetaRepo { .with_timeout(std::time::Duration::from_secs(60 * 2)); Self { - desc: String::from(""), - device_id: None, - service_list_id: None, meta_client, cache: Mutex::new(None), service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), @@ -156,38 +147,35 @@ impl DeviceConfigMetaRepo { } } - pub fn init(&mut self, config_desc: &str, version: &ServiceListVersion) -> Result<(), BuckyError> { - assert!(self.desc.len() == 0); - self.desc = config_desc.to_owned(); + pub fn init(&self) -> BuckyResult<()> { + Self::gen_service_list_id()?; + + Ok(()) + } - // 首先加载device,用作ServiceList的owner - let device_id = self.load_device()?; - let version = version.to_string(); + fn gen_service_list_id() -> BuckyResult { + let device_id = Self::load_device(&get_system_config().config_desc)?; + let service_list_version = get_system_config().service_list_version.to_string(); // 计算ServiceList对象id let service_list_id = AppList::generate_id( device_id.object_id().to_owned(), - &version, + &service_list_version, APPLIST_SERVICE_CATEGORY, ); info!( - "device config repo: device_id={}, service_list_id={}, version={}", - device_id, service_list_id, version + "device config repo: config_desc={}, device_id={}, service_list_id={}, version={}", + get_system_config().config_desc, device_id, service_list_id, service_list_version ); - self.service_list_id = Some(service_list_id); - self.device_id = Some(device_id); - - Ok(()) + Ok(service_list_id) } - fn load_device(&self) -> BuckyResult { - assert!(self.device_id.is_none()); - - let ret = LOCAL_DEVICE_MANAGER.load(&self.desc); + fn load_device(desc: &str) -> BuckyResult { + let ret = LOCAL_DEVICE_MANAGER.load(&desc); if let Err(e) = ret { - error!("load config desc failed! desc={}, err={}", self.desc, e); + error!("load config desc failed! desc={}, err={}", desc, e); return Err(e); } @@ -198,14 +186,13 @@ impl DeviceConfigMetaRepo { } async fn load_service_list(&self) -> BuckyResult { - assert!(self.service_list_id.is_some()); - - let object_id = self.service_list_id.as_ref().unwrap(); - let ret = MetaClientHelper::get_object(&self.meta_client, object_id).await?; + + let service_list_id = Self::gen_service_list_id()?; + let ret = MetaClientHelper::get_object(&self.meta_client, &service_list_id).await?; if ret.is_none() { let msg = format!( "load service list object from meta chain but not found! id={}", - object_id + service_list_id ); error!("{}", msg); @@ -216,7 +203,7 @@ impl DeviceConfigMetaRepo { // 解码 let list = AppList::clone_from_slice(&object_raw).map_err(|e| { - let msg = format!("decode service list object failed! id={}, {}", object_id, e); + let msg = format!("decode service list object failed! id={}, {}", service_list_id, e); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -224,7 +211,7 @@ impl DeviceConfigMetaRepo { debug!( "load service list object success! id={:?}, list={:?}", - self.service_list_id, + service_list_id, list.app_list() ); @@ -464,8 +451,7 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { } debug!( - "load device_config from meta: device_id={}, config={}", - self.device_id.as_ref().unwrap(), + "load device_config from meta: config={}", device_config_str ); From 61ec28225293814acae71530d783733791c9d8f1 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 15:59:40 +0800 Subject: [PATCH 303/553] Fix two warning after package updated --- src/component/cyfs-base/build.rs | 2 +- .../cyfs-lib/src/base/requestor_helper.rs | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-base/build.rs b/src/component/cyfs-base/build.rs index 9cd52e271..919d0c275 100644 --- a/src/component/cyfs-base/build.rs +++ b/src/component/cyfs-base/build.rs @@ -59,7 +59,7 @@ fn main() { println!( "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + chrono::Local::now().format("%y-%m-%d") ); println!("cargo:rerun-if-changed=protos"); diff --git a/src/component/cyfs-lib/src/base/requestor_helper.rs b/src/component/cyfs-lib/src/base/requestor_helper.rs index 23d6a49dc..1b63024b2 100644 --- a/src/component/cyfs-lib/src/base/requestor_helper.rs +++ b/src/component/cyfs-lib/src/base/requestor_helper.rs @@ -809,12 +809,19 @@ impl RequestorHelper { 0 }; - let time = NaiveDateTime::from_timestamp(secs as i64, nsecs as u32); - - let dt = DateTime::::from_utc(time, Utc); - let s = dt.to_rfc2822(); - - req.insert_header(name, s); + let time = NaiveDateTime::from_timestamp_opt(secs as i64, nsecs as u32); + match time { + Some(time) => { + let dt = DateTime::::from_utc(time, Utc); + let s = dt.to_rfc2822(); + + req.insert_header(name, s); + } + None => { + error!("invalid timestamp format! {}.{}", secs, nsecs); + } + } + } pub async fn request_to_service( From 0fa41cfc2711bc1d96f4b821dabbf0e710a8b59c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 304/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index ca2a714ee..4a1a3eb58 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -206,7 +206,6 @@ dependencies = [ "cyfs-base-meta", "cyfs-core", "cyfs-debug", - "cyfs-lib", "cyfs-meta-lib", "cyfs-util", "lazy_static", From d6261f271068aea7f884ba015907f7d2e262615a Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 305/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/Cargo.lock | 1164 ++++++++--------- src/service/ood-daemon/Cargo.toml | 3 +- .../src/config/device_config_manager.rs | 58 +- .../ood-daemon/src/config/system_config.rs | 51 +- src/service/ood-daemon/src/config/version.rs | 4 +- .../ood-daemon/src/config_repo/test.rs | 11 +- src/service/ood-daemon/src/daemon/daemon.rs | 12 +- src/service/ood-daemon/src/daemon/stop.rs | 9 +- src/service/ood-daemon/src/repo/manager.rs | 29 +- .../ood-daemon/src/status/service_status.rs | 6 +- 10 files changed, 704 insertions(+), 643 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 4a1a3eb58..b892d402f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -111,9 +111,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" [[package]] name = "android_logger" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" +checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" dependencies = [ "android_log-sys", "env_logger", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "app-manager" @@ -262,9 +262,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ "concurrent-queue", "event-listener", @@ -283,23 +283,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", @@ -329,31 +329,32 @@ dependencies = [ [[package]] name = "async-io" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ + "async-lock", "autocfg 1.1.0", "concurrent-queue", "futures-lite", "libc", "log 0.4.17", - "once_cell", "parking", "polling", "slab", "socket2", "waker-fn", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -370,27 +371,27 @@ dependencies = [ [[package]] name = "async-process" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" +checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" dependencies = [ "async-io", + "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", - "once_cell", "signal-hook", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ "proc-macro2", "quote", @@ -492,9 +493,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -525,9 +526,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -535,7 +536,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -557,9 +558,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -773,16 +774,16 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", + "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", - "once_cell", ] [[package]] @@ -793,14 +794,14 @@ checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" dependencies = [ "base64 0.13.1", "bollard-stubs", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "dirs-next", "futures-core", "futures-util", "hex", "http", - "hyper 0.14.20", + "hyper 0.14.24", "hyperlocal", "log 0.4.17", "pin-project", @@ -848,13 +849,11 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" dependencies = [ - "lazy_static", "memchr", - "regex-automata", "serde", ] @@ -866,15 +865,15 @@ checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -884,9 +883,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" [[package]] name = "byteorder" @@ -906,15 +905,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -951,9 +950,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -984,16 +983,16 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.44", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -1109,7 +1108,7 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "memchr", ] @@ -1121,11 +1120,11 @@ checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" [[package]] name = "concurrent-queue" -version = "1.2.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ - "cache-padded", + "crossbeam-utils", ] [[package]] @@ -1302,22 +1301,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1325,9 +1324,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -1390,13 +1389,12 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -1431,9 +1429,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -1443,9 +1441,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -1458,15 +1456,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -1513,7 +1511,7 @@ dependencies = [ "simple_logger 2.3.0", "sqlx", "url 2.3.0", - "zip", + "zip 0.6.4", ] [[package]] @@ -1565,7 +1563,7 @@ dependencies = [ "log 0.4.17", "lru_time_cache", "md5", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.7.3", "ringbuf", @@ -1621,7 +1619,7 @@ dependencies = [ "cyfs-util", "dirs 4.0.0", "log 0.4.17", - "sysinfo 0.26.5", + "sysinfo 0.26.9", ] [[package]] @@ -1637,7 +1635,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1661,7 +1659,7 @@ dependencies = [ "scan_dir", "sha2 0.8.2", "shared_memory", - "sysinfo 0.26.5", + "sysinfo 0.26.9", ] [[package]] @@ -1678,7 +1676,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "time 0.1.44", + "time 0.1.45", "url 2.3.0", ] @@ -1702,7 +1700,7 @@ version = "0.6.4" dependencies = [ "bip39", "cyfs-base", - "digest 0.10.5", + "digest 0.10.6", "hex", "hmac 0.12.1", "log 0.4.17", @@ -1768,7 +1766,6 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", - "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1779,10 +1776,9 @@ dependencies = [ "protoc-bin-vendored", "protoc-rust", "rand 0.8.5", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", - "sha2 0.8.2", ] [[package]] @@ -1832,65 +1828,6 @@ dependencies = [ "sha2 0.8.2", ] -[[package]] -name = "cyfs-group" -version = "0.1.1" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "chrono", - "cyfs-base", - "cyfs-bdt", - "cyfs-chunk-lib", - "cyfs-core", - "cyfs-debug", - "cyfs-group-lib", - "cyfs-lib", - "futures", - "itertools", - "lazy_static", - "log 0.4.17", - "prost 0.11.8", - "prost-build 0.9.0", - "protobuf", - "protoc-bin-vendored", - "protoc-rust", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", -] - -[[package]] -name = "cyfs-group-lib" -version = "0.1.1" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "chrono", - "cyfs-base", - "cyfs-core", - "cyfs-debug", - "cyfs-lib", - "cyfs-util", - "futures", - "http-types", - "itertools", - "lazy_static", - "log 0.4.17", - "prost 0.11.8", - "prost-build 0.9.0", - "protobuf", - "protoc-bin-vendored", - "protoc-rust", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", -] - [[package]] name = "cyfs-lib" version = "0.8.0" @@ -1899,7 +1836,7 @@ dependencies = [ "async-std", "async-trait", "async-tungstenite", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "cyfs-base", "cyfs-bdt", @@ -2187,7 +2124,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.2.1", + "bytes 1.4.0", "clap", "cyfs-base", "cyfs-bdt", @@ -2242,8 +2179,6 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", - "cyfs-group", - "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -2261,18 +2196,18 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.8", - "prost-build 0.11.3", + "prost 0.11.6", + "prost-build 0.11.6", "protoc-bin-vendored", "rand 0.8.5", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", "sha2 0.8.2", "sqlx", "tide", "toml", - "zip", + "zip 0.6.4", ] [[package]] @@ -2318,7 +2253,7 @@ dependencies = [ "regex", "serde", "toml", - "toml_edit", + "toml_edit 0.15.0", ] [[package]] @@ -2403,7 +2338,7 @@ dependencies = [ "log 0.4.17", "log-panics", "named-lock", - "nix 0.24.2", + "nix 0.24.3", "once_cell", "rand 0.8.5", "rusqlite", @@ -2416,7 +2351,7 @@ dependencies = [ "url 2.3.0", "walkdir", "winapi", - "zip", + "zip 0.6.4", ] [[package]] @@ -2464,7 +2399,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] @@ -2540,9 +2475,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -2615,9 +2550,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "email-encoding" @@ -2701,9 +2636,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "env_logger" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "log 0.4.17", "regex", @@ -2711,9 +2646,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" +checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" dependencies = [ "serde", ] @@ -2729,7 +2664,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itertools", - "paste 1.0.9", + "paste 1.0.11", "rustc-hex", "serde", "serde_json", @@ -2865,9 +2800,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -2904,14 +2839,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -2934,9 +2869,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -2968,7 +2903,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.4", + "spin 0.9.5", ] [[package]] @@ -3028,9 +2963,18 @@ dependencies = [ [[package]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] [[package]] name = "fuchsia-cprng" @@ -3046,9 +2990,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -3061,9 +3005,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -3071,15 +3015,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -3089,20 +3033,20 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.12.1", + "parking_lot 0.11.2", ] [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -3121,9 +3065,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -3132,21 +3076,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -3167,7 +3111,7 @@ dependencies = [ "async-h1", "async-std", "async-trait", - "bytes 1.2.1", + "bytes 1.4.0", "clap", "cyfs-base", "cyfs-bdt", @@ -3247,9 +3191,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" +checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" dependencies = [ "proc-macro2", "quote", @@ -3258,21 +3202,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -3283,9 +3227,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", @@ -3293,42 +3237,13 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "group-example" -version = "0.1.0" -dependencies = [ - "async-recursion", - "async-std", - "async-trait", - "cyfs-base", - "cyfs-bdt", - "cyfs-bdt-ext", - "cyfs-chunk-lib", - "cyfs-core", - "cyfs-debug", - "cyfs-group-lib", - "cyfs-lib", - "cyfs-meta-lib", - "cyfs-stack", - "cyfs-util", - "futures", - "lazy_static", - "log 0.4.17", - "prost 0.11.8", - "protobuf", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.8.2", -] - [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "fnv", "futures-core", "futures-sink", @@ -3337,7 +3252,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.4", + "tokio-util 0.7.7", "tracing", ] @@ -3403,9 +3318,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -3419,6 +3334,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -3506,7 +3430,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -3533,13 +3457,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "fnv", - "itoa 1.0.4", + "itoa", ] [[package]] @@ -3548,7 +3472,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "http", "pin-project-lite 0.2.9", ] @@ -3624,7 +3548,7 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time 0.1.44", + "time 0.1.45", "traitobject", "typeable", "unicase 1.4.2", @@ -3633,11 +3557,11 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-channel", "futures-core", "futures-util", @@ -3646,7 +3570,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.4", + "itoa", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -3663,16 +3587,16 @@ checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" dependencies = [ "futures-util", "hex", - "hyper 0.14.20", + "hyper 0.14.24", "pin-project", "tokio", ] [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3774,9 +3698,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -3789,7 +3713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" dependencies = [ "indoc-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -3798,7 +3722,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "syn", @@ -3811,6 +3735,26 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -3891,15 +3835,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jni" @@ -3932,18 +3870,41 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] [[package]] name = "kv-log-macro" @@ -3985,7 +3946,7 @@ dependencies = [ "idna 0.2.1", "mime 0.3.16", "native-tls", - "nom 7.1.1", + "nom 7.1.3", "once_cell", "quoted_printable", "socket2", @@ -4006,15 +3967,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libsecp256k1" @@ -4045,9 +4006,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -4116,7 +4077,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" dependencies = [ - "nix 0.23.1", + "nix 0.23.2", "winapi", ] @@ -4128,9 +4089,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "maybe-uninit" @@ -4152,9 +4113,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" dependencies = [ "libc", ] @@ -4168,6 +4129,15 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "memzero" version = "0.1.0" @@ -4249,23 +4219,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] @@ -4300,9 +4270,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -4328,27 +4298,27 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -4364,14 +4334,41 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "notify" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.42.0", +] + [[package]] name = "ntapi" version = "0.4.0" @@ -4424,9 +4421,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" dependencies = [ "byteorder", "lazy_static", @@ -4483,11 +4480,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -4502,18 +4499,18 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "ood-control" @@ -4538,7 +4535,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sysinfo 0.26.5", + "sysinfo 0.26.9", "tide", ] @@ -4565,15 +4562,16 @@ dependencies = [ "http-types", "lazy_static", "log 0.4.17", + "notify", "once_cell", "ood-control", "rand 0.7.3", - "semver 1.0.14", + "semver 1.0.16", "serde", "serde_json", "tide", "toml", - "zip", + "zip 0.6.4", ] [[package]] @@ -4623,9 +4621,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.42" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -4655,9 +4653,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.77" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg 1.1.0", "cc", @@ -4685,7 +4683,7 @@ dependencies = [ "sha2 0.8.2", "simple_logger 2.3.0", "walkdir", - "zip", + "zip 0.6.4", ] [[package]] @@ -4708,7 +4706,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -4728,7 +4726,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -4738,14 +4736,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -4757,15 +4755,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec 1.10.0", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -4786,14 +4784,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "paste-impl" @@ -4801,7 +4799,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", ] [[package]] @@ -4810,7 +4808,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -4850,9 +4848,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -4920,9 +4918,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -4973,16 +4971,16 @@ dependencies = [ [[package]] name = "polling" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -4998,15 +4996,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ "proc-macro2", "syn", @@ -5014,9 +5012,9 @@ dependencies = [ [[package]] name = "primal" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389bfb36ac527b5fe21a57f87bc7956af45cbeb2de7750b90b7ebac6770e715e" +checksum = "4b53cc99c892c461727618e8a63806c94b09ae13c494dc5fc70a7557b3a2f071" dependencies = [ "primal-check", "primal-estimate", @@ -5049,9 +5047,9 @@ checksum = "7374f14c76f23e1271e6be806981ac5dd9e52b59132b0a2f10bcc412495f9159" [[package]] name = "primal-sieve" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fee6031f66b44e8e004ac9bf81fd1c5abcbbb25bd392bc27429daa1759654a" +checksum = "9f2a14766f8c543620824b5b2cec356abf2681b76966a7ac4b4ed2c0011e696a" dependencies = [ "primal-bit", "primal-estimate", @@ -5082,13 +5080,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit 0.18.1", ] [[package]] @@ -5102,9 +5099,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-hack-impl" @@ -5114,9 +5111,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -5127,18 +5124,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ - "bytes 1.2.1", - "prost-derive 0.11.8", + "bytes 1.4.0", + "prost-derive 0.11.6", ] [[package]] @@ -5147,7 +5144,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "heck 0.3.3", "itertools", "lazy_static", @@ -5163,20 +5160,20 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ - "bytes 1.2.1", - "heck 0.4.0", + "bytes 1.4.0", + "heck 0.4.1", "itertools", "lazy_static", "log 0.4.17", "multimap", "petgraph", "prettyplease", - "prost 0.11.8", - "prost-types 0.11.2", + "prost 0.11.6", + "prost-types 0.11.6", "regex", "syn", "tempfile", @@ -5198,9 +5195,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -5215,18 +5212,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.2" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ - "bytes 1.2.1", - "prost 0.11.8", + "bytes 1.4.0", + "prost 0.11.6", ] [[package]] @@ -5235,7 +5232,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", ] [[package]] @@ -5375,18 +5372,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "quoted_printable" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f14e071918cbeefc5edc986a7aa92c425dae244e003a35e1cdddb5ca39b5cb" +checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" [[package]] name = "radium" @@ -5586,21 +5583,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg 1.1.0", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -5656,26 +5651,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -5716,7 +5705,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "rustc-hex", ] @@ -5766,8 +5755,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", - "digest 0.10.5", - "num-bigint-dig 0.8.1", + "digest 0.10.6", + "num-bigint-dig 0.8.2", "num-integer", "num-iter", "num-traits", @@ -5903,15 +5892,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "safemem" @@ -5946,7 +5935,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -5963,12 +5952,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -5979,9 +5967,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "sct" @@ -5995,9 +5983,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.7.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -6008,9 +5996,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -6027,9 +6015,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -6039,9 +6027,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -6058,9 +6046,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -6078,11 +6066,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.4", + "itoa", "ryu", "serde", ] @@ -6105,7 +6093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa", "ryu", "serde", ] @@ -6134,13 +6122,13 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6160,7 +6148,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6202,7 +6190,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -6248,16 +6236,16 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.17", - "nix 0.23.1", + "nix 0.23.2", "rand 0.8.5", "win-sys", ] [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -6265,9 +6253,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -6301,7 +6289,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "winapi", ] @@ -6314,7 +6302,7 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "winapi", ] @@ -6327,15 +6315,15 @@ dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", + "time 0.3.19", "windows-sys 0.42.0", ] [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg 1.1.0", ] @@ -6414,9 +6402,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" dependencies = [ "lock_api", ] @@ -6438,7 +6426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom 7.1.1", + "nom 7.1.3", "unicode_categories", ] @@ -6462,11 +6450,11 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.2.1", + "bytes 1.4.0", "chrono", "crc", "crossbeam-queue", - "digest 0.10.5", + "digest 0.10.6", "either", "event-listener", "flume", @@ -6479,14 +6467,14 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.4", + "itoa", "libc", "libsqlite3-sys", "log 0.4.17", "memchr", "num-bigint 0.3.3", "once_cell", - "paste 1.0.9", + "paste 1.0.11", "percent-encoding 2.2.0", "rand 0.8.5", "rsa 0.6.1", @@ -6511,7 +6499,7 @@ checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.4.0", + "heck 0.4.1", "once_cell", "proc-macro2", "quote", @@ -6665,9 +6653,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -6688,9 +6676,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.5" +version = "0.26.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade661fa5e048ada64ad7901713301c21d2dbc5b65ee7967de8826c111452960" +checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -6770,9 +6758,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -6798,18 +6786,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -6818,10 +6806,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -6859,9 +6848,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -6885,16 +6874,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ - "itoa 1.0.4", + "itoa", "libc", "num_threads", "serde", "time-core", - "time-macros 0.2.5", + "time-macros 0.2.7", ] [[package]] @@ -6909,15 +6898,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "time-macros-impl", ] [[package]] name = "time-macros" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" dependencies = [ "time-core", ] @@ -6928,7 +6917,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "proc-macro-hack 0.5.19", + "proc-macro-hack 0.5.20+deprecated", "proc-macro2", "quote", "standback", @@ -6965,19 +6954,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.21.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg 1.1.0", - "bytes 1.2.1", + "bytes 1.4.0", "libc", "memchr", "mio", "num_cpus", "pin-project-lite 0.2.9", "socket2", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -6986,7 +6975,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-core", "futures-sink", "log 0.4.17", @@ -6996,11 +6985,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ - "bytes 1.2.1", + "bytes 1.4.0", "futures-core", "futures-sink", "pin-project-lite 0.2.9", @@ -7010,9 +6999,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "indexmap", "serde", @@ -7020,9 +7009,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" [[package]] name = "toml_edit" @@ -7036,6 +7025,17 @@ dependencies = [ "toml_datetime", ] +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -7044,9 +7044,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite 0.2.9", @@ -7080,9 +7080,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" @@ -7092,7 +7092,7 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.2.1", + "bytes 1.4.0", "http", "httparse", "log 0.4.17", @@ -7111,15 +7111,15 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "uint" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", @@ -7147,15 +7147,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -7168,9 +7168,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -7192,9 +7192,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unindent" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "universal-hash" @@ -7269,9 +7269,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version-compare" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" @@ -7341,9 +7341,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "serde", @@ -7353,9 +7353,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log 0.4.17", @@ -7368,9 +7368,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7380,9 +7380,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7390,9 +7390,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -7403,15 +7403,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -7456,9 +7456,9 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", @@ -7532,37 +7532,48 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" @@ -7572,15 +7583,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" @@ -7590,15 +7595,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" @@ -7608,15 +7607,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" @@ -7626,21 +7619,15 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" @@ -7650,15 +7637,9 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "wyz" @@ -7686,9 +7667,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", @@ -7696,6 +7677,20 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zip" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "flate2", + "thiserror", + "time 0.1.45", +] + [[package]] name = "zip" version = "0.6.4" @@ -7712,19 +7707,19 @@ dependencies = [ "hmac 0.12.1", "pbkdf2", "sha1 0.10.5", - "time 0.3.16", + "time 0.3.19", "zstd", ] [[package]] name = "zip-extract" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb654964c003959ed64cbd0d7b329bcdcbd9690facd50c8617748d3622543972" +checksum = "4c5cc0309f6e81ab96c2b43d5e935025f8732c886690be8f78f68e06bad1d274" dependencies = [ "log 0.4.17", "thiserror", - "zip", + "zip 0.5.13", ] [[package]] @@ -7798,10 +7793,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.7+zstd.1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" dependencies = [ "cc", "libc", + "pkg-config", ] diff --git a/src/service/ood-daemon/Cargo.toml b/src/service/ood-daemon/Cargo.toml index dad44f82a..cef02b40b 100644 --- a/src/service/ood-daemon/Cargo.toml +++ b/src/service/ood-daemon/Cargo.toml @@ -36,4 +36,5 @@ http-types = "2.12" hex = "0.4" tide = "0.16" rand = '0.7' -semver = "1.0" \ No newline at end of file +semver = "1.0" +notify = "5.1" \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 7e52b619e..7394a575f 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -7,30 +7,59 @@ use cyfs_base::*; use cyfs_debug::Mutex; use lazy_static::lazy_static; -use once_cell::sync::OnceCell; use std::sync::Arc; use std::time::Duration; +struct DeviceConfigRepoItem { + desc: String, + repo: DeviceConfigRepoRef, +} + pub struct DeviceConfigManager { - repo: OnceCell, + repo: Mutex>, device_config_hash: Mutex>, device_config: DeviceConfig, } impl DeviceConfigManager { - pub fn new() -> Self { + fn new() -> Self { Self { - repo: OnceCell::new(), + repo: Mutex::new(None), device_config_hash: Mutex::new(None), device_config: DeviceConfig::new(), } } pub fn init(&self) -> BuckyResult<()> { + self.init_repo()?; + + // 计算当前device_config的hash + let hash = Self::calc_config_hash(); + *self.device_config_hash.lock().unwrap() = hash; + + Ok(()) + } + + // can be init multi times! + pub fn init_repo(&self) -> BuckyResult<()> { // 从system_config获取device_config依赖的desc let desc = &get_system_config().config_desc; + { + let current = self.repo.lock().unwrap(); + match &*current { + Some(item) => { + if item.desc == *desc { + return Ok(()); + } + + info!("device config's desc changed! {} -> {}", item.desc, desc); + } + None => {} + } + } + info!("will init device_config repo: {}", desc); let repo = if desc == "local" { @@ -38,9 +67,7 @@ impl DeviceConfigManager { Box::new(repo) as Box } else if desc == "cyfs_repo" || desc == "device" { let repo = DeviceConfigMetaRepo::new(); - if let Err(e) = repo.init() { - return Err(e); - } + repo.init()?; Box::new(repo) as Box } else if desc.starts_with("http") { @@ -54,17 +81,18 @@ impl DeviceConfigManager { return Err(BuckyError::new(BuckyErrorCode::NotSupport, msg)); }; - if let Err(_) = self.repo.set(Arc::new(repo)) { - unreachable!(); - } - - // 计算当前device_config的hash - let hash = Self::calc_config_hash(); - *self.device_config_hash.lock().unwrap() = hash; + *self.repo.lock().unwrap() = Some(DeviceConfigRepoItem { + desc: desc.to_owned(), + repo: Arc::new(repo), + }); Ok(()) } + pub fn get_repo(&self) -> DeviceConfigRepoRef { + self.repo.lock().unwrap().as_ref().unwrap().repo.clone() + } + pub async fn load_and_apply_config(&self) -> BuckyResult<()> { self.device_config .load_and_apply_config() @@ -117,7 +145,7 @@ impl DeviceConfigManager { } pub async fn fetch_config(&self) -> Result { - let repo = self.repo.get().unwrap().clone(); + let repo = self.get_repo(); // 从mete-chain拉取对应desc let ret = async_std::future::timeout(Duration::from_secs(60), repo.fetch()).await; diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index fa50b80f4..0560c025d 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -1,14 +1,16 @@ use super::path::PATHS; -use super::version::{ServiceVersion, ServiceListVersion}; +use super::version::{ServiceListVersion, ServiceVersion}; +use super::DEVICE_CONFIG_MANAGER; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; use std::sync::Arc; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct SystemConfig { // device_config动态更新依赖的desc文件,默认从cyfs_repo,可以指定device标识当前设备 // ServiceList对象会使用该id+version,来计算当前依赖的ServiceList对象,并从链上拉取 @@ -28,7 +30,7 @@ pub struct SystemConfig { } impl SystemConfig { - pub fn new() -> Self { + fn new() -> Self { Self { config_desc: String::from("cyfs_repo"), @@ -53,14 +55,12 @@ impl SystemConfig { return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } - info!("will load system-config file: {}", config_file.display()); + debug!("will load system-config file: {}", config_file.display()); let node = self.load_as_json(&config_file).await?; self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } @@ -165,28 +165,47 @@ impl SystemConfig { return Err(BuckyError::from(msg)); } - info!( - "system-config: config_desc={}, target={}", - self.config_desc, self.target - ); - Ok(()) } } -use once_cell::sync::OnceCell; -static SYSTEM_CONFIG: OnceCell> = OnceCell::new(); +use std::sync::Mutex; +static SYSTEM_CONFIG: Mutex>> = Mutex::new(None); // 只在进程初始化时候调用一次 pub async fn init_system_config() -> BuckyResult<()> { let mut system_config = SystemConfig::new(); system_config.load_config().await?; - SYSTEM_CONFIG.set(Arc::new(system_config)).unwrap(); + info!("init system config: {:?}", system_config); + *SYSTEM_CONFIG.lock().unwrap() = Some(Arc::new(system_config)); + + SystemConfigMonitor::start(); Ok(()) } -pub fn get_system_config() -> Arc { - SYSTEM_CONFIG.get().unwrap().clone() +pub async fn reload_system_config() -> BuckyResult<()> { + let mut system_config = SystemConfig::new(); + system_config.load_config().await?; + + debug!("reload system config success! {:?}", system_config); + { + let mut current = SYSTEM_CONFIG.lock().unwrap(); + if current.as_deref() != Some(&system_config) { + info!( + "reload system config and changed! {:?} -> {:?}", + current.as_deref(), system_config + ); + *current = Some(Arc::new(system_config)); + } + } + + let _ = DEVICE_CONFIG_MANAGER.init_repo(); + + Ok(()) } + +pub fn get_system_config() -> Arc { + SYSTEM_CONFIG.lock().unwrap().clone().unwrap() +} \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/version.rs b/src/service/ood-daemon/src/config/version.rs index 1822f6403..d29d91009 100644 --- a/src/service/ood-daemon/src/config/version.rs +++ b/src/service/ood-daemon/src/config/version.rs @@ -2,7 +2,7 @@ use cyfs_base::*; use std::str::FromStr; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum ServiceListVersion { Nightly, // default version Specific(String), // user confined @@ -38,7 +38,7 @@ impl FromStr for ServiceListVersion { } // 版本列表定义 -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum ServiceVersion { Default, // use the version config in service list Specific(String), // semver, * as the newest version diff --git a/src/service/ood-daemon/src/config_repo/test.rs b/src/service/ood-daemon/src/config_repo/test.rs index 81ee0f461..ec734df71 100644 --- a/src/service/ood-daemon/src/config_repo/test.rs +++ b/src/service/ood-daemon/src/config_repo/test.rs @@ -1,14 +1,13 @@ -use crate::config::DeviceConfigManager; +use crate::config::DEVICE_CONFIG_MANAGER; use crate::init_system_config; async fn test() { init_system_config().await.unwrap(); + + DEVICE_CONFIG_MANAGER.init().unwrap(); - let config_manager = DeviceConfigManager::new(); - config_manager.init().unwrap(); - - config_manager.fetch_config().await.unwrap(); - config_manager.fetch_config().await.unwrap(); + DEVICE_CONFIG_MANAGER.fetch_config().await.unwrap(); + DEVICE_CONFIG_MANAGER.fetch_config().await.unwrap(); } #[test] diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index c4f6d0c6b..34737f778 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -1,5 +1,5 @@ use super::gateway_monitor::GATEWAY_MONITOR; -use crate::config::{init_system_config, DeviceConfigManager}; +use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER}; use crate::service::ServiceMode; use crate::service::SERVICE_MANAGER; use cyfs_base::{bucky_time_now, BuckyResult}; @@ -46,7 +46,6 @@ impl Default for ActionActive { #[derive(Clone)] pub struct Daemon { mode: ServiceMode, - device_config_manager: Arc, no_monitor: bool, last_active: Arc, } @@ -54,11 +53,8 @@ pub struct Daemon { impl Daemon { // add code here pub fn new(mode: ServiceMode, no_monitor: bool) -> Self { - let device_config_manager = DeviceConfigManager::new(); - Self { mode, - device_config_manager: Arc::new(device_config_manager), no_monitor, last_active: Arc::new(ActionActive::default()), } @@ -67,7 +63,7 @@ impl Daemon { pub async fn run(&self) -> BuckyResult<()> { init_system_config().await?; - self.device_config_manager.init()?; + DEVICE_CONFIG_MANAGER.init()?; OOD_STATUS_MANAGER.start().await?; @@ -101,7 +97,7 @@ impl Daemon { .map(|v| v.config.fid.clone()); // 首先尝试下载同步配置 - match self.device_config_manager.fetch_config().await { + match DEVICE_CONFIG_MANAGER.fetch_config().await { Ok(changed) => { if changed { need_load_config = true; @@ -115,7 +111,7 @@ impl Daemon { } if need_load_config { - if let Err(e) = self.device_config_manager.load_and_apply_config().await { + if let Err(e) = DEVICE_CONFIG_MANAGER.load_and_apply_config().await { // 加载配置失败,那么需要等下一个周期继续尝试load error!("load config failed! now will retry on next loop! {}", e); } else { diff --git a/src/service/ood-daemon/src/daemon/stop.rs b/src/service/ood-daemon/src/daemon/stop.rs index b0e635901..1d669c2bf 100644 --- a/src/service/ood-daemon/src/daemon/stop.rs +++ b/src/service/ood-daemon/src/daemon/stop.rs @@ -1,26 +1,23 @@ use crate::config::ServiceState; -use crate::config::{init_system_config, DeviceConfigManager, OOD_DAEMON_SERVICE}; +use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER, OOD_DAEMON_SERVICE}; use crate::service::SERVICE_MANAGER; use cyfs_base::*; pub struct ServicesStopController { - device_config_manager: DeviceConfigManager, } impl ServicesStopController { pub fn new() -> Self { - let device_config_manager = DeviceConfigManager::new(); Self { - device_config_manager, } } pub async fn stop_all(&self) -> BuckyResult<()> { init_system_config().await?; - self.device_config_manager.init()?; + DEVICE_CONFIG_MANAGER.init()?; - let mut list = self.device_config_manager.load_config()?; + let mut list = DEVICE_CONFIG_MANAGER.load_config()?; info!("service list: {:?}", list); diff --git a/src/service/ood-daemon/src/repo/manager.rs b/src/service/ood-daemon/src/repo/manager.rs index 1b1f3e27f..eff36e9d4 100644 --- a/src/service/ood-daemon/src/repo/manager.rs +++ b/src/service/ood-daemon/src/repo/manager.rs @@ -73,6 +73,7 @@ pub trait Repo: Send + Sync { pub struct RepoManager { cache_dir: PathBuf, + repo_config: Mutex>, repo_list: Mutex>>>, } @@ -99,6 +100,7 @@ impl RepoManager { pub fn new() -> RepoManager { let cache_dir = Self::cache_dir(); RepoManager { + repo_config: Mutex::new(None), repo_list: Mutex::new(Vec::new()), cache_dir, } @@ -112,6 +114,7 @@ impl RepoManager { let repo = Arc::new(Box::new(repo) as Box); Ok(Self { + repo_config: Mutex::new(None), repo_list: Mutex::new(vec![repo]), cache_dir, }) @@ -221,13 +224,23 @@ impl RepoManager { // 从system_config的repo字段加载配置 pub async fn load(&self, repo_node: &Vec) -> BuckyResult<()> { assert!(repo_node.len() > 0); - assert!(self.repo_list.lock().unwrap().is_empty()); + let config_string = serde_json::to_string(&repo_node).unwrap(); + { + let current = self.repo_config.lock().unwrap(); + if current.as_deref() == Some(&config_string) { + return Ok(()); + } + + info!("repo config changed! {:?} -> {}", &*current, config_string); + } + + let mut list = vec![]; for item in repo_node.iter() { info!("new repo item: {:?}", item); if let toml::Value::Table(m) = item { let repo = Self::load_repo_item(&m).await?; - self.repo_list.lock().unwrap().push(Arc::new(repo)); + list.push(Arc::new(repo)); } else { let msg = format!("unsupport repo item format!"); error!("{}", msg); @@ -235,6 +248,18 @@ impl RepoManager { } } + // Support for repeated loading + { + let mut current = self.repo_list.lock().unwrap(); + if !current.is_empty() { + warn!("will replace current repo list!"); + } + + *current = list; + } + + *self.repo_config.lock().unwrap() = Some(config_string); + Ok(()) } diff --git a/src/service/ood-daemon/src/status/service_status.rs b/src/service/ood-daemon/src/status/service_status.rs index 8fa4b1278..e19b25b7f 100644 --- a/src/service/ood-daemon/src/status/service_status.rs +++ b/src/service/ood-daemon/src/status/service_status.rs @@ -1,5 +1,5 @@ -use crate::SERVICE_MANAGER; -use crate::config::{ServiceState, ServiceConfig, DeviceConfigManager}; +use crate::{SERVICE_MANAGER}; +use crate::config::{ServiceState, ServiceConfig, DEVICE_CONFIG_MANAGER}; use crate::service::ServicePackageLocalState; use cyfs_base::bucky_time_now; @@ -71,7 +71,7 @@ impl OODDaemonStatusGenerator { } fn gen() -> OODDaemonStatus { - let device_config = match DeviceConfigManager::new().load_config() { + let device_config = match DEVICE_CONFIG_MANAGER.load_config() { Ok(list) => list, Err(_) => vec![], }; From a07e1f8b85f0d4367c6a2670d17a2fbae313a21e Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:35:08 +0800 Subject: [PATCH 306/553] Add dynamic monitoring mechanism for system-config.toml --- src/service/ood-daemon/src/config/mod.rs | 1 + src/service/ood-daemon/src/config/monitor.rs | 75 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/service/ood-daemon/src/config/monitor.rs diff --git a/src/service/ood-daemon/src/config/mod.rs b/src/service/ood-daemon/src/config/mod.rs index 6836c142d..5383a844a 100644 --- a/src/service/ood-daemon/src/config/mod.rs +++ b/src/service/ood-daemon/src/config/mod.rs @@ -4,6 +4,7 @@ mod path; mod device_config_manager; mod device_config; mod version; +mod monitor; pub use device_config::DeviceConfig; pub use service_config::*; diff --git a/src/service/ood-daemon/src/config/monitor.rs b/src/service/ood-daemon/src/config/monitor.rs new file mode 100644 index 000000000..925be909d --- /dev/null +++ b/src/service/ood-daemon/src/config/monitor.rs @@ -0,0 +1,75 @@ +use super::path::PATHS; +use super::reload_system_config; +use cyfs_base::*; + + + +pub struct SystemConfigMonitor { + watcher: Option, +} + +impl SystemConfigMonitor { + pub fn start() { + use once_cell::sync::OnceCell; + + static INIT: OnceCell = OnceCell::new(); + INIT.get_or_init(|| { + let watcher = Self::start_monitor().ok(); + + Self::start_periodic_check(); + Self { + watcher, + } + }); + } + + fn start_periodic_check() { + async_std::task::spawn(async move { + loop { + async_std::task::sleep(std::time::Duration::from_secs(60 * 15)).await; + let _ = reload_system_config().await; + } + }); + } + + fn start_monitor() -> BuckyResult { + use notify::{RecursiveMode, Watcher}; + + let mut watcher = notify::recommended_watcher(|res| match res { + Ok(event) => { + info!("got system config file event: {:?}", event); + + if PATHS.system_config.is_file() { + async_std::task::spawn(async move { + let _ = reload_system_config().await; + }); + } + } + Err(e) => error!("watch system config file error: {:?}", e), + }) + .map_err(|e| { + let msg = format!("create system-config.toml monitor failed! {}", e); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::NotSupport, msg) + })?; + + watcher + .watch(&PATHS.system_config, RecursiveMode::NonRecursive) + .map_err(|e| { + let msg = format!( + "watch system-config.toml monitor failed! file={}, {}", + PATHS.system_config.display(), + e + ); + error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + info!( + "start monitor system-config file change! file={}", + PATHS.system_config.display() + ); + + Ok(watcher) + } +} \ No newline at end of file From 8b0099c08d723ec2bc5f909174a466fb0cffe24b Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:43:37 +0800 Subject: [PATCH 307/553] Fix two log param errors --- .../cyfs-base/src/objects/object_map/isolate_path_env.rs | 2 +- src/component/cyfs-base/src/objects/object_map/single_env.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs b/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs index f871a9d6c..2cc26a3f1 100644 --- a/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs +++ b/src/component/cyfs-base/src/objects/object_map/isolate_path_env.rs @@ -130,7 +130,7 @@ impl ObjectMapIsolatePathOpEnv { if value.is_none() { let msg = format!( "load ioslate_path_op_env with inner_path but not found! root={}, inner_path={}", - obj_map_id, obj_map_id, + obj_map_id, inner_path, ); error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); diff --git a/src/component/cyfs-base/src/objects/object_map/single_env.rs b/src/component/cyfs-base/src/objects/object_map/single_env.rs index 9cfc50cd2..e529df0cd 100644 --- a/src/component/cyfs-base/src/objects/object_map/single_env.rs +++ b/src/component/cyfs-base/src/objects/object_map/single_env.rs @@ -140,7 +140,7 @@ impl ObjectMapSingleOpEnv { if value.is_none() { let msg = format!( "load single_op_env with inner_path but not found! root={}, inner_path={}", - obj_map_id, obj_map_id, + obj_map_id, inner_path, ); error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); From db5be356e7c8ca6c033daaddd1ff9514d1bf0f45 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 19:07:13 +0800 Subject: [PATCH 308/553] Add mechanism that trigger immediate update after system config changes --- src/service/ood-daemon/src/config/mod.rs | 3 +- src/service/ood-daemon/src/config/monitor.rs | 57 +++++++++++++------ .../ood-daemon/src/config/system_config.rs | 16 ++---- src/service/ood-daemon/src/daemon/daemon.rs | 40 ++++++++----- .../ood-daemon/src/service/service_manager.rs | 8 ++- 5 files changed, 78 insertions(+), 46 deletions(-) diff --git a/src/service/ood-daemon/src/config/mod.rs b/src/service/ood-daemon/src/config/mod.rs index 5383a844a..d623631bc 100644 --- a/src/service/ood-daemon/src/config/mod.rs +++ b/src/service/ood-daemon/src/config/mod.rs @@ -11,4 +11,5 @@ pub use service_config::*; pub use system_config::*; pub use path::*; pub use version::*; -pub use device_config_manager::{DeviceConfigManager, DEVICE_CONFIG_MANAGER}; \ No newline at end of file +pub use device_config_manager::{DeviceConfigManager, DEVICE_CONFIG_MANAGER}; +pub use monitor::SystemConfigMonitor; \ No newline at end of file diff --git a/src/service/ood-daemon/src/config/monitor.rs b/src/service/ood-daemon/src/config/monitor.rs index 925be909d..d7246003f 100644 --- a/src/service/ood-daemon/src/config/monitor.rs +++ b/src/service/ood-daemon/src/config/monitor.rs @@ -1,47 +1,68 @@ use super::path::PATHS; use super::reload_system_config; +use crate::config::DEVICE_CONFIG_MANAGER; +use crate::daemon::Daemon; use cyfs_base::*; +use std::sync::Arc; - +#[derive(Clone)] pub struct SystemConfigMonitor { - watcher: Option, + watcher: Arc>, + daemon: Daemon, } impl SystemConfigMonitor { - pub fn start() { + fn new(daemon: Daemon) -> Self { + let watcher = Self::start_monitor(daemon.clone()).ok(); + + Self::start_periodic_check(daemon.clone()); + Self { + watcher: Arc::new(watcher), + daemon, + } + } + + pub fn start(daemon: Daemon) { use once_cell::sync::OnceCell; static INIT: OnceCell = OnceCell::new(); - INIT.get_or_init(|| { - let watcher = Self::start_monitor().ok(); - - Self::start_periodic_check(); - Self { - watcher, - } - }); + INIT.get_or_init(|| Self::new(daemon)); } - fn start_periodic_check() { + async fn on_changed(daemon: &Daemon) -> BuckyResult<()> { + let changed = reload_system_config().await?; + if !changed { + return Ok(()); + } + + let _ = DEVICE_CONFIG_MANAGER.init_repo(); + + daemon.wakeup_check_update(); + + Ok(()) + } + + fn start_periodic_check(daemon: Daemon) { async_std::task::spawn(async move { loop { - async_std::task::sleep(std::time::Duration::from_secs(60 * 15)).await; - let _ = reload_system_config().await; + async_std::task::sleep(std::time::Duration::from_secs(60 * 60)).await; + let _ = Self::on_changed(&daemon).await; } }); } - fn start_monitor() -> BuckyResult { + fn start_monitor(daemon: Daemon) -> BuckyResult { use notify::{RecursiveMode, Watcher}; - let mut watcher = notify::recommended_watcher(|res| match res { + let mut watcher = notify::recommended_watcher(move |res| match res { Ok(event) => { info!("got system config file event: {:?}", event); if PATHS.system_config.is_file() { + let daemon = daemon.clone(); async_std::task::spawn(async move { - let _ = reload_system_config().await; + let _ = Self::on_changed(&daemon).await; }); } } @@ -72,4 +93,4 @@ impl SystemConfigMonitor { Ok(watcher) } -} \ No newline at end of file +} diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 0560c025d..1f5341cc0 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -1,10 +1,8 @@ use super::path::PATHS; use super::version::{ServiceListVersion, ServiceVersion}; -use super::DEVICE_CONFIG_MANAGER; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; -use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -59,9 +57,7 @@ impl SystemConfig { let node = self.load_as_json(&config_file).await?; - self.parse_config(node).await?; - - Ok(()) + self.parse_config(node).await } async fn load_as_json(&self, file_path: &Path) -> BuckyResult { @@ -180,16 +176,15 @@ pub async fn init_system_config() -> BuckyResult<()> { info!("init system config: {:?}", system_config); *SYSTEM_CONFIG.lock().unwrap() = Some(Arc::new(system_config)); - SystemConfigMonitor::start(); - Ok(()) } -pub async fn reload_system_config() -> BuckyResult<()> { +pub async fn reload_system_config() -> BuckyResult { let mut system_config = SystemConfig::new(); system_config.load_config().await?; debug!("reload system config success! {:?}", system_config); + let mut changed = false; { let mut current = SYSTEM_CONFIG.lock().unwrap(); if current.as_deref() != Some(&system_config) { @@ -198,12 +193,11 @@ pub async fn reload_system_config() -> BuckyResult<()> { current.as_deref(), system_config ); *current = Some(Arc::new(system_config)); + changed = true; } } - let _ = DEVICE_CONFIG_MANAGER.init_repo(); - - Ok(()) + Ok(changed) } pub fn get_system_config() -> Arc { diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index 34737f778..4c59ca60e 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -1,11 +1,11 @@ use super::gateway_monitor::GATEWAY_MONITOR; -use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER}; +use crate::config::{init_system_config, DEVICE_CONFIG_MANAGER, SystemConfigMonitor}; use crate::service::ServiceMode; use crate::service::SERVICE_MANAGER; +use crate::status::OOD_STATUS_MANAGER; use cyfs_base::{bucky_time_now, BuckyResult}; use cyfs_util::*; use ood_control::OOD_CONTROLLER; -use crate::status::OOD_STATUS_MANAGER; use async_std::task; use futures::future::{AbortHandle, Abortable}; @@ -48,6 +48,7 @@ pub struct Daemon { mode: ServiceMode, no_monitor: bool, last_active: Arc, + check_update_waker: Arc>>, } impl Daemon { @@ -57,6 +58,7 @@ impl Daemon { mode, no_monitor, last_active: Arc::new(ActionActive::default()), + check_update_waker: Arc::new(Mutex::new(None)), } } @@ -75,6 +77,8 @@ impl Daemon { let _ = GATEWAY_MONITOR.init().await; + SystemConfigMonitor::start(self.clone()); + self.start_check_active(); self.start_check_service_state(); @@ -84,6 +88,13 @@ impl Daemon { Ok(()) } + pub fn wakeup_check_update(&self) { + if let Some(abort_handle) = self.check_update_waker.lock().unwrap().take() { + info!("will wakeup check update now!"); + abort_handle.abort(); + } + } + async fn run_check_update(&self, notify: BindNotify) { let mut need_load_config = true; loop { @@ -177,19 +188,20 @@ impl Daemon { // 检查绑定状态 let timer = task::sleep(Duration::from_secs(60 * 10)); - if OOD_CONTROLLER.is_bind() { - timer.await; - } else { - let (abort_handle, abort_registration) = AbortHandle::new_pair(); - *notify.abort_handle.lock().unwrap() = Some(abort_handle); - match Abortable::new(timer, abort_registration).await { - Ok(_) => { - debug!("check loop wait timeout, now will check once"); - } - Err(futures::future::Aborted { .. }) => { - info!("check loop waked up, now will check once"); - } + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + + if !OOD_CONTROLLER.is_bind() { + *notify.abort_handle.lock().unwrap() = Some(abort_handle.clone()); + } + *self.check_update_waker.lock().unwrap() = Some(abort_handle); + + match Abortable::new(timer, abort_registration).await { + Ok(_) => { + debug!("check update loop wait timeout, now will check once"); + } + Err(futures::future::Aborted { .. }) => { + info!("check update loop waked up, now will check once"); } } } diff --git a/src/service/ood-daemon/src/service/service_manager.rs b/src/service/ood-daemon/src/service/service_manager.rs index 2d1540057..4f656c614 100644 --- a/src/service/ood-daemon/src/service/service_manager.rs +++ b/src/service/ood-daemon/src/service/service_manager.rs @@ -462,9 +462,13 @@ impl ServiceManager { pub async fn sync_service_packages(&self) { let _lock = self.sync_lock.lock().await; - debug!("will sync all service packages"); - let service_list = self.service_list.lock().unwrap().clone(); + if service_list.is_empty() { + warn!("sync all service packages but is empty!"); + return; + } + + debug!("will sync all service packages"); for (name, service_info) in service_list { if service_info.service.is_none() { error!("service not init yet! name={}", name); From 48416d1dee1e344dafbc24b7b58d12b80db06075 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 19:27:37 +0800 Subject: [PATCH 309/553] Try using git commit logs to organize changelog --- CHANGELOG-nightly.md | 743 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 743 insertions(+) create mode 100644 CHANGELOG-nightly.md diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md new file mode 100644 index 000000000..0c79dfc4b --- /dev/null +++ b/CHANGELOG-nightly.md @@ -0,0 +1,743 @@ +## [1.0.0.718] -- 2023/2/21 +1b0cf118 Change sync services packages from parallel to serial +638848a2 Remove two spawn task using for cancel on timeout +70837da7 Fix error op_env type check in requestor +e3f55f6e Improve timeout and retry strategy for repo download in ood-daemon service +9c3c63ab Meta db initialization switch to transaction mode +1e4e4277 Modify: add some statistic logs for ndn +94d8f7a4 Merge branch '104-appmanager-suppport-local-app-repo-store' +34580770 Modify: add some statistic logs for ndn +7522c0fe Email Sender support starttls +10d27023 App Manager support install app from local repo +2a3c1dc1 ood-installer support sync app repo +51f0be28 WIP: App Manager Support Local Repo +e6392f5b WIP: App Manager reflator app install logic +e65fe061 WIP: AppManager add repo type, use zip_extract to extract app service package + +## [1.0.0.715] -- 2023/2/20 +e51af4f2 Set docker api timeout to 300s +b213c3fe Fix: tcp not update active time when recv packet +24553a9c Improve the object layer strategy detection of after pass the first layer rpath access verification +574cfddf OOD-daemon will now report an error and exit if it fails to load the repo +0ab51327 Add version output in process alive check log +14c004b6 Fix meta-stat email format +4daab080 App-manager report app status to ood-daemon +c09ddea9 Fix field names of ood status +f3449363 Fix: monitor create desc when desc not existed on chain +a4e0e755 Fix: stream break when loss fin ack packet +0d2393f3 Fix: monitor create desc error +ba302dd4 Merge remote-tracking branch 'origin/107-support-multiple-global-states-in-cyfs-stack' into main +3d70797d Add group state test case +63e3e712 Fix a assert error when global state is init +61a5eff1 Cyfs monitor use generated identify to test metachain read and write +3d4aefc9 Improve the use of u64::MAX in two places +ee5323ea Delete some useless logs +90d9b5c8 meta spv support storage anbd query objects by object id, body hash +1101829c Add isolate_id method for GlobalStateRawProcessor +e3765b61 Add global state raw processor for use by external components of cyfs-stack +ff03c824 Add the persistence mechanism of all the global state list +b4c4de04 Refactor GlobalStateManager to support multiple global-states +937c7dbe Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +b4284830 Add exists methods into collection for to check if exists +5bcc2984 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +da09ed21 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +412d03ff Merge branch '99-recycle-unused-bdt-tunnel-instances' +979773da Fix: implement stream reserving 2*msl state with lru cache +25c53b07 Refactory: export private methods with pub(crate) +114f1d1b Fix: bdt unit test sn with ipv6 endpoints +fdde1948 Merge branch '95-ipv6-support-refactory' +1b91764a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8d522ec7 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +1875de3d Add object and name for meta in cyfs-stack +3e12b1be Fix cyfs-perf deps Improve the format of some tomls +e83890fc Add noc meta cache to optimize update last access write operation +2ff85f4d Publish cyfs-core new version +d917d648 Bump cyfs-core version +0dd49104 Fix cyfs-core deps +220c7ab2 Fix compile error +dd2f2f17 Publish new cargo packages +fb63c476 Bump cargo package version and dependences +89917227 Merge branch 'main' into beta +75aea584 Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8f60a00b Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +2ebd1e20 Add object and name for meta in cyfs-stack +4d5a9e90 Fix cyfs-perf deps Improve the format of some tomls +2121a11e Add noc meta cache to optimize update last access write operation +078b27d3 Publish cyfs-core new version +019b09d9 Bump cyfs-core version +51e4365b Fix cyfs-core deps +a04d6e88 Fix compile error +038b75b4 Publish new cargo packages +279ce4bd Bump cargo package version and dependences +026c1383 Merge branch 'main' into beta +ccb044db Integrate ood-daemon services status +4af47a92 Improve ServiceState fields spelling +f9eaed01 Add service status related def +ec1ba569 ood-daemon adds independent status http server +5bc02595 Add service status support to ood-daemon +ff14b0d1 Add external http server support to ood control +287c9468 Fix app-manager compile error +08249fa5 Cyfs Monitor restore case interval time after success +c6c372dc Add noc test cases +b176d6a5 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +97bd7bb9 Print warning when decapp missing status or stop scripts +9f85c599 Stream shutdown success at closed state +71ffede0 Fix: fix reset key logic +ec2194ec Integrate ood-daemon services status +2b30769b Improve ServiceState fields spelling +eb881d46 Add service status related def +5dc9c661 ood-daemon adds independent status http server +b2882ff5 Add service status support to ood-daemon +cfc87989 Add external http server support to ood control +d54866c2 Fix app-manager compile error +f0822e79 Cyfs Monitor restore case interval time after success +ab37ea21 Add noc test cases +fa1cc5c0 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +13cdfe46 Print warning when decapp missing status or stop scripts +5ad5d183 Fix: bdt unit test sn with ipv6 endpoints +9607470d Merge branch '95-ipv6-support-refactory' +a8ba267a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +5c2a8d77 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +c88a5e76 Add object and name for meta in cyfs-stack +598df4a8 Fix cyfs-perf deps Improve the format of some tomls +1952c7ee Add noc meta cache to optimize update last access write operation +ba181cef Publish cyfs-core new version +139a9ab6 Bump cyfs-core version +11c7205a Fix cyfs-core deps +76f871ea Fix compile error +30f99d3d Publish new cargo packages +4228e263 Bump cargo package version and dependences +34cb38f4 Merge branch 'main' into beta +87956987 Integrate ood-daemon services status +086dcd8a Improve ServiceState fields spelling +51f135c6 Add service status related def +0bd37768 ood-daemon adds independent status http server +933ed8cd Add isolate_path_env stub test cases +1be055d0 Add service status support to ood-daemon +d3e16c4d Add native ioslate_path_env component test cases and fix some test warnings +25fa3e85 Add external http server support to ood control +60b04789 Add ioslate path env stub +4b32f2b0 Optimize objectmap path to support non-transactional mode +5a6aa9b7 Integrate isolate path env into global-state services +6ccd4ef9 Add isolate path env impl +c78ae028 Fix app-manager compile error +429bddd8 Cyfs Monitor restore case interval time after success +9dd5aac3 Add noc test cases +c7132f26 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +cbf80ee3 Print warning when decapp missing status or stop scripts +2451a583 Fix: package enter write closed state correctly +0d4443ff Panic manager supports multiple bug reporters +f6749bb1 Stream shutdown success at closed state +f1a4cc60 Create a directory if it does not exist when downloading to a local file +28a37154 Improve cyfs-stack's control strategy for task manager resume_task +a63d6854 Fix: fix reset key logic +b7a3e3c9 Add dingtalk_bug_report method to PanicBuilder for external use +445fc501 Optimize some logs output +cc70a84b Add init-ood-daemon param to ood-installer +28fbed65 Remove cyfs-bdt's dependence on os-id lib +18d1534d Improve the ndn request logs output +8538be10 Add req_path suport to front o protocol for acl +1a621713 Send start notify when cyfs-monitor started +e8752b2a Improve the problem that the front r protocol cannot correctly handle data req_path for acl +4abdcf6b Use search instead of get for device in context +c8ad90a8 Add target device prompt info to access reject msg for better debug +4cc08abb Improve cyfs stack test cases +9cf2aafe Improve some logs output about chunk cache +b30d8cd6 Fix: chunk list task download split chunks dumplicatedly +c2570da0 Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +b7ecdbc7 Fix: using channel got reserved correctly +a8a9a3b9 Fix: cyfs-monitor report, use sn-online-test to test sn server status +c3964a38 impl: log udp socket's recv loop thread os id +cb239140 Improve some logs output +67b2aed5 Add seperate sn-online-test program +b6e22b0f Fix: cyfs stack resp interest with NotFound if chunk not exists on default +e1bbe10d Fix: Add some log for dectecting zero speed source +d3535025 Fix: modify resend piece control send time +04629f0f Fix: channel ignore estimate request for sequence lost +11bfb5a5 Correct the use of sync mechanism on bdt download context +d2d9ff8f Bdt acl callback can correctly handle empty referer now +a2ebb0df Changed to auto cancel strategy for ndn task with context param +d653c967 Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +a2cb418a Remove useless ood_resolver field from ndn service relate codes +236abdbb Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +cb0cba8a Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +dce764a9 Add object and name for meta in cyfs-stack +e0dac397 Fix: tcp stream don't reset tunnel when break +5af0b5fb Fix: implement stream reserving 2*msl state with lru cache +3da42793 Fix cyfs-perf deps Improve the format of some tomls +9867ad29 Add noc meta cache to optimize update last access write operation +e11ff3ef Publish cyfs-core new version +95a5c99d Bump cyfs-core version +c168c17a Fix cyfs-core deps +427050c6 Fix compile error +2412d747 Integrate ood-daemon services status +aa5ff976 Publish new cargo packages +0249ba77 Bump cargo package version and dependences +96e3bb69 Merge branch 'main' into beta +0493c935 Improve ServiceState fields spelling +5a88c564 Add service status related def +00bf2764 ood-daemon adds independent status http server +c013612e Fix: bdt mem device cache limited size +39de9529 Refactory: export private methods with pub(crate) +7785029d Fix: package enter write closed state correctly +101db063 Stream shutdown success at closed state +3fca43d8 Create a directory if it does not exist when downloading to a local file +ac0e4f2a Improve cyfs-stack's control strategy for task manager resume_task +4d8bfacc Fix: fix reset key logic +96e1c1e6 Panic manager supports multiple bug reporters +8d9b7929 Add dingtalk_bug_report method to PanicBuilder for external use +7825a4ea Optimize some logs output +fa6867c6 Add init-ood-daemon param to ood-installer +9aa4489c Remove cyfs-bdt's dependence on os-id lib +66b856fc Improve the ndn request logs output +c0622388 Add req_path suport to front o protocol for acl +cc24f8e0 Send start notify when cyfs-monitor started +10ace371 Improve the problem that the front r protocol cannot correctly handle data req_path for acl +6c59337d Use search instead of get for device in context +ef0f880d Add target device prompt info to access reject msg for better debug +beb0e7be Add service status support to ood-daemon +edc1d1f6 Add external http server support to ood control +e5e9a3a5 Refactory: stream release tunnel guard when closed +009c3c8a Refactory: export private methods with pub(crate) +8e21764a Refactory: export private methods with pub(crate) +743c2fcf Impl: recycle unused tunnel +b4eb9f85 Add isolate_path_env stub test cases +b0c6fd63 Add native ioslate_path_env component test cases and fix some test warnings +3f14f978 Impl: add a test for sn ipv6 ping +ff916188 Add ioslate path env stub +dd437a1f Impl: sn support ipv6 ping +b69709df Optimize objectmap path to support non-transactional mode +0de3fc0c Integrate isolate path env into global-state services +edacc65a Add isolate path env impl +29fed496 Remove complie warning +f3f66501 Impl: Add transfered and recursion close method to ndn task +027e9ae4 Impl: Add transfered and recursion close method to ndn task +6a1f7ed1 Rebase: rebase to 74-integrate-bdt-task-context-and-group +aa682520 Refactory: impl trans api for close upload group +260cbdf8 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +c2bd5612 Refactory: impl trans api for close upload group +99bbebfc Refactory: impl trans api for upload group +c19064b5 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +2f47bcc0 Fix: reserve or recycle channels when all reference released +ae3f02eb Impl: cancel task with user defined error +82692c64 Fix: download task progress/speed +bc3ba88e Rebase: rebase to 74-integrate-bdt-task-context-and-group +58d6d195 Refactory: impl trans api for close upload group +5dad1539 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +30aa07ae Fix: reserve or recycle channels when all reference released +acaa42fb Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +09076f70 Add uptime and boot_time into get_system_info +2b81e62a Fix: correctly wait dapp process +3bbbcfc3 Add total trans bytes field in get_system_info Added network card deduplication in some environments +80fa0863 Publish new cargo packages +ae40d694 Fix cyfs-util publish error +ee957a29 Bump cargo packages version +89341b52 Fix: retry sn list when offline +1370e83c Improve ndn test case with get_data +3584395e Improve the resp's return logic of get_data with error prompt +a3a5172e Use of http requestor for get_data and put_data methods as default +0347e50e Error of reading resp is returned correctly in ws mode +87d26ad6 Merge remote-tracking branch 'origin/main' into main +0df70f89 Sync projects for trans and stack object relate apis's changes +2ef0d178 Fix a compile error with requestor config and some warnings +4b716f44 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +1a15a767 Fix: trigger chunk downloader's on_drain method +e9faea63 Add some logs +a8dedd60 Add serialization support for storage base on global state +6effd696 Add log for named-data-client chunk reading +9edf7c31 Merge branch '74-integrate-bdt-task-context-and-group' +3fcdbf0c Improve ood-daemon's upgrade detection and restart logic +e0323ea1 Add host mode support to browser sanbox +91e519ec Also check app exclude list when install or start app +66acc69e Merge pull request #88 from buckyos/fix-container-dns +f1a63712 Ood-installer support only start ood-daemon +6514acec Fix AppManager startup param +ee80ce8c Fix AppManager config path, load config after log init +cb2ac1ee Mixed the usage of different requestor config for zone simulator stacks +be10f64b Add shared stack cache logic to zone simulator +5da765af Remove shared stack support and cache from cyfs-stack-loader +c2708f59 Improve open shared stack relate logic and add requestor config params +6150617a Temporarily disable all ipv6 addresses for bdt stack +95654ae5 App Manager AppSource logic +e849439c AppManager supports more detailed configuration +715e851e WIP: add new config for app manager +2ded38db Modify the way to start file uploader +0a50ed5f Improve the update state relate logic for service in ood-daemon service +c7de6539 Fix: avoid duplicate hole punching process when retry sn call +e828e7b5 Merge remote-tracking branch 'origin/fix-container-dns' +f8f4381b Add --startup-mode for ood-daemon startup script +c7bf12f2 Add startup-mode to ood-daemon service with network verify on system startup +b9aca01d Add active check in daemon update and state check loop +dc6aa3d9 Add timeout for repo in ood-daemon service +20ec54d1 Start the monitor service synchronously on startup +2e66ff4a Add service_list cache mechanism for meta config repo +d758151b Remove the local status of meta config repo in ood-daemon service +f99caadc Fix: retry sn list when builder not establish in time +b143379f Integrate surf requestor into shared stack +7eed812f App-tool and app-tool-ex return error correctly +09f79e9a Remove redundant service requestors constructor +cd8588de Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f5873108 Add surf based requestor +889d7f81 Adjust the file directory structure of requestsors in cyfs-lib +e7e9781e Fix some compile errors and warnings +3aa50d32 Remove the useless base project +4de7e33d Add app-manager.toml config file support to ood-installer tool +9317c01d Remove the useless old configuration of acl.toml +5af28985 Improve the error status of build relate tasks +a762fecf Merge branch 'fix-container-dns' into beta +b3231559 Fix compile +832e7a20 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b2471088 Fix container dns, when resolv contain 127.0.0.53 +bde55b1a Merge branch 'main' into beta +4dd330fe Merge branch 'main' into beta +35cabb3f Merge branch 'main' into beta +bd9326c9 File upload tool only support windows & mac for now. +01a46434 Open upload tool with "open" cmd on Mac +b45d377f Fix:ping client doesn't update local device +b36e728e Fix:ping client doesn't update local device +d9bd6698 Remove handler and event manager's none mode +980b5392 Add some field compatibility with the old version's data on new db format +6541571a Fix: pannic on time escape of call session +c0ceda78 Improve ws session and manager stop-related timing logic +f30cc9c8 Fix: some warning with while let +473e56d6 Add delayed start mechanism for router handler and events +74e30500 Fix: downloading speed/progress for chunk_list/file task use percent +172c5c9e Add shared stack stop test case +d670b458 Improve ws and event manager stop strategy +5841a4fb Improve ws session and ws client stop strategy +b62c204a Refactor ws session related logic and improve packet parser logic +706f06e6 Add stop method to shared stack with requestors +b45ddcf1 Enable none mode for handler and event system in shared stack +a1d67489 Optimize the use of requestor by the service component and adopt the shared mode +6acc40fa Remove http handler support for shared stack +5c3abc42 Add stop method to handler and event manager +b24935d7 Add stop method for ws client +6f55517f Publish new cargo packages +8c933ffc Fix cyfs-util publish error +bf75d29e Bump cargo packages version +bce2a745 Merge branch 'main' into beta +acbd636a Refactory: Add track chunk method option to publish dir/file methods +a022c2cc Fix the bug that search context will enter an infinite loop +a8a57c27 Improve the result of router get_object with flash flags is true +9f3d4e8d Fix the bug for decode context path param without fix +4236102e Add router support for group relate methods Add target check for publish_file method +3d758fcd Merge branch 'main' into beta +0843bbba Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead (#87) +387362a2 Rebase: rebase to 74-integrate-bdt-task-context-and-group +8bdf227b Refactory: impl trans api for close upload group +18ed9311 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +3f52efd9 Impl: cancel task with user defined error +9627d57a Fix: download task progress/speed +e0292e40 Fix: download task progress/speed +addd1976 Refactory: impl trans api for close upload group +dcb4395e Refactory: impl trans api for upload group +db6750fd Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +9f10434a Fix: reserve or recycle channels when all reference released +3ffb8c7e Refactor the file task and chunk task and use a consistent impls at the lower layer +603b5377 Impl: cancel task with user defined error +e66ab510 Fix: download task progress/speed +538a7111 Rebase: rebase to 74-integrate-bdt-task-context-and-group +f720dac7 Refactory: impl trans api for close upload group +a3d86db0 Refactory: impl trans api for upload group +31a93c96 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +f2287d89 Fix query_tasks error and add some logs for task +8ed9f7f2 Sync context manager modifications with bdt +7d6ceaa8 Refactor the context state session manager with source and chunk as unique index +50fb0345 Refactor the download task to better support state switching and task release +a9fe0654 Fix the read logic error for SharedMemChunk +2f89e98d Refactory: change context update_at to async function +f9bbc140 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +4643e4d5 Refactory: add update at property for download context +da234ea1 Fix: reserve or recycle channels when all reference released +a63f74ea Router handler support empty string as filter and will treat as none +5475581f Improve the local file & chunk writers logs +3758c0a0 Refactor the file task and chunk task and use a consistent impls at the lower layer +680f18e2 Add chunk type support for verify_file_task +f237b25b Add state manager with context for ndn task to cancel task on source error +d46a8abb Refactory: add method on_drain for download context +b88929fd Impl: cancel task with user defined error +81c297f0 Sync test cases with interface modification +9ead4762 Add access support for build_dir_from_object_map source object's access +078811fa Add get_object_map_ex with access field return for object_map relate cache +2e1d1924 Add access param support for publish_file and build_file relate methods +eb62b863 Add access support to put_object_map relate methods +dd1caba5 Add some logs for task manager +2b843a47 Fix: download task progress/speed +db13d228 Improve some logs output +f00b77c2 Add from_str support for access string +7c92e607 Add alias for trans output requests +c08c3e36 Improve the log and error codes for local file relate codes +7821234f Use insert_chunk instead of update_chunk_state for chunk state updater +91f0177a Improve insert_chunk logic with update state when already exists for ndc module +ddd8f8e6 Improve some logs output for ndn relate codes +4f637a9d Refactory: interest reponse upload field tokens +1c12c499 Fix: download task finish directly when total length is zero +a43ef9db Fix: download task progress/speed +e94e9560 Fix: download task progress/speed +307c10b5 Refactory: impl trans api for close upload group +a9071c13 Refactory: impl trans api for upload group +763791ba Refactory: upload handler with group_path filter; upload handler response with upload from path +96603e3c Refactory: impl download task progress +191497e7 Fix: finish download leaf task +311aba18 Refactory: upload task group cancel/close +38d8d707 Refactory: Add logic leaf download task +f0141ccc Refactory: chunk downloader send interest with group_path field +6291029a Refactory: chunk downloader not mergable +1684b91f Fix: pannic on udp call +0cf29489 Merge branch 'main' into bdt-beta +5bd73033 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +7805227c Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +a4dbe34f Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +8611caff Fix: add log for ping clients +71af78d7 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +7a1d4b82 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +5540f89e Fix: the status of udp stream +e5307fac Fix: cc loss bytes in stream write +229dbc6a Add reset_sn_list() function in Stack's ineterface. +b469a288 Upload get-nearest SN Server in client call. The build-tunnel-params's remote-sn is priority over get-nearest sn-list. +a564d9ee Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta + +## [1.0.0.713] -- 2023/2/11 +ab8a2a6c Fix app-manager compile error +cd7eb6b4 Cyfs Monitor restore case interval time after success +7a03fdb3 Add noc test cases +bb596b85 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +20d14f19 Print warning when decapp missing status or stop scripts + +## [1.0.0.711] -- 2023/2/11 +2c798622 Fix: package enter write closed state correctly +be780df7 Stream shutdown success at closed state +21aef793 Create a directory if it does not exist when downloading to a local file +b6b7e7f8 Improve cyfs-stack's control strategy for task manager resume_task +c0f775cc Fix: fix reset key logic +c90f6ae9 Panic manager supports multiple bug reporters +07f2717d Add dingtalk_bug_report method to PanicBuilder for external use +db4acc4b Optimize some logs output +fb13f654 Add init-ood-daemon param to ood-installer +8f8e88c2 Remove cyfs-bdt's dependence on os-id lib +c05e88b7 Improve the ndn request logs output +7e0c03b0 Add req_path suport to front o protocol for acl +e3d042a0 Send start notify when cyfs-monitor started +2b3a433e Improve the problem that the front r protocol cannot correctly handle data req_path for acl +11e6ed60 Use search instead of get for device in context +06498f24 Add target device prompt info to access reject msg for better debug +7c753b20 Improve cyfs stack test cases +851f1a04 Improve some logs output about chunk cache +7cce9079 Fix: chunk list task download split chunks dumplicatedly + +## [1.0.0.709] -- 2023/2/7 +3005944e Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +0a004af9 Fix: using channel got reserved correctly +1bfe7b55 Fix: cyfs-monitor report, use sn-online-test to test sn server status +8aa6a426 impl: log udp socket's recv loop thread os id +a1d30562 Improve some logs output +4bf5e29c Add seperate sn-online-test program +82e71892 Fix: cyfs stack resp interest with NotFound if chunk not exists on default +7af6ce69 Fix: Add some log for dectecting zero speed source +d593800f Fix: modify resend piece control send time +b5c41727 Fix: channel ignore estimate request for sequence lost +21a3cb11 Correct the use of sync mechanism on bdt download context +42b7029e Bdt acl callback can correctly handle empty referer now +52709bc8 Changed to auto cancel strategy for ndn task with context param +acde7c48 Remove complie warning +6834b67a Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +4c3370f4 Remove useless ood_resolver field from ndn service relate codes + +## [1.0.0.708] -- 2023/2/6 +4e1122df Fix: the status of udp stream +58c545d7 Improve the handling of non.get_object when the target object cannot be found in (dir or objectmap) + inner_path mode +78904db7 Switch cyfs-ndc and cyfs-tracker-cache db to use SqliteConnectionHolder +932f1c61 Add SqliteConnectionHolder for general db connection management Switch cyfs-noc db to use SqliteConnectionHolder +5f1db008 impl: add a download context strategy to cancel source when zero speed +044bc59c Fix: ndn timer triggered correctly +d6bccc0f The read and write mode of Meta db is separated to support read-only in special cases such as disk is full etc + +## [1.0.0.707] -- 2023/2/3 +0ac77054 Fix the coding stability problem of Dir about HashMap +85cdd9cb Change some Mutex to cyfs-debug's checked Mutex in ood-daemon +5a448ccd Fix the deadlock bug that may be caused by service state detection +24177f29 Add test cases for config repo in ood-daemon project +8c7465ea Fix the coding stability problem of AppList and AppLocalStatus about HashMap +47d820ae Add sort by name strategy for device-config.toml +df39550f Fix the init error of trans store when the db dir is missing +bad1a48d Add inner path support for SingleOpEnvStub +cec8822c Add inner_path support for single_op_env.load method +26c68baa Fix some warning and add some comments +dc3b6e74 Update cyfs-bdt-ext deps +e977dcc9 Move LocalDeviceManager from cyfs-stack-loader to cyfs-util Remove the dependency on cyfs-stack-loader of ood-daemon and ood-installer +b09291cb Add stop_all support to stop all the services for ood-daemon +e031b4b5 Remove useless codes in cyfs-stack project +efb2431c Merge remote-tracking branch 'origin/92-more-convenient-and-suitable-to-use-cyfs-bdt' into main +170eedcf Move group and data relate codes to cyfs-bdt-ext project +259c46c4 Switched cyfs-stack to rely on cyfs-bdt-ext +965803d5 Move relate components to cyfs-bdt-ext project +00f5b35b Add cyfs-bdt-ext project +50036402 Add uptime and boot_time into get_system_info +a166c72d Fix: correctly wait dapp process +20ddf1d0 Add total trans bytes field in get_system_info Added network card deduplication in some environments +ec08c584 Publish new cargo packages +b6db6f9b Fix cyfs-util publish error +cd204231 Bump cargo packages version +cd120a75 Fix: retry sn list when offline +338c31b8 Improve ndn test case with get_data +9ee1a6d4 Improve the resp's return logic of get_data with error prompt +87b0693e Use of http requestor for get_data and put_data methods as default +6f4d47a0 Error of reading resp is returned correctly in ws mode +114c040a Merge remote-tracking branch 'origin/main' into main +a5c5da0e Sync projects for trans and stack object relate apis's changes +b51738f3 Fix a compile error with requestor config and some warnings +d7950257 Fix: trigger chunk downloader's on_drain method +95abf250 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +fd22bdec Add some logs +4a459fd3 Add serialization support for storage base on global state +068cde9a Add log for named-data-client chunk reading +cd0f3c5f Fix a compile error +ab7cf9e1 Merge branch '74-integrate-bdt-task-context-and-group' +63a37de6 Improve ood-daemon's upgrade detection and restart logic +6850633e Add host mode support to browser sanbox +d4d2639d Improve the error status of build relate tasks +7aa93795 Fix the bug that search context will enter an infinite loop +3ff1412f Improve the result of router get_object with flash flags is true +1ff3ff2e Fix the bug for decode context path param without fix +6bd563c9 Integrate surf requestor into shared stack +dc6d5ebb Remove redundant service requestors constructor +066ebd0e Add surf based requestor +066fe787 Also check app exclude list when install or start app +32b62e13 Adjust the file directory structure of requestsors in cyfs-lib +4ed6ddd2 Merge pull request #88 from buckyos/fix-container-dns +7404ab2e Merge branch 'fix-container-dns' into beta +93c35af4 Add router support for group relate methods Add target check for publish_file method +647b53ba Fix query_tasks error and add some logs for task +37c9bd9c Sync context manager modifications with bdt +78dd780c Refactor the context state session manager with source and chunk as unique index +f05bcd8b Refactor the download task to better support state switching and task release +c028b5bc Fix the read logic error for SharedMemChunk +f50bf84b Refactory: change context update_at to async function +7a2582f6 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +475de4ad Refactory: add update at property for download context +d0200673 Fix: reserve or recycle channels when all reference released +eda71af7 Ood-installer support only start ood-daemon +a491c000 Fix AppManager startup param +d2fa72e0 Fix AppManager config path, load config after log init +409c38f9 Router handler support empty string as filter and will treat as none +51d8dc8f Mixed the usage of different requestor config for zone simulator stacks +70e1e833 Add shared stack cache logic to zone simulator +37cae961 Remove shared stack support and cache from cyfs-stack-loader +eb77a092 Improve open shared stack relate logic and add requestor config params +00b8cf65 Improve the local file & chunk writers logs +e0f14387 Refactor the file task and chunk task and use a consistent impls at the lower layer +e138e06c Add chunk type support for verify_file_task +3fb583e0 Add state manager with context for ndn task to cancel task on source error +200c8922 Refactory: add method on_drain for download context +72e2bb30 Impl: cancel task with user defined error +a0413319 Sync test cases with interface modification +473334df Add access support for build_dir_from_object_map source object's access +973718a1 Add get_object_map_ex with access field return for object_map relate cache +4a547ca3 Add access param support for publish_file and build_file relate methods +78d8f93e Add access support to put_object_map relate methods +750e65d5 Add some logs for task manager +58d90843 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b398e932 Fix: download task finish directly when total length is zero +2b415e37 Fix: download task progress/speed +54965e6c Improve some logs output +f62cb4df Refactory: impl download task progress +bbec1935 Fix: finish download leaf task +fd230411 Refactory: upload task group cancel/close +4c2f95b4 Refactory: Add logic leaf download task +eab160ec Refactory: chunk downloader send interest with group_path field +50db1d5c Refactory: chunk downloader not mergable +062bf19e Add from_str support for access string +2243fa7b Add alias for trans output requests +ebb67790 Improve the log and error codes for local file relate codes +ff7dd4c1 Use insert_chunk instead of update_chunk_state for chunk state updater +0525944c Improve insert_chunk logic with update state when already exists for ndc module +fc2d8b18 Improve some logs output for ndn relate codes +128a7cc5 Fix: some warning with while let +f1890ba3 Add chunk exists check for ndn get_data cache mechanism +18c94cf2 Improve some error process in std::io poll relate methods +06f03a6a Improve the conversion between BuckyError and std::io::Error +e801b468 Improve put_chunk for local chunk cache +23a61570 Add cache mechanism to ndn get_data +9055ec35 Refactory: add group_path field to interest packet +1093046b Add range support for ndn get_data with chunk +e3797e31 Add group test case +5061b962 Refactory: poll split read +e700a047 Use {dec_id}/ as default group when no group param is specified +14339d1a Remove dec_id field of context object Add global context support for context +6922dfa0 Put_context is adjusted to depend on context manager Add access field for put_context request +968e5e6d Fix context path fix error & add test case +b70f7990 Fix error when context manager parse context string with object_id +de18c885 Add ndn context test cases Fix compile errors of trans relate methods +8687e171 Fix ndn referer param encode error +be8f06b3 Add debug output for changed of context +abcc02d8 Remove context_id field for query tasks request +21421faf Fix: build error for cyfs-stack +4f62dbad Fix: build error for cyfs-stack +6d6ccad3 Improve resp process for trans & sync api methods +3eb6ca28 Refactor put_context and get_context methods for trans +5ad7e7f1 Improve the clone_from_slice method for ObjectId +9ece347b Refactor context support for trans +7340db07 Refactor ndn api target related codes to support context +458ad1f6 Refactor context to support target mode +9ea97744 Add context field for ndn get_data request +4a0aa1b6 Adapt to bdt new context relate params and types +b51eed19 Add cache and path search category to context manager +f0427489 Add dec_id field for context object, and add strict limit to context_path field +3441fdb0 Refactory: rename ChunkEncodeDesc => ChunkCodecDesc; declare context.source_of as async function; +04db0d46 Add context holder generator for context manager +6081a426 Add context manager and holder core impls +23eb4af0 Refactor the TransContext core object +73d7dcb1 Add dec limit for trans task group relate methods +abda8cfc Improve the param of TransOutputProcessor methods +a3678c4e Improve the trans.query_tasks request path +0fb35dbb Add task group relate methods for trans api +c78b3568 Add a common impl of serde code for JsonCodec +70366e60 Refactor get_task_state method's response to add group support +2d335eff Add group field for DownloadTaskState +ba606857 Add task group for ndn get_data resp +bbb16276 Improve the url query parse for referer and group params +5fae309c Add task group support for NDN/Trans modules +71414249 Rename the task range reader +a5107424 Optimize the ChunkWriter write method +b5ba81fb DirLoader switch to reply on chunk_store_reader instead of local_data_manager +89df6fcc NDN local_data_manager's get relate impls switch to reply on target_data_manager instead +bdfabe75 Fix: split read test +12610350 Fix: cyfs stack ndn event apply to new bdt ndn interface +816e7f6b Refactor the param model of ndc/tracker/chunk_manager +a397bd52 Adapt to bdt's new download stream model +2d5eb444 Impl: split read for download task reader +6cd9410e Impl: Add Single source context +95c8554a Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +5a1f23af Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +6111f439 Fix: Release chunk cache and downloader with weak reference +ffc56abe Refactory:create seperate downloader when context is not mergable +1ff8388e Refactory: add loading state to chunk cache +8e3590a2 Refactory: split chunk downloader from chunk cache +f2a3672f Fix: call cc on_loss with error loss count value +1dd8bae3 Fix: Donwload task path logic +4f3a92c4 Fix: return download task speed +371792c0 Fix: use BuckyError instead of BuckyErrorCode in some state +167664c9 Fix: add chunk_list_writer method to TrackedChunkStore +b4a67578 Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta +2e42dae0 Fix: stream chunk encoder always read cache with sync reader +bb954d5f Impl: Unit test for upload from path +8b7aa861 Refactory: Add start_upload_from_cache method +81014478 Refactory: Move ndn default event handler to utils +def00192 Refactory: remove default ndc/tracker from bdt stack +67f29271 Refactory: Taskgroup makesure path +896b39ba Impl: File raw cache for chunk +bc043adc In SN statistic, add endpoint's statistic. +ecb58708 Call sn support MTU_LARGE +2cf4567b Add Mutlity SN。 +2321e02c Fix: tcp tunnel send piece buffer with mtu +2ac27f33 Refactory: add DownloadContext trait +6832e73e Refactory: add DownloadContext trait +330a8940 Support large mtu and question&answer +e03962a7 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +d1cc885e Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +06d89662 Fix: chunk list task reader +f4d20813 Fix: close/finish download task group +5bd2ec64 Fix: task.reader return unexpected not found error +7d2e6f6f Fix:panic on download reader +de837c47 Refactory: write chunk from task.reader +677e444b Refactory: Reader of download task +c0a479e3 Refactory: Upload session wait establish +22e9cc0f Refactory: download/upload differs in tcp/udp tunnel +638a8fc4 Refactory: download/upload differs in tcp/udp tunnel +23251581 Fix: bind tunnel with upload/download session +70292ce4 Fix: cache packages in tunnel.build_send, send them when tunnel actived +197e241a Merge branch 'ndn-cache' into bdt-beta +51d5b714 Merge branch 'ndn-cache' into bdt-beta +ea1dae46 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +16d25537 Merge branch 'ndn-cache' into bdt-beta +c6bf684a log decrypt aeskey error info +79bceeea Fix: chunk list task reader +bc380433 Fix: close/finish download task group +61714a7b Fix: task.reader return unexpected not found error +97c955d7 Fix:panic on download reader +1e95e4da Refactory: write chunk from task.reader +9ad964fb Refactory: Reader of download task +d8bf33a0 Refactory: Upload session wait establish +06f3affc Refactory: download/upload differs in tcp/udp tunnel +2ef44f99 Refactory: download/upload differs in tcp/udp tunnel +8519534c Fix: bind tunnel with upload/download session +b2925e95 Fix: cache packages in tunnel.build_send, send them when tunnel actived +7235f3dc Merge branch 'ndn-cache' into bdt-beta +04e2a5a0 Merge branch 'ndn-cache' into bdt-beta +eaa0b650 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +3d711110 Merge branch 'ndn-cache' into bdt-beta +8c8b6039 log decrypt aeskey error info +43ccf15c Impl: Cancel download chunk task +6efb6eca Test: download from uploader test ok +439635f5 Merge branch 'ndn-cache' into bdt-beta +0e08b03a Refactory: download/upload session support reverse step stream +96ffaef7 Refactory: impl download/upload session with new cache +292cf4ae Refactory: impl download/upload session with new cache +d38e31ba Refactory: impl download/upload session with new cache +07b40c65 Refactory: impl download/upload session with new cache +d525a649 Refactory: implement memory raw cache +e07a4b0e Refactory: chunk downloader with stream cache + +## [1.0.0.703] -- 2023/1/13 +cfd654ac Temporarily disable all ipv6 addresses for bdt stack + +## [1.0.0.702] -- 2023/1/12 +bb72348e App Manager AppSource logic +413edbad AppManager supports more detailed configuration +7b0704ec WIP: add new config for app manager +2eb6dce1 Modify the way to start file uploader +6076a69f Improve the update state relate logic for service in ood-daemon service +44fbe781 Fix: avoid duplicate hole punching process when retry sn call +ea48e120 Merge remote-tracking branch 'origin/fix-container-dns' +56f22e21 Add --startup-mode for ood-daemon startup script +cf1f363c Add startup-mode to ood-daemon service with network verify on system startup +56b755e6 Add active check in daemon update and state check loop +b7943988 Fix compile +2b355960 Fix container dns, when resolv contain 127.0.0.53 +d6b5bb06 Add timeout for repo in ood-daemon service +628649f0 Start the monitor service synchronously on startup +de1e9960 Add service_list cache mechanism for meta config repo +a84bfafe Remove the local status of meta config repo in ood-daemon service +a807f171 Fix: retry sn list when builder not establish in time +5639e004 App-tool and app-tool-ex return error correctly +26b234cb Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f136c262 Fix some compile errors and warnings +a4ece723 Remove the useless base project +2d216910 Add app-manager.toml config file support to ood-installer tool +e111f3b2 Remove the useless old configuration of acl.toml +eae9d604 Merge branch 'main' into beta +d5463188 Merge branch 'main' into beta +b34744c3 Merge branch 'main' into beta +180ae196 Remove handler and event manager's none mode +d10953b2 Improve ws session and manager stop-related timing logic +8b84ef3f Add delayed start mechanism for router handler and events +c13cc029 Add shared stack stop test case +faf04a09 Improve ws and event manager stop strategy +c5d02ab9 Improve ws session and ws client stop strategy +007247e2 Refactor ws session related logic and improve packet parser logic +b0463c83 Add stop method to shared stack with requestors +1b80f43a Enable none mode for handler and event system in shared stack +8ec0888b Optimize the use of requestor by the service component and adopt the shared mode +d9d69051 Remove http handler support for shared stack +bb0e005e Add stop method to handler and event manager +1a2ada09 Add stop method for ws client +77ea26c6 Fix: cyfs-client correct get sn list from local stack +e29cd15c Merge branch 'main' into beta +0bb5dcd7 Sync service list method use the lock for services in ood-daemon +19b338e6 Improve some logs output +7e8cb267 Improve cmd status check return value and compare mechanism +fc800657 Improve the agent check for the browser disable mode +67a2179e NamedDataClient use init config, use GetData instead of GetDataWithMeta +e160a62a Improve the get_data logic of chunk_manager +9f7263bc Add memory cache for chunk_manager get_data_with_meta Improve the get_chunk_data resp body mechanism and remove the chunk_id verify temporarily +270778a9 Fix: stream pool use sn list in device cache +b1abf319 Fix: ignore sn list in build param's remote desc +ff05f5ff Fix: beta use correct built-in sn list +02fe10ef Fix: Add logs for build params info +26989db3 Merge branch 'main' into beta +440b90f9 Merge branch 'main' into beta +c377c61f Merge branch 'main' into beta +b0fe871d Merge branch 'main' into beta +ef8a124a Merge branch 'main' into beta +71e9e52b Merge branch 'main' into beta +2fa6be68 Fix: disable cyfs_debug::mutex check in some fraquently called functions From 3bed5f11b79f0762179940507d748c8cc58b23fe Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Thu, 23 Feb 2023 19:51:53 +0800 Subject: [PATCH 310/553] Fix changelog markdown format --- CHANGELOG-nightly.md | 1486 +++++++++++++++++++++--------------------- 1 file changed, 743 insertions(+), 743 deletions(-) diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md index 0c79dfc4b..527382d38 100644 --- a/CHANGELOG-nightly.md +++ b/CHANGELOG-nightly.md @@ -1,743 +1,743 @@ -## [1.0.0.718] -- 2023/2/21 -1b0cf118 Change sync services packages from parallel to serial -638848a2 Remove two spawn task using for cancel on timeout -70837da7 Fix error op_env type check in requestor -e3f55f6e Improve timeout and retry strategy for repo download in ood-daemon service -9c3c63ab Meta db initialization switch to transaction mode -1e4e4277 Modify: add some statistic logs for ndn -94d8f7a4 Merge branch '104-appmanager-suppport-local-app-repo-store' -34580770 Modify: add some statistic logs for ndn -7522c0fe Email Sender support starttls -10d27023 App Manager support install app from local repo -2a3c1dc1 ood-installer support sync app repo -51f0be28 WIP: App Manager Support Local Repo -e6392f5b WIP: App Manager reflator app install logic -e65fe061 WIP: AppManager add repo type, use zip_extract to extract app service package - -## [1.0.0.715] -- 2023/2/20 -e51af4f2 Set docker api timeout to 300s -b213c3fe Fix: tcp not update active time when recv packet -24553a9c Improve the object layer strategy detection of after pass the first layer rpath access verification -574cfddf OOD-daemon will now report an error and exit if it fails to load the repo -0ab51327 Add version output in process alive check log -14c004b6 Fix meta-stat email format -4daab080 App-manager report app status to ood-daemon -c09ddea9 Fix field names of ood status -f3449363 Fix: monitor create desc when desc not existed on chain -a4e0e755 Fix: stream break when loss fin ack packet -0d2393f3 Fix: monitor create desc error -ba302dd4 Merge remote-tracking branch 'origin/107-support-multiple-global-states-in-cyfs-stack' into main -3d70797d Add group state test case -63e3e712 Fix a assert error when global state is init -61a5eff1 Cyfs monitor use generated identify to test metachain read and write -3d4aefc9 Improve the use of u64::MAX in two places -ee5323ea Delete some useless logs -90d9b5c8 meta spv support storage anbd query objects by object id, body hash -1101829c Add isolate_id method for GlobalStateRawProcessor -e3765b61 Add global state raw processor for use by external components of cyfs-stack -ff03c824 Add the persistence mechanism of all the global state list -b4c4de04 Refactor GlobalStateManager to support multiple global-states -937c7dbe Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' -b4284830 Add exists methods into collection for to check if exists -5bcc2984 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' -da09ed21 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' -412d03ff Merge branch '99-recycle-unused-bdt-tunnel-instances' -979773da Fix: implement stream reserving 2*msl state with lru cache -25c53b07 Refactory: export private methods with pub(crate) -114f1d1b Fix: bdt unit test sn with ipv6 endpoints -fdde1948 Merge branch '95-ipv6-support-refactory' -1b91764a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -8d522ec7 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -1875de3d Add object and name for meta in cyfs-stack -3e12b1be Fix cyfs-perf deps Improve the format of some tomls -e83890fc Add noc meta cache to optimize update last access write operation -2ff85f4d Publish cyfs-core new version -d917d648 Bump cyfs-core version -0dd49104 Fix cyfs-core deps -220c7ab2 Fix compile error -dd2f2f17 Publish new cargo packages -fb63c476 Bump cargo package version and dependences -89917227 Merge branch 'main' into beta -75aea584 Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -8f60a00b Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -2ebd1e20 Add object and name for meta in cyfs-stack -4d5a9e90 Fix cyfs-perf deps Improve the format of some tomls -2121a11e Add noc meta cache to optimize update last access write operation -078b27d3 Publish cyfs-core new version -019b09d9 Bump cyfs-core version -51e4365b Fix cyfs-core deps -a04d6e88 Fix compile error -038b75b4 Publish new cargo packages -279ce4bd Bump cargo package version and dependences -026c1383 Merge branch 'main' into beta -ccb044db Integrate ood-daemon services status -4af47a92 Improve ServiceState fields spelling -f9eaed01 Add service status related def -ec1ba569 ood-daemon adds independent status http server -5bc02595 Add service status support to ood-daemon -ff14b0d1 Add external http server support to ood control -287c9468 Fix app-manager compile error -08249fa5 Cyfs Monitor restore case interval time after success -c6c372dc Add noc test cases -b176d6a5 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -97bd7bb9 Print warning when decapp missing status or stop scripts -9f85c599 Stream shutdown success at closed state -71ffede0 Fix: fix reset key logic -ec2194ec Integrate ood-daemon services status -2b30769b Improve ServiceState fields spelling -eb881d46 Add service status related def -5dc9c661 ood-daemon adds independent status http server -b2882ff5 Add service status support to ood-daemon -cfc87989 Add external http server support to ood control -d54866c2 Fix app-manager compile error -f0822e79 Cyfs Monitor restore case interval time after success -ab37ea21 Add noc test cases -fa1cc5c0 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -13cdfe46 Print warning when decapp missing status or stop scripts -5ad5d183 Fix: bdt unit test sn with ipv6 endpoints -9607470d Merge branch '95-ipv6-support-refactory' -a8ba267a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -5c2a8d77 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -c88a5e76 Add object and name for meta in cyfs-stack -598df4a8 Fix cyfs-perf deps Improve the format of some tomls -1952c7ee Add noc meta cache to optimize update last access write operation -ba181cef Publish cyfs-core new version -139a9ab6 Bump cyfs-core version -11c7205a Fix cyfs-core deps -76f871ea Fix compile error -30f99d3d Publish new cargo packages -4228e263 Bump cargo package version and dependences -34cb38f4 Merge branch 'main' into beta -87956987 Integrate ood-daemon services status -086dcd8a Improve ServiceState fields spelling -51f135c6 Add service status related def -0bd37768 ood-daemon adds independent status http server -933ed8cd Add isolate_path_env stub test cases -1be055d0 Add service status support to ood-daemon -d3e16c4d Add native ioslate_path_env component test cases and fix some test warnings -25fa3e85 Add external http server support to ood control -60b04789 Add ioslate path env stub -4b32f2b0 Optimize objectmap path to support non-transactional mode -5a6aa9b7 Integrate isolate path env into global-state services -6ccd4ef9 Add isolate path env impl -c78ae028 Fix app-manager compile error -429bddd8 Cyfs Monitor restore case interval time after success -9dd5aac3 Add noc test cases -c7132f26 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -cbf80ee3 Print warning when decapp missing status or stop scripts -2451a583 Fix: package enter write closed state correctly -0d4443ff Panic manager supports multiple bug reporters -f6749bb1 Stream shutdown success at closed state -f1a4cc60 Create a directory if it does not exist when downloading to a local file -28a37154 Improve cyfs-stack's control strategy for task manager resume_task -a63d6854 Fix: fix reset key logic -b7a3e3c9 Add dingtalk_bug_report method to PanicBuilder for external use -445fc501 Optimize some logs output -cc70a84b Add init-ood-daemon param to ood-installer -28fbed65 Remove cyfs-bdt's dependence on os-id lib -18d1534d Improve the ndn request logs output -8538be10 Add req_path suport to front o protocol for acl -1a621713 Send start notify when cyfs-monitor started -e8752b2a Improve the problem that the front r protocol cannot correctly handle data req_path for acl -4abdcf6b Use search instead of get for device in context -c8ad90a8 Add target device prompt info to access reject msg for better debug -4cc08abb Improve cyfs stack test cases -9cf2aafe Improve some logs output about chunk cache -b30d8cd6 Fix: chunk list task download split chunks dumplicatedly -c2570da0 Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system -b7ecdbc7 Fix: using channel got reserved correctly -a8a9a3b9 Fix: cyfs-monitor report, use sn-online-test to test sn server status -c3964a38 impl: log udp socket's recv loop thread os id -cb239140 Improve some logs output -67b2aed5 Add seperate sn-online-test program -b6e22b0f Fix: cyfs stack resp interest with NotFound if chunk not exists on default -e1bbe10d Fix: Add some log for dectecting zero speed source -d3535025 Fix: modify resend piece control send time -04629f0f Fix: channel ignore estimate request for sequence lost -11bfb5a5 Correct the use of sync mechanism on bdt download context -d2d9ff8f Bdt acl callback can correctly handle empty referer now -a2ebb0df Changed to auto cancel strategy for ndn task with context param -d653c967 Fix the bug that the device_list param of trans.create_task cannot correctly find the device object -a2cb418a Remove useless ood_resolver field from ndn service relate codes -236abdbb Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main -cb0cba8a Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main -dce764a9 Add object and name for meta in cyfs-stack -e0dac397 Fix: tcp stream don't reset tunnel when break -5af0b5fb Fix: implement stream reserving 2*msl state with lru cache -3da42793 Fix cyfs-perf deps Improve the format of some tomls -9867ad29 Add noc meta cache to optimize update last access write operation -e11ff3ef Publish cyfs-core new version -95a5c99d Bump cyfs-core version -c168c17a Fix cyfs-core deps -427050c6 Fix compile error -2412d747 Integrate ood-daemon services status -aa5ff976 Publish new cargo packages -0249ba77 Bump cargo package version and dependences -96e3bb69 Merge branch 'main' into beta -0493c935 Improve ServiceState fields spelling -5a88c564 Add service status related def -00bf2764 ood-daemon adds independent status http server -c013612e Fix: bdt mem device cache limited size -39de9529 Refactory: export private methods with pub(crate) -7785029d Fix: package enter write closed state correctly -101db063 Stream shutdown success at closed state -3fca43d8 Create a directory if it does not exist when downloading to a local file -ac0e4f2a Improve cyfs-stack's control strategy for task manager resume_task -4d8bfacc Fix: fix reset key logic -96e1c1e6 Panic manager supports multiple bug reporters -8d9b7929 Add dingtalk_bug_report method to PanicBuilder for external use -7825a4ea Optimize some logs output -fa6867c6 Add init-ood-daemon param to ood-installer -9aa4489c Remove cyfs-bdt's dependence on os-id lib -66b856fc Improve the ndn request logs output -c0622388 Add req_path suport to front o protocol for acl -cc24f8e0 Send start notify when cyfs-monitor started -10ace371 Improve the problem that the front r protocol cannot correctly handle data req_path for acl -6c59337d Use search instead of get for device in context -ef0f880d Add target device prompt info to access reject msg for better debug -beb0e7be Add service status support to ood-daemon -edc1d1f6 Add external http server support to ood control -e5e9a3a5 Refactory: stream release tunnel guard when closed -009c3c8a Refactory: export private methods with pub(crate) -8e21764a Refactory: export private methods with pub(crate) -743c2fcf Impl: recycle unused tunnel -b4eb9f85 Add isolate_path_env stub test cases -b0c6fd63 Add native ioslate_path_env component test cases and fix some test warnings -3f14f978 Impl: add a test for sn ipv6 ping -ff916188 Add ioslate path env stub -dd437a1f Impl: sn support ipv6 ping -b69709df Optimize objectmap path to support non-transactional mode -0de3fc0c Integrate isolate path env into global-state services -edacc65a Add isolate path env impl -29fed496 Remove complie warning -f3f66501 Impl: Add transfered and recursion close method to ndn task -027e9ae4 Impl: Add transfered and recursion close method to ndn task -6a1f7ed1 Rebase: rebase to 74-integrate-bdt-task-context-and-group -aa682520 Refactory: impl trans api for close upload group -260cbdf8 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -c2bd5612 Refactory: impl trans api for close upload group -99bbebfc Refactory: impl trans api for upload group -c19064b5 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -2f47bcc0 Fix: reserve or recycle channels when all reference released -ae3f02eb Impl: cancel task with user defined error -82692c64 Fix: download task progress/speed -bc3ba88e Rebase: rebase to 74-integrate-bdt-task-context-and-group -58d6d195 Refactory: impl trans api for close upload group -5dad1539 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -30aa07ae Fix: reserve or recycle channels when all reference released -acaa42fb Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -09076f70 Add uptime and boot_time into get_system_info -2b81e62a Fix: correctly wait dapp process -3bbbcfc3 Add total trans bytes field in get_system_info Added network card deduplication in some environments -80fa0863 Publish new cargo packages -ae40d694 Fix cyfs-util publish error -ee957a29 Bump cargo packages version -89341b52 Fix: retry sn list when offline -1370e83c Improve ndn test case with get_data -3584395e Improve the resp's return logic of get_data with error prompt -a3a5172e Use of http requestor for get_data and put_data methods as default -0347e50e Error of reading resp is returned correctly in ws mode -87d26ad6 Merge remote-tracking branch 'origin/main' into main -0df70f89 Sync projects for trans and stack object relate apis's changes -2ef0d178 Fix a compile error with requestor config and some warnings -4b716f44 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main -1a15a767 Fix: trigger chunk downloader's on_drain method -e9faea63 Add some logs -a8dedd60 Add serialization support for storage base on global state -6effd696 Add log for named-data-client chunk reading -9edf7c31 Merge branch '74-integrate-bdt-task-context-and-group' -3fcdbf0c Improve ood-daemon's upgrade detection and restart logic -e0323ea1 Add host mode support to browser sanbox -91e519ec Also check app exclude list when install or start app -66acc69e Merge pull request #88 from buckyos/fix-container-dns -f1a63712 Ood-installer support only start ood-daemon -6514acec Fix AppManager startup param -ee80ce8c Fix AppManager config path, load config after log init -cb2ac1ee Mixed the usage of different requestor config for zone simulator stacks -be10f64b Add shared stack cache logic to zone simulator -5da765af Remove shared stack support and cache from cyfs-stack-loader -c2708f59 Improve open shared stack relate logic and add requestor config params -6150617a Temporarily disable all ipv6 addresses for bdt stack -95654ae5 App Manager AppSource logic -e849439c AppManager supports more detailed configuration -715e851e WIP: add new config for app manager -2ded38db Modify the way to start file uploader -0a50ed5f Improve the update state relate logic for service in ood-daemon service -c7de6539 Fix: avoid duplicate hole punching process when retry sn call -e828e7b5 Merge remote-tracking branch 'origin/fix-container-dns' -f8f4381b Add --startup-mode for ood-daemon startup script -c7bf12f2 Add startup-mode to ood-daemon service with network verify on system startup -b9aca01d Add active check in daemon update and state check loop -dc6aa3d9 Add timeout for repo in ood-daemon service -20ec54d1 Start the monitor service synchronously on startup -2e66ff4a Add service_list cache mechanism for meta config repo -d758151b Remove the local status of meta config repo in ood-daemon service -f99caadc Fix: retry sn list when builder not establish in time -b143379f Integrate surf requestor into shared stack -7eed812f App-tool and app-tool-ex return error correctly -09f79e9a Remove redundant service requestors constructor -cd8588de Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main -f5873108 Add surf based requestor -889d7f81 Adjust the file directory structure of requestsors in cyfs-lib -e7e9781e Fix some compile errors and warnings -3aa50d32 Remove the useless base project -4de7e33d Add app-manager.toml config file support to ood-installer tool -9317c01d Remove the useless old configuration of acl.toml -5af28985 Improve the error status of build relate tasks -a762fecf Merge branch 'fix-container-dns' into beta -b3231559 Fix compile -832e7a20 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead -b2471088 Fix container dns, when resolv contain 127.0.0.53 -bde55b1a Merge branch 'main' into beta -4dd330fe Merge branch 'main' into beta -35cabb3f Merge branch 'main' into beta -bd9326c9 File upload tool only support windows & mac for now. -01a46434 Open upload tool with "open" cmd on Mac -b45d377f Fix:ping client doesn't update local device -b36e728e Fix:ping client doesn't update local device -d9bd6698 Remove handler and event manager's none mode -980b5392 Add some field compatibility with the old version's data on new db format -6541571a Fix: pannic on time escape of call session -c0ceda78 Improve ws session and manager stop-related timing logic -f30cc9c8 Fix: some warning with while let -473e56d6 Add delayed start mechanism for router handler and events -74e30500 Fix: downloading speed/progress for chunk_list/file task use percent -172c5c9e Add shared stack stop test case -d670b458 Improve ws and event manager stop strategy -5841a4fb Improve ws session and ws client stop strategy -b62c204a Refactor ws session related logic and improve packet parser logic -706f06e6 Add stop method to shared stack with requestors -b45ddcf1 Enable none mode for handler and event system in shared stack -a1d67489 Optimize the use of requestor by the service component and adopt the shared mode -6acc40fa Remove http handler support for shared stack -5c3abc42 Add stop method to handler and event manager -b24935d7 Add stop method for ws client -6f55517f Publish new cargo packages -8c933ffc Fix cyfs-util publish error -bf75d29e Bump cargo packages version -bce2a745 Merge branch 'main' into beta -acbd636a Refactory: Add track chunk method option to publish dir/file methods -a022c2cc Fix the bug that search context will enter an infinite loop -a8a57c27 Improve the result of router get_object with flash flags is true -9f3d4e8d Fix the bug for decode context path param without fix -4236102e Add router support for group relate methods Add target check for publish_file method -3d758fcd Merge branch 'main' into beta -0843bbba Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead (#87) -387362a2 Rebase: rebase to 74-integrate-bdt-task-context-and-group -8bdf227b Refactory: impl trans api for close upload group -18ed9311 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -3f52efd9 Impl: cancel task with user defined error -9627d57a Fix: download task progress/speed -e0292e40 Fix: download task progress/speed -addd1976 Refactory: impl trans api for close upload group -dcb4395e Refactory: impl trans api for upload group -db6750fd Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -9f10434a Fix: reserve or recycle channels when all reference released -3ffb8c7e Refactor the file task and chunk task and use a consistent impls at the lower layer -603b5377 Impl: cancel task with user defined error -e66ab510 Fix: download task progress/speed -538a7111 Rebase: rebase to 74-integrate-bdt-task-context-and-group -f720dac7 Refactory: impl trans api for close upload group -a3d86db0 Refactory: impl trans api for upload group -31a93c96 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -f2287d89 Fix query_tasks error and add some logs for task -8ed9f7f2 Sync context manager modifications with bdt -7d6ceaa8 Refactor the context state session manager with source and chunk as unique index -50fb0345 Refactor the download task to better support state switching and task release -a9fe0654 Fix the read logic error for SharedMemChunk -2f89e98d Refactory: change context update_at to async function -f9bbc140 Refactory: chunk downloader triggers context's on_drain when all existing sources tried -4643e4d5 Refactory: add update at property for download context -da234ea1 Fix: reserve or recycle channels when all reference released -a63f74ea Router handler support empty string as filter and will treat as none -5475581f Improve the local file & chunk writers logs -3758c0a0 Refactor the file task and chunk task and use a consistent impls at the lower layer -680f18e2 Add chunk type support for verify_file_task -f237b25b Add state manager with context for ndn task to cancel task on source error -d46a8abb Refactory: add method on_drain for download context -b88929fd Impl: cancel task with user defined error -81c297f0 Sync test cases with interface modification -9ead4762 Add access support for build_dir_from_object_map source object's access -078811fa Add get_object_map_ex with access field return for object_map relate cache -2e1d1924 Add access param support for publish_file and build_file relate methods -eb62b863 Add access support to put_object_map relate methods -dd1caba5 Add some logs for task manager -2b843a47 Fix: download task progress/speed -db13d228 Improve some logs output -f00b77c2 Add from_str support for access string -7c92e607 Add alias for trans output requests -c08c3e36 Improve the log and error codes for local file relate codes -7821234f Use insert_chunk instead of update_chunk_state for chunk state updater -91f0177a Improve insert_chunk logic with update state when already exists for ndc module -ddd8f8e6 Improve some logs output for ndn relate codes -4f637a9d Refactory: interest reponse upload field tokens -1c12c499 Fix: download task finish directly when total length is zero -a43ef9db Fix: download task progress/speed -e94e9560 Fix: download task progress/speed -307c10b5 Refactory: impl trans api for close upload group -a9071c13 Refactory: impl trans api for upload group -763791ba Refactory: upload handler with group_path filter; upload handler response with upload from path -96603e3c Refactory: impl download task progress -191497e7 Fix: finish download leaf task -311aba18 Refactory: upload task group cancel/close -38d8d707 Refactory: Add logic leaf download task -f0141ccc Refactory: chunk downloader send interest with group_path field -6291029a Refactory: chunk downloader not mergable -1684b91f Fix: pannic on udp call -0cf29489 Merge branch 'main' into bdt-beta -5bd73033 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -7805227c Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta -a4dbe34f Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta -8611caff Fix: add log for ping clients -71af78d7 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta -7a1d4b82 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta -5540f89e Fix: the status of udp stream -e5307fac Fix: cc loss bytes in stream write -229dbc6a Add reset_sn_list() function in Stack's ineterface. -b469a288 Upload get-nearest SN Server in client call. The build-tunnel-params's remote-sn is priority over get-nearest sn-list. -a564d9ee Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta - -## [1.0.0.713] -- 2023/2/11 -ab8a2a6c Fix app-manager compile error -cd7eb6b4 Cyfs Monitor restore case interval time after success -7a03fdb3 Add noc test cases -bb596b85 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part -20d14f19 Print warning when decapp missing status or stop scripts - -## [1.0.0.711] -- 2023/2/11 -2c798622 Fix: package enter write closed state correctly -be780df7 Stream shutdown success at closed state -21aef793 Create a directory if it does not exist when downloading to a local file -b6b7e7f8 Improve cyfs-stack's control strategy for task manager resume_task -c0f775cc Fix: fix reset key logic -c90f6ae9 Panic manager supports multiple bug reporters -07f2717d Add dingtalk_bug_report method to PanicBuilder for external use -db4acc4b Optimize some logs output -fb13f654 Add init-ood-daemon param to ood-installer -8f8e88c2 Remove cyfs-bdt's dependence on os-id lib -c05e88b7 Improve the ndn request logs output -7e0c03b0 Add req_path suport to front o protocol for acl -e3d042a0 Send start notify when cyfs-monitor started -2b3a433e Improve the problem that the front r protocol cannot correctly handle data req_path for acl -11e6ed60 Use search instead of get for device in context -06498f24 Add target device prompt info to access reject msg for better debug -7c753b20 Improve cyfs stack test cases -851f1a04 Improve some logs output about chunk cache -7cce9079 Fix: chunk list task download split chunks dumplicatedly - -## [1.0.0.709] -- 2023/2/7 -3005944e Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system -0a004af9 Fix: using channel got reserved correctly -1bfe7b55 Fix: cyfs-monitor report, use sn-online-test to test sn server status -8aa6a426 impl: log udp socket's recv loop thread os id -a1d30562 Improve some logs output -4bf5e29c Add seperate sn-online-test program -82e71892 Fix: cyfs stack resp interest with NotFound if chunk not exists on default -7af6ce69 Fix: Add some log for dectecting zero speed source -d593800f Fix: modify resend piece control send time -b5c41727 Fix: channel ignore estimate request for sequence lost -21a3cb11 Correct the use of sync mechanism on bdt download context -42b7029e Bdt acl callback can correctly handle empty referer now -52709bc8 Changed to auto cancel strategy for ndn task with context param -acde7c48 Remove complie warning -6834b67a Fix the bug that the device_list param of trans.create_task cannot correctly find the device object -4c3370f4 Remove useless ood_resolver field from ndn service relate codes - -## [1.0.0.708] -- 2023/2/6 -4e1122df Fix: the status of udp stream -58c545d7 Improve the handling of non.get_object when the target object cannot be found in (dir or objectmap) + inner_path mode -78904db7 Switch cyfs-ndc and cyfs-tracker-cache db to use SqliteConnectionHolder -932f1c61 Add SqliteConnectionHolder for general db connection management Switch cyfs-noc db to use SqliteConnectionHolder -5f1db008 impl: add a download context strategy to cancel source when zero speed -044bc59c Fix: ndn timer triggered correctly -d6bccc0f The read and write mode of Meta db is separated to support read-only in special cases such as disk is full etc - -## [1.0.0.707] -- 2023/2/3 -0ac77054 Fix the coding stability problem of Dir about HashMap -85cdd9cb Change some Mutex to cyfs-debug's checked Mutex in ood-daemon -5a448ccd Fix the deadlock bug that may be caused by service state detection -24177f29 Add test cases for config repo in ood-daemon project -8c7465ea Fix the coding stability problem of AppList and AppLocalStatus about HashMap -47d820ae Add sort by name strategy for device-config.toml -df39550f Fix the init error of trans store when the db dir is missing -bad1a48d Add inner path support for SingleOpEnvStub -cec8822c Add inner_path support for single_op_env.load method -26c68baa Fix some warning and add some comments -dc3b6e74 Update cyfs-bdt-ext deps -e977dcc9 Move LocalDeviceManager from cyfs-stack-loader to cyfs-util Remove the dependency on cyfs-stack-loader of ood-daemon and ood-installer -b09291cb Add stop_all support to stop all the services for ood-daemon -e031b4b5 Remove useless codes in cyfs-stack project -efb2431c Merge remote-tracking branch 'origin/92-more-convenient-and-suitable-to-use-cyfs-bdt' into main -170eedcf Move group and data relate codes to cyfs-bdt-ext project -259c46c4 Switched cyfs-stack to rely on cyfs-bdt-ext -965803d5 Move relate components to cyfs-bdt-ext project -00f5b35b Add cyfs-bdt-ext project -50036402 Add uptime and boot_time into get_system_info -a166c72d Fix: correctly wait dapp process -20ddf1d0 Add total trans bytes field in get_system_info Added network card deduplication in some environments -ec08c584 Publish new cargo packages -b6db6f9b Fix cyfs-util publish error -cd204231 Bump cargo packages version -cd120a75 Fix: retry sn list when offline -338c31b8 Improve ndn test case with get_data -9ee1a6d4 Improve the resp's return logic of get_data with error prompt -87b0693e Use of http requestor for get_data and put_data methods as default -6f4d47a0 Error of reading resp is returned correctly in ws mode -114c040a Merge remote-tracking branch 'origin/main' into main -a5c5da0e Sync projects for trans and stack object relate apis's changes -b51738f3 Fix a compile error with requestor config and some warnings -d7950257 Fix: trigger chunk downloader's on_drain method -95abf250 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main -fd22bdec Add some logs -4a459fd3 Add serialization support for storage base on global state -068cde9a Add log for named-data-client chunk reading -cd0f3c5f Fix a compile error -ab7cf9e1 Merge branch '74-integrate-bdt-task-context-and-group' -63a37de6 Improve ood-daemon's upgrade detection and restart logic -6850633e Add host mode support to browser sanbox -d4d2639d Improve the error status of build relate tasks -7aa93795 Fix the bug that search context will enter an infinite loop -3ff1412f Improve the result of router get_object with flash flags is true -1ff3ff2e Fix the bug for decode context path param without fix -6bd563c9 Integrate surf requestor into shared stack -dc6d5ebb Remove redundant service requestors constructor -066ebd0e Add surf based requestor -066fe787 Also check app exclude list when install or start app -32b62e13 Adjust the file directory structure of requestsors in cyfs-lib -4ed6ddd2 Merge pull request #88 from buckyos/fix-container-dns -7404ab2e Merge branch 'fix-container-dns' into beta -93c35af4 Add router support for group relate methods Add target check for publish_file method -647b53ba Fix query_tasks error and add some logs for task -37c9bd9c Sync context manager modifications with bdt -78dd780c Refactor the context state session manager with source and chunk as unique index -f05bcd8b Refactor the download task to better support state switching and task release -c028b5bc Fix the read logic error for SharedMemChunk -f50bf84b Refactory: change context update_at to async function -7a2582f6 Refactory: chunk downloader triggers context's on_drain when all existing sources tried -475de4ad Refactory: add update at property for download context -d0200673 Fix: reserve or recycle channels when all reference released -eda71af7 Ood-installer support only start ood-daemon -a491c000 Fix AppManager startup param -d2fa72e0 Fix AppManager config path, load config after log init -409c38f9 Router handler support empty string as filter and will treat as none -51d8dc8f Mixed the usage of different requestor config for zone simulator stacks -70e1e833 Add shared stack cache logic to zone simulator -37cae961 Remove shared stack support and cache from cyfs-stack-loader -eb77a092 Improve open shared stack relate logic and add requestor config params -00b8cf65 Improve the local file & chunk writers logs -e0f14387 Refactor the file task and chunk task and use a consistent impls at the lower layer -e138e06c Add chunk type support for verify_file_task -3fb583e0 Add state manager with context for ndn task to cancel task on source error -200c8922 Refactory: add method on_drain for download context -72e2bb30 Impl: cancel task with user defined error -a0413319 Sync test cases with interface modification -473334df Add access support for build_dir_from_object_map source object's access -973718a1 Add get_object_map_ex with access field return for object_map relate cache -4a547ca3 Add access param support for publish_file and build_file relate methods -78d8f93e Add access support to put_object_map relate methods -750e65d5 Add some logs for task manager -58d90843 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead -b398e932 Fix: download task finish directly when total length is zero -2b415e37 Fix: download task progress/speed -54965e6c Improve some logs output -f62cb4df Refactory: impl download task progress -bbec1935 Fix: finish download leaf task -fd230411 Refactory: upload task group cancel/close -4c2f95b4 Refactory: Add logic leaf download task -eab160ec Refactory: chunk downloader send interest with group_path field -50db1d5c Refactory: chunk downloader not mergable -062bf19e Add from_str support for access string -2243fa7b Add alias for trans output requests -ebb67790 Improve the log and error codes for local file relate codes -ff7dd4c1 Use insert_chunk instead of update_chunk_state for chunk state updater -0525944c Improve insert_chunk logic with update state when already exists for ndc module -fc2d8b18 Improve some logs output for ndn relate codes -128a7cc5 Fix: some warning with while let -f1890ba3 Add chunk exists check for ndn get_data cache mechanism -18c94cf2 Improve some error process in std::io poll relate methods -06f03a6a Improve the conversion between BuckyError and std::io::Error -e801b468 Improve put_chunk for local chunk cache -23a61570 Add cache mechanism to ndn get_data -9055ec35 Refactory: add group_path field to interest packet -1093046b Add range support for ndn get_data with chunk -e3797e31 Add group test case -5061b962 Refactory: poll split read -e700a047 Use {dec_id}/ as default group when no group param is specified -14339d1a Remove dec_id field of context object Add global context support for context -6922dfa0 Put_context is adjusted to depend on context manager Add access field for put_context request -968e5e6d Fix context path fix error & add test case -b70f7990 Fix error when context manager parse context string with object_id -de18c885 Add ndn context test cases Fix compile errors of trans relate methods -8687e171 Fix ndn referer param encode error -be8f06b3 Add debug output for changed of context -abcc02d8 Remove context_id field for query tasks request -21421faf Fix: build error for cyfs-stack -4f62dbad Fix: build error for cyfs-stack -6d6ccad3 Improve resp process for trans & sync api methods -3eb6ca28 Refactor put_context and get_context methods for trans -5ad7e7f1 Improve the clone_from_slice method for ObjectId -9ece347b Refactor context support for trans -7340db07 Refactor ndn api target related codes to support context -458ad1f6 Refactor context to support target mode -9ea97744 Add context field for ndn get_data request -4a0aa1b6 Adapt to bdt new context relate params and types -b51eed19 Add cache and path search category to context manager -f0427489 Add dec_id field for context object, and add strict limit to context_path field -3441fdb0 Refactory: rename ChunkEncodeDesc => ChunkCodecDesc; declare context.source_of as async function; -04db0d46 Add context holder generator for context manager -6081a426 Add context manager and holder core impls -23eb4af0 Refactor the TransContext core object -73d7dcb1 Add dec limit for trans task group relate methods -abda8cfc Improve the param of TransOutputProcessor methods -a3678c4e Improve the trans.query_tasks request path -0fb35dbb Add task group relate methods for trans api -c78b3568 Add a common impl of serde code for JsonCodec -70366e60 Refactor get_task_state method's response to add group support -2d335eff Add group field for DownloadTaskState -ba606857 Add task group for ndn get_data resp -bbb16276 Improve the url query parse for referer and group params -5fae309c Add task group support for NDN/Trans modules -71414249 Rename the task range reader -a5107424 Optimize the ChunkWriter write method -b5ba81fb DirLoader switch to reply on chunk_store_reader instead of local_data_manager -89df6fcc NDN local_data_manager's get relate impls switch to reply on target_data_manager instead -bdfabe75 Fix: split read test -12610350 Fix: cyfs stack ndn event apply to new bdt ndn interface -816e7f6b Refactor the param model of ndc/tracker/chunk_manager -a397bd52 Adapt to bdt's new download stream model -2d5eb444 Impl: split read for download task reader -6cd9410e Impl: Add Single source context -95c8554a Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group -5a1f23af Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group -6111f439 Fix: Release chunk cache and downloader with weak reference -ffc56abe Refactory:create seperate downloader when context is not mergable -1ff8388e Refactory: add loading state to chunk cache -8e3590a2 Refactory: split chunk downloader from chunk cache -f2a3672f Fix: call cc on_loss with error loss count value -1dd8bae3 Fix: Donwload task path logic -4f3a92c4 Fix: return download task speed -371792c0 Fix: use BuckyError instead of BuckyErrorCode in some state -167664c9 Fix: add chunk_list_writer method to TrackedChunkStore -b4a67578 Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta -2e42dae0 Fix: stream chunk encoder always read cache with sync reader -bb954d5f Impl: Unit test for upload from path -8b7aa861 Refactory: Add start_upload_from_cache method -81014478 Refactory: Move ndn default event handler to utils -def00192 Refactory: remove default ndc/tracker from bdt stack -67f29271 Refactory: Taskgroup makesure path -896b39ba Impl: File raw cache for chunk -bc043adc In SN statistic, add endpoint's statistic. -ecb58708 Call sn support MTU_LARGE -2cf4567b Add Mutlity SN。 -2321e02c Fix: tcp tunnel send piece buffer with mtu -2ac27f33 Refactory: add DownloadContext trait -6832e73e Refactory: add DownloadContext trait -330a8940 Support large mtu and question&answer -e03962a7 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -d1cc885e Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -06d89662 Fix: chunk list task reader -f4d20813 Fix: close/finish download task group -5bd2ec64 Fix: task.reader return unexpected not found error -7d2e6f6f Fix:panic on download reader -de837c47 Refactory: write chunk from task.reader -677e444b Refactory: Reader of download task -c0a479e3 Refactory: Upload session wait establish -22e9cc0f Refactory: download/upload differs in tcp/udp tunnel -638a8fc4 Refactory: download/upload differs in tcp/udp tunnel -23251581 Fix: bind tunnel with upload/download session -70292ce4 Fix: cache packages in tunnel.build_send, send them when tunnel actived -197e241a Merge branch 'ndn-cache' into bdt-beta -51d5b714 Merge branch 'ndn-cache' into bdt-beta -ea1dae46 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -16d25537 Merge branch 'ndn-cache' into bdt-beta -c6bf684a log decrypt aeskey error info -79bceeea Fix: chunk list task reader -bc380433 Fix: close/finish download task group -61714a7b Fix: task.reader return unexpected not found error -97c955d7 Fix:panic on download reader -1e95e4da Refactory: write chunk from task.reader -9ad964fb Refactory: Reader of download task -d8bf33a0 Refactory: Upload session wait establish -06f3affc Refactory: download/upload differs in tcp/udp tunnel -2ef44f99 Refactory: download/upload differs in tcp/udp tunnel -8519534c Fix: bind tunnel with upload/download session -b2925e95 Fix: cache packages in tunnel.build_send, send them when tunnel actived -7235f3dc Merge branch 'ndn-cache' into bdt-beta -04e2a5a0 Merge branch 'ndn-cache' into bdt-beta -eaa0b650 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta -3d711110 Merge branch 'ndn-cache' into bdt-beta -8c8b6039 log decrypt aeskey error info -43ccf15c Impl: Cancel download chunk task -6efb6eca Test: download from uploader test ok -439635f5 Merge branch 'ndn-cache' into bdt-beta -0e08b03a Refactory: download/upload session support reverse step stream -96ffaef7 Refactory: impl download/upload session with new cache -292cf4ae Refactory: impl download/upload session with new cache -d38e31ba Refactory: impl download/upload session with new cache -07b40c65 Refactory: impl download/upload session with new cache -d525a649 Refactory: implement memory raw cache -e07a4b0e Refactory: chunk downloader with stream cache - -## [1.0.0.703] -- 2023/1/13 -cfd654ac Temporarily disable all ipv6 addresses for bdt stack - -## [1.0.0.702] -- 2023/1/12 -bb72348e App Manager AppSource logic -413edbad AppManager supports more detailed configuration -7b0704ec WIP: add new config for app manager -2eb6dce1 Modify the way to start file uploader -6076a69f Improve the update state relate logic for service in ood-daemon service -44fbe781 Fix: avoid duplicate hole punching process when retry sn call -ea48e120 Merge remote-tracking branch 'origin/fix-container-dns' -56f22e21 Add --startup-mode for ood-daemon startup script -cf1f363c Add startup-mode to ood-daemon service with network verify on system startup -56b755e6 Add active check in daemon update and state check loop -b7943988 Fix compile -2b355960 Fix container dns, when resolv contain 127.0.0.53 -d6b5bb06 Add timeout for repo in ood-daemon service -628649f0 Start the monitor service synchronously on startup -de1e9960 Add service_list cache mechanism for meta config repo -a84bfafe Remove the local status of meta config repo in ood-daemon service -a807f171 Fix: retry sn list when builder not establish in time -5639e004 App-tool and app-tool-ex return error correctly -26b234cb Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main -f136c262 Fix some compile errors and warnings -a4ece723 Remove the useless base project -2d216910 Add app-manager.toml config file support to ood-installer tool -e111f3b2 Remove the useless old configuration of acl.toml -eae9d604 Merge branch 'main' into beta -d5463188 Merge branch 'main' into beta -b34744c3 Merge branch 'main' into beta -180ae196 Remove handler and event manager's none mode -d10953b2 Improve ws session and manager stop-related timing logic -8b84ef3f Add delayed start mechanism for router handler and events -c13cc029 Add shared stack stop test case -faf04a09 Improve ws and event manager stop strategy -c5d02ab9 Improve ws session and ws client stop strategy -007247e2 Refactor ws session related logic and improve packet parser logic -b0463c83 Add stop method to shared stack with requestors -1b80f43a Enable none mode for handler and event system in shared stack -8ec0888b Optimize the use of requestor by the service component and adopt the shared mode -d9d69051 Remove http handler support for shared stack -bb0e005e Add stop method to handler and event manager -1a2ada09 Add stop method for ws client -77ea26c6 Fix: cyfs-client correct get sn list from local stack -e29cd15c Merge branch 'main' into beta -0bb5dcd7 Sync service list method use the lock for services in ood-daemon -19b338e6 Improve some logs output -7e8cb267 Improve cmd status check return value and compare mechanism -fc800657 Improve the agent check for the browser disable mode -67a2179e NamedDataClient use init config, use GetData instead of GetDataWithMeta -e160a62a Improve the get_data logic of chunk_manager -9f7263bc Add memory cache for chunk_manager get_data_with_meta Improve the get_chunk_data resp body mechanism and remove the chunk_id verify temporarily -270778a9 Fix: stream pool use sn list in device cache -b1abf319 Fix: ignore sn list in build param's remote desc -ff05f5ff Fix: beta use correct built-in sn list -02fe10ef Fix: Add logs for build params info -26989db3 Merge branch 'main' into beta -440b90f9 Merge branch 'main' into beta -c377c61f Merge branch 'main' into beta -b0fe871d Merge branch 'main' into beta -ef8a124a Merge branch 'main' into beta -71e9e52b Merge branch 'main' into beta -2fa6be68 Fix: disable cyfs_debug::mutex check in some fraquently called functions +## [1.0.0.718] -- 2023/2/21 +1b0cf118 Change sync services packages from parallel to serial +638848a2 Remove two spawn task using for cancel on timeout +70837da7 Fix error op_env type check in requestor +e3f55f6e Improve timeout and retry strategy for repo download in ood-daemon service +9c3c63ab Meta db initialization switch to transaction mode +1e4e4277 Modify: add some statistic logs for ndn +94d8f7a4 Merge branch '104-appmanager-suppport-local-app-repo-store' +34580770 Modify: add some statistic logs for ndn +7522c0fe Email Sender support starttls +10d27023 App Manager support install app from local repo +2a3c1dc1 ood-installer support sync app repo +51f0be28 WIP: App Manager Support Local Repo +e6392f5b WIP: App Manager reflator app install logic +e65fe061 WIP: AppManager add repo type, use zip_extract to extract app service package + +## [1.0.0.715] -- 2023/2/20 +e51af4f2 Set docker api timeout to 300s +b213c3fe Fix: tcp not update active time when recv packet +24553a9c Improve the object layer strategy detection of after pass the first layer rpath access verification +574cfddf OOD-daemon will now report an error and exit if it fails to load the repo +0ab51327 Add version output in process alive check log +14c004b6 Fix meta-stat email format +4daab080 App-manager report app status to ood-daemon +c09ddea9 Fix field names of ood status +f3449363 Fix: monitor create desc when desc not existed on chain +a4e0e755 Fix: stream break when loss fin ack packet +0d2393f3 Fix: monitor create desc error +ba302dd4 Merge remote-tracking branch 'origin/107-support-multiple-global-states-in-cyfs-stack' into main +3d70797d Add group state test case +63e3e712 Fix a assert error when global state is init +61a5eff1 Cyfs monitor use generated identify to test metachain read and write +3d4aefc9 Improve the use of u64::MAX in two places +ee5323ea Delete some useless logs +90d9b5c8 meta spv support storage anbd query objects by object id, body hash +1101829c Add isolate_id method for GlobalStateRawProcessor +e3765b61 Add global state raw processor for use by external components of cyfs-stack +ff03c824 Add the persistence mechanism of all the global state list +b4c4de04 Refactor GlobalStateManager to support multiple global-states +937c7dbe Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +b4284830 Add exists methods into collection for to check if exists +5bcc2984 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +da09ed21 Merge branch '79-cyfs-stack-should-support-interfaces-for-ndn-upload-task' +412d03ff Merge branch '99-recycle-unused-bdt-tunnel-instances' +979773da Fix: implement stream reserving 2*msl state with lru cache +25c53b07 Refactory: export private methods with pub(crate) +114f1d1b Fix: bdt unit test sn with ipv6 endpoints +fdde1948 Merge branch '95-ipv6-support-refactory' +1b91764a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8d522ec7 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +1875de3d Add object and name for meta in cyfs-stack +3e12b1be Fix cyfs-perf deps Improve the format of some tomls +e83890fc Add noc meta cache to optimize update last access write operation +2ff85f4d Publish cyfs-core new version +d917d648 Bump cyfs-core version +0dd49104 Fix cyfs-core deps +220c7ab2 Fix compile error +dd2f2f17 Publish new cargo packages +fb63c476 Bump cargo package version and dependences +89917227 Merge branch 'main' into beta +75aea584 Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +8f60a00b Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +2ebd1e20 Add object and name for meta in cyfs-stack +4d5a9e90 Fix cyfs-perf deps Improve the format of some tomls +2121a11e Add noc meta cache to optimize update last access write operation +078b27d3 Publish cyfs-core new version +019b09d9 Bump cyfs-core version +51e4365b Fix cyfs-core deps +a04d6e88 Fix compile error +038b75b4 Publish new cargo packages +279ce4bd Bump cargo package version and dependences +026c1383 Merge branch 'main' into beta +ccb044db Integrate ood-daemon services status +4af47a92 Improve ServiceState fields spelling +f9eaed01 Add service status related def +ec1ba569 ood-daemon adds independent status http server +5bc02595 Add service status support to ood-daemon +ff14b0d1 Add external http server support to ood control +287c9468 Fix app-manager compile error +08249fa5 Cyfs Monitor restore case interval time after success +c6c372dc Add noc test cases +b176d6a5 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +97bd7bb9 Print warning when decapp missing status or stop scripts +9f85c599 Stream shutdown success at closed state +71ffede0 Fix: fix reset key logic +ec2194ec Integrate ood-daemon services status +2b30769b Improve ServiceState fields spelling +eb881d46 Add service status related def +5dc9c661 ood-daemon adds independent status http server +b2882ff5 Add service status support to ood-daemon +cfc87989 Add external http server support to ood control +d54866c2 Fix app-manager compile error +f0822e79 Cyfs Monitor restore case interval time after success +ab37ea21 Add noc test cases +fa1cc5c0 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +13cdfe46 Print warning when decapp missing status or stop scripts +5ad5d183 Fix: bdt unit test sn with ipv6 endpoints +9607470d Merge branch '95-ipv6-support-refactory' +a8ba267a Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +5c2a8d77 Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +c88a5e76 Add object and name for meta in cyfs-stack +598df4a8 Fix cyfs-perf deps Improve the format of some tomls +1952c7ee Add noc meta cache to optimize update last access write operation +ba181cef Publish cyfs-core new version +139a9ab6 Bump cyfs-core version +11c7205a Fix cyfs-core deps +76f871ea Fix compile error +30f99d3d Publish new cargo packages +4228e263 Bump cargo package version and dependences +34cb38f4 Merge branch 'main' into beta +87956987 Integrate ood-daemon services status +086dcd8a Improve ServiceState fields spelling +51f135c6 Add service status related def +0bd37768 ood-daemon adds independent status http server +933ed8cd Add isolate_path_env stub test cases +1be055d0 Add service status support to ood-daemon +d3e16c4d Add native ioslate_path_env component test cases and fix some test warnings +25fa3e85 Add external http server support to ood control +60b04789 Add ioslate path env stub +4b32f2b0 Optimize objectmap path to support non-transactional mode +5a6aa9b7 Integrate isolate path env into global-state services +6ccd4ef9 Add isolate path env impl +c78ae028 Fix app-manager compile error +429bddd8 Cyfs Monitor restore case interval time after success +9dd5aac3 Add noc test cases +c7132f26 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +cbf80ee3 Print warning when decapp missing status or stop scripts +2451a583 Fix: package enter write closed state correctly +0d4443ff Panic manager supports multiple bug reporters +f6749bb1 Stream shutdown success at closed state +f1a4cc60 Create a directory if it does not exist when downloading to a local file +28a37154 Improve cyfs-stack's control strategy for task manager resume_task +a63d6854 Fix: fix reset key logic +b7a3e3c9 Add dingtalk_bug_report method to PanicBuilder for external use +445fc501 Optimize some logs output +cc70a84b Add init-ood-daemon param to ood-installer +28fbed65 Remove cyfs-bdt's dependence on os-id lib +18d1534d Improve the ndn request logs output +8538be10 Add req_path suport to front o protocol for acl +1a621713 Send start notify when cyfs-monitor started +e8752b2a Improve the problem that the front r protocol cannot correctly handle data req_path for acl +4abdcf6b Use search instead of get for device in context +c8ad90a8 Add target device prompt info to access reject msg for better debug +4cc08abb Improve cyfs stack test cases +9cf2aafe Improve some logs output about chunk cache +b30d8cd6 Fix: chunk list task download split chunks dumplicatedly +c2570da0 Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +b7ecdbc7 Fix: using channel got reserved correctly +a8a9a3b9 Fix: cyfs-monitor report, use sn-online-test to test sn server status +c3964a38 impl: log udp socket's recv loop thread os id +cb239140 Improve some logs output +67b2aed5 Add seperate sn-online-test program +b6e22b0f Fix: cyfs stack resp interest with NotFound if chunk not exists on default +e1bbe10d Fix: Add some log for dectecting zero speed source +d3535025 Fix: modify resend piece control send time +04629f0f Fix: channel ignore estimate request for sequence lost +11bfb5a5 Correct the use of sync mechanism on bdt download context +d2d9ff8f Bdt acl callback can correctly handle empty referer now +a2ebb0df Changed to auto cancel strategy for ndn task with context param +d653c967 Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +a2cb418a Remove useless ood_resolver field from ndn service relate codes +236abdbb Merge remote-tracking branch 'origin/101-ood-status-query-an-aggregation-services' into main +cb0cba8a Merge remote-tracking branch 'origin/96-singleopenvstub-support-constructing-directory-tree-structure-and-support-directory-tree-traversal' into main +dce764a9 Add object and name for meta in cyfs-stack +e0dac397 Fix: tcp stream don't reset tunnel when break +5af0b5fb Fix: implement stream reserving 2*msl state with lru cache +3da42793 Fix cyfs-perf deps Improve the format of some tomls +9867ad29 Add noc meta cache to optimize update last access write operation +e11ff3ef Publish cyfs-core new version +95a5c99d Bump cyfs-core version +c168c17a Fix cyfs-core deps +427050c6 Fix compile error +2412d747 Integrate ood-daemon services status +aa5ff976 Publish new cargo packages +0249ba77 Bump cargo package version and dependences +96e3bb69 Merge branch 'main' into beta +0493c935 Improve ServiceState fields spelling +5a88c564 Add service status related def +00bf2764 ood-daemon adds independent status http server +c013612e Fix: bdt mem device cache limited size +39de9529 Refactory: export private methods with pub(crate) +7785029d Fix: package enter write closed state correctly +101db063 Stream shutdown success at closed state +3fca43d8 Create a directory if it does not exist when downloading to a local file +ac0e4f2a Improve cyfs-stack's control strategy for task manager resume_task +4d8bfacc Fix: fix reset key logic +96e1c1e6 Panic manager supports multiple bug reporters +8d9b7929 Add dingtalk_bug_report method to PanicBuilder for external use +7825a4ea Optimize some logs output +fa6867c6 Add init-ood-daemon param to ood-installer +9aa4489c Remove cyfs-bdt's dependence on os-id lib +66b856fc Improve the ndn request logs output +c0622388 Add req_path suport to front o protocol for acl +cc24f8e0 Send start notify when cyfs-monitor started +10ace371 Improve the problem that the front r protocol cannot correctly handle data req_path for acl +6c59337d Use search instead of get for device in context +ef0f880d Add target device prompt info to access reject msg for better debug +beb0e7be Add service status support to ood-daemon +edc1d1f6 Add external http server support to ood control +e5e9a3a5 Refactory: stream release tunnel guard when closed +009c3c8a Refactory: export private methods with pub(crate) +8e21764a Refactory: export private methods with pub(crate) +743c2fcf Impl: recycle unused tunnel +b4eb9f85 Add isolate_path_env stub test cases +b0c6fd63 Add native ioslate_path_env component test cases and fix some test warnings +3f14f978 Impl: add a test for sn ipv6 ping +ff916188 Add ioslate path env stub +dd437a1f Impl: sn support ipv6 ping +b69709df Optimize objectmap path to support non-transactional mode +0de3fc0c Integrate isolate path env into global-state services +edacc65a Add isolate path env impl +29fed496 Remove complie warning +f3f66501 Impl: Add transfered and recursion close method to ndn task +027e9ae4 Impl: Add transfered and recursion close method to ndn task +6a1f7ed1 Rebase: rebase to 74-integrate-bdt-task-context-and-group +aa682520 Refactory: impl trans api for close upload group +260cbdf8 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +c2bd5612 Refactory: impl trans api for close upload group +99bbebfc Refactory: impl trans api for upload group +c19064b5 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +2f47bcc0 Fix: reserve or recycle channels when all reference released +ae3f02eb Impl: cancel task with user defined error +82692c64 Fix: download task progress/speed +bc3ba88e Rebase: rebase to 74-integrate-bdt-task-context-and-group +58d6d195 Refactory: impl trans api for close upload group +5dad1539 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +30aa07ae Fix: reserve or recycle channels when all reference released +acaa42fb Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +09076f70 Add uptime and boot_time into get_system_info +2b81e62a Fix: correctly wait dapp process +3bbbcfc3 Add total trans bytes field in get_system_info Added network card deduplication in some environments +80fa0863 Publish new cargo packages +ae40d694 Fix cyfs-util publish error +ee957a29 Bump cargo packages version +89341b52 Fix: retry sn list when offline +1370e83c Improve ndn test case with get_data +3584395e Improve the resp's return logic of get_data with error prompt +a3a5172e Use of http requestor for get_data and put_data methods as default +0347e50e Error of reading resp is returned correctly in ws mode +87d26ad6 Merge remote-tracking branch 'origin/main' into main +0df70f89 Sync projects for trans and stack object relate apis's changes +2ef0d178 Fix a compile error with requestor config and some warnings +4b716f44 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +1a15a767 Fix: trigger chunk downloader's on_drain method +e9faea63 Add some logs +a8dedd60 Add serialization support for storage base on global state +6effd696 Add log for named-data-client chunk reading +9edf7c31 Merge branch '74-integrate-bdt-task-context-and-group' +3fcdbf0c Improve ood-daemon's upgrade detection and restart logic +e0323ea1 Add host mode support to browser sanbox +91e519ec Also check app exclude list when install or start app +66acc69e Merge pull request #88 from buckyos/fix-container-dns +f1a63712 Ood-installer support only start ood-daemon +6514acec Fix AppManager startup param +ee80ce8c Fix AppManager config path, load config after log init +cb2ac1ee Mixed the usage of different requestor config for zone simulator stacks +be10f64b Add shared stack cache logic to zone simulator +5da765af Remove shared stack support and cache from cyfs-stack-loader +c2708f59 Improve open shared stack relate logic and add requestor config params +6150617a Temporarily disable all ipv6 addresses for bdt stack +95654ae5 App Manager AppSource logic +e849439c AppManager supports more detailed configuration +715e851e WIP: add new config for app manager +2ded38db Modify the way to start file uploader +0a50ed5f Improve the update state relate logic for service in ood-daemon service +c7de6539 Fix: avoid duplicate hole punching process when retry sn call +e828e7b5 Merge remote-tracking branch 'origin/fix-container-dns' +f8f4381b Add --startup-mode for ood-daemon startup script +c7bf12f2 Add startup-mode to ood-daemon service with network verify on system startup +b9aca01d Add active check in daemon update and state check loop +dc6aa3d9 Add timeout for repo in ood-daemon service +20ec54d1 Start the monitor service synchronously on startup +2e66ff4a Add service_list cache mechanism for meta config repo +d758151b Remove the local status of meta config repo in ood-daemon service +f99caadc Fix: retry sn list when builder not establish in time +b143379f Integrate surf requestor into shared stack +7eed812f App-tool and app-tool-ex return error correctly +09f79e9a Remove redundant service requestors constructor +cd8588de Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f5873108 Add surf based requestor +889d7f81 Adjust the file directory structure of requestsors in cyfs-lib +e7e9781e Fix some compile errors and warnings +3aa50d32 Remove the useless base project +4de7e33d Add app-manager.toml config file support to ood-installer tool +9317c01d Remove the useless old configuration of acl.toml +5af28985 Improve the error status of build relate tasks +a762fecf Merge branch 'fix-container-dns' into beta +b3231559 Fix compile +832e7a20 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b2471088 Fix container dns, when resolv contain 127.0.0.53 +bde55b1a Merge branch 'main' into beta +4dd330fe Merge branch 'main' into beta +35cabb3f Merge branch 'main' into beta +bd9326c9 File upload tool only support windows & mac for now. +01a46434 Open upload tool with "open" cmd on Mac +b45d377f Fix:ping client doesn't update local device +b36e728e Fix:ping client doesn't update local device +d9bd6698 Remove handler and event manager's none mode +980b5392 Add some field compatibility with the old version's data on new db format +6541571a Fix: pannic on time escape of call session +c0ceda78 Improve ws session and manager stop-related timing logic +f30cc9c8 Fix: some warning with while let +473e56d6 Add delayed start mechanism for router handler and events +74e30500 Fix: downloading speed/progress for chunk_list/file task use percent +172c5c9e Add shared stack stop test case +d670b458 Improve ws and event manager stop strategy +5841a4fb Improve ws session and ws client stop strategy +b62c204a Refactor ws session related logic and improve packet parser logic +706f06e6 Add stop method to shared stack with requestors +b45ddcf1 Enable none mode for handler and event system in shared stack +a1d67489 Optimize the use of requestor by the service component and adopt the shared mode +6acc40fa Remove http handler support for shared stack +5c3abc42 Add stop method to handler and event manager +b24935d7 Add stop method for ws client +6f55517f Publish new cargo packages +8c933ffc Fix cyfs-util publish error +bf75d29e Bump cargo packages version +bce2a745 Merge branch 'main' into beta +acbd636a Refactory: Add track chunk method option to publish dir/file methods +a022c2cc Fix the bug that search context will enter an infinite loop +a8a57c27 Improve the result of router get_object with flash flags is true +9f3d4e8d Fix the bug for decode context path param without fix +4236102e Add router support for group relate methods Add target check for publish_file method +3d758fcd Merge branch 'main' into beta +0843bbba Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead (#87) +387362a2 Rebase: rebase to 74-integrate-bdt-task-context-and-group +8bdf227b Refactory: impl trans api for close upload group +18ed9311 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +3f52efd9 Impl: cancel task with user defined error +9627d57a Fix: download task progress/speed +e0292e40 Fix: download task progress/speed +addd1976 Refactory: impl trans api for close upload group +dcb4395e Refactory: impl trans api for upload group +db6750fd Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +9f10434a Fix: reserve or recycle channels when all reference released +3ffb8c7e Refactor the file task and chunk task and use a consistent impls at the lower layer +603b5377 Impl: cancel task with user defined error +e66ab510 Fix: download task progress/speed +538a7111 Rebase: rebase to 74-integrate-bdt-task-context-and-group +f720dac7 Refactory: impl trans api for close upload group +a3d86db0 Refactory: impl trans api for upload group +31a93c96 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +f2287d89 Fix query_tasks error and add some logs for task +8ed9f7f2 Sync context manager modifications with bdt +7d6ceaa8 Refactor the context state session manager with source and chunk as unique index +50fb0345 Refactor the download task to better support state switching and task release +a9fe0654 Fix the read logic error for SharedMemChunk +2f89e98d Refactory: change context update_at to async function +f9bbc140 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +4643e4d5 Refactory: add update at property for download context +da234ea1 Fix: reserve or recycle channels when all reference released +a63f74ea Router handler support empty string as filter and will treat as none +5475581f Improve the local file & chunk writers logs +3758c0a0 Refactor the file task and chunk task and use a consistent impls at the lower layer +680f18e2 Add chunk type support for verify_file_task +f237b25b Add state manager with context for ndn task to cancel task on source error +d46a8abb Refactory: add method on_drain for download context +b88929fd Impl: cancel task with user defined error +81c297f0 Sync test cases with interface modification +9ead4762 Add access support for build_dir_from_object_map source object's access +078811fa Add get_object_map_ex with access field return for object_map relate cache +2e1d1924 Add access param support for publish_file and build_file relate methods +eb62b863 Add access support to put_object_map relate methods +dd1caba5 Add some logs for task manager +2b843a47 Fix: download task progress/speed +db13d228 Improve some logs output +f00b77c2 Add from_str support for access string +7c92e607 Add alias for trans output requests +c08c3e36 Improve the log and error codes for local file relate codes +7821234f Use insert_chunk instead of update_chunk_state for chunk state updater +91f0177a Improve insert_chunk logic with update state when already exists for ndc module +ddd8f8e6 Improve some logs output for ndn relate codes +4f637a9d Refactory: interest reponse upload field tokens +1c12c499 Fix: download task finish directly when total length is zero +a43ef9db Fix: download task progress/speed +e94e9560 Fix: download task progress/speed +307c10b5 Refactory: impl trans api for close upload group +a9071c13 Refactory: impl trans api for upload group +763791ba Refactory: upload handler with group_path filter; upload handler response with upload from path +96603e3c Refactory: impl download task progress +191497e7 Fix: finish download leaf task +311aba18 Refactory: upload task group cancel/close +38d8d707 Refactory: Add logic leaf download task +f0141ccc Refactory: chunk downloader send interest with group_path field +6291029a Refactory: chunk downloader not mergable +1684b91f Fix: pannic on udp call +0cf29489 Merge branch 'main' into bdt-beta +5bd73033 Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +7805227c Merge branch '74-integrate-bdt-task-context-and-group' into bdt-beta +a4dbe34f Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +8611caff Fix: add log for ping clients +71af78d7 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +7a1d4b82 Merge branch '56-cyfs-stack-support-no-sn-online' into bdt-beta +5540f89e Fix: the status of udp stream +e5307fac Fix: cc loss bytes in stream write +229dbc6a Add reset_sn_list() function in Stack's ineterface. +b469a288 Upload get-nearest SN Server in client call. The build-tunnel-params's remote-sn is priority over get-nearest sn-list. +a564d9ee Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta + +## [1.0.0.713] -- 2023/2/11 +ab8a2a6c Fix app-manager compile error +cd7eb6b4 Cyfs Monitor restore case interval time after success +7a03fdb3 Add noc test cases +bb596b85 Fix the reserved names as blob and chunk dir names's bug on windows for the missing part +20d14f19 Print warning when decapp missing status or stop scripts + +## [1.0.0.711] -- 2023/2/11 +2c798622 Fix: package enter write closed state correctly +be780df7 Stream shutdown success at closed state +21aef793 Create a directory if it does not exist when downloading to a local file +b6b7e7f8 Improve cyfs-stack's control strategy for task manager resume_task +c0f775cc Fix: fix reset key logic +c90f6ae9 Panic manager supports multiple bug reporters +07f2717d Add dingtalk_bug_report method to PanicBuilder for external use +db4acc4b Optimize some logs output +fb13f654 Add init-ood-daemon param to ood-installer +8f8e88c2 Remove cyfs-bdt's dependence on os-id lib +c05e88b7 Improve the ndn request logs output +7e0c03b0 Add req_path suport to front o protocol for acl +e3d042a0 Send start notify when cyfs-monitor started +2b3a433e Improve the problem that the front r protocol cannot correctly handle data req_path for acl +11e6ed60 Use search instead of get for device in context +06498f24 Add target device prompt info to access reject msg for better debug +7c753b20 Improve cyfs stack test cases +851f1a04 Improve some logs output about chunk cache +7cce9079 Fix: chunk list task download split chunks dumplicatedly + +## [1.0.0.709] -- 2023/2/7 +3005944e Improve the problem that the backslash path in Windows format cannot be correctly recognized when the download task processes the local file path on nix system +0a004af9 Fix: using channel got reserved correctly +1bfe7b55 Fix: cyfs-monitor report, use sn-online-test to test sn server status +8aa6a426 impl: log udp socket's recv loop thread os id +a1d30562 Improve some logs output +4bf5e29c Add seperate sn-online-test program +82e71892 Fix: cyfs stack resp interest with NotFound if chunk not exists on default +7af6ce69 Fix: Add some log for dectecting zero speed source +d593800f Fix: modify resend piece control send time +b5c41727 Fix: channel ignore estimate request for sequence lost +21a3cb11 Correct the use of sync mechanism on bdt download context +42b7029e Bdt acl callback can correctly handle empty referer now +52709bc8 Changed to auto cancel strategy for ndn task with context param +acde7c48 Remove complie warning +6834b67a Fix the bug that the device_list param of trans.create_task cannot correctly find the device object +4c3370f4 Remove useless ood_resolver field from ndn service relate codes + +## [1.0.0.708] -- 2023/2/6 +4e1122df Fix: the status of udp stream +58c545d7 Improve the handling of non.get_object when the target object cannot be found in (dir or objectmap) + inner_path mode +78904db7 Switch cyfs-ndc and cyfs-tracker-cache db to use SqliteConnectionHolder +932f1c61 Add SqliteConnectionHolder for general db connection management Switch cyfs-noc db to use SqliteConnectionHolder +5f1db008 impl: add a download context strategy to cancel source when zero speed +044bc59c Fix: ndn timer triggered correctly +d6bccc0f The read and write mode of Meta db is separated to support read-only in special cases such as disk is full etc + +## [1.0.0.707] -- 2023/2/3 +0ac77054 Fix the coding stability problem of Dir about HashMap +85cdd9cb Change some Mutex to cyfs-debug's checked Mutex in ood-daemon +5a448ccd Fix the deadlock bug that may be caused by service state detection +24177f29 Add test cases for config repo in ood-daemon project +8c7465ea Fix the coding stability problem of AppList and AppLocalStatus about HashMap +47d820ae Add sort by name strategy for device-config.toml +df39550f Fix the init error of trans store when the db dir is missing +bad1a48d Add inner path support for SingleOpEnvStub +cec8822c Add inner_path support for single_op_env.load method +26c68baa Fix some warning and add some comments +dc3b6e74 Update cyfs-bdt-ext deps +e977dcc9 Move LocalDeviceManager from cyfs-stack-loader to cyfs-util Remove the dependency on cyfs-stack-loader of ood-daemon and ood-installer +b09291cb Add stop_all support to stop all the services for ood-daemon +e031b4b5 Remove useless codes in cyfs-stack project +efb2431c Merge remote-tracking branch 'origin/92-more-convenient-and-suitable-to-use-cyfs-bdt' into main +170eedcf Move group and data relate codes to cyfs-bdt-ext project +259c46c4 Switched cyfs-stack to rely on cyfs-bdt-ext +965803d5 Move relate components to cyfs-bdt-ext project +00f5b35b Add cyfs-bdt-ext project +50036402 Add uptime and boot_time into get_system_info +a166c72d Fix: correctly wait dapp process +20ddf1d0 Add total trans bytes field in get_system_info Added network card deduplication in some environments +ec08c584 Publish new cargo packages +b6db6f9b Fix cyfs-util publish error +cd204231 Bump cargo packages version +cd120a75 Fix: retry sn list when offline +338c31b8 Improve ndn test case with get_data +9ee1a6d4 Improve the resp's return logic of get_data with error prompt +87b0693e Use of http requestor for get_data and put_data methods as default +6f4d47a0 Error of reading resp is returned correctly in ws mode +114c040a Merge remote-tracking branch 'origin/main' into main +a5c5da0e Sync projects for trans and stack object relate apis's changes +b51738f3 Fix a compile error with requestor config and some warnings +d7950257 Fix: trigger chunk downloader's on_drain method +95abf250 Merge remote-tracking branch 'origin/80-add-surf-based-http-requestor' into main +fd22bdec Add some logs +4a459fd3 Add serialization support for storage base on global state +068cde9a Add log for named-data-client chunk reading +cd0f3c5f Fix a compile error +ab7cf9e1 Merge branch '74-integrate-bdt-task-context-and-group' +63a37de6 Improve ood-daemon's upgrade detection and restart logic +6850633e Add host mode support to browser sanbox +d4d2639d Improve the error status of build relate tasks +7aa93795 Fix the bug that search context will enter an infinite loop +3ff1412f Improve the result of router get_object with flash flags is true +1ff3ff2e Fix the bug for decode context path param without fix +6bd563c9 Integrate surf requestor into shared stack +dc6d5ebb Remove redundant service requestors constructor +066ebd0e Add surf based requestor +066fe787 Also check app exclude list when install or start app +32b62e13 Adjust the file directory structure of requestsors in cyfs-lib +4ed6ddd2 Merge pull request #88 from buckyos/fix-container-dns +7404ab2e Merge branch 'fix-container-dns' into beta +93c35af4 Add router support for group relate methods Add target check for publish_file method +647b53ba Fix query_tasks error and add some logs for task +37c9bd9c Sync context manager modifications with bdt +78dd780c Refactor the context state session manager with source and chunk as unique index +f05bcd8b Refactor the download task to better support state switching and task release +c028b5bc Fix the read logic error for SharedMemChunk +f50bf84b Refactory: change context update_at to async function +7a2582f6 Refactory: chunk downloader triggers context's on_drain when all existing sources tried +475de4ad Refactory: add update at property for download context +d0200673 Fix: reserve or recycle channels when all reference released +eda71af7 Ood-installer support only start ood-daemon +a491c000 Fix AppManager startup param +d2fa72e0 Fix AppManager config path, load config after log init +409c38f9 Router handler support empty string as filter and will treat as none +51d8dc8f Mixed the usage of different requestor config for zone simulator stacks +70e1e833 Add shared stack cache logic to zone simulator +37cae961 Remove shared stack support and cache from cyfs-stack-loader +eb77a092 Improve open shared stack relate logic and add requestor config params +00b8cf65 Improve the local file & chunk writers logs +e0f14387 Refactor the file task and chunk task and use a consistent impls at the lower layer +e138e06c Add chunk type support for verify_file_task +3fb583e0 Add state manager with context for ndn task to cancel task on source error +200c8922 Refactory: add method on_drain for download context +72e2bb30 Impl: cancel task with user defined error +a0413319 Sync test cases with interface modification +473334df Add access support for build_dir_from_object_map source object's access +973718a1 Add get_object_map_ex with access field return for object_map relate cache +4a547ca3 Add access param support for publish_file and build_file relate methods +78d8f93e Add access support to put_object_map relate methods +750e65d5 Add some logs for task manager +58d90843 Fix container dns: when resolv contain 127.0.0.53, mount the systemd resolv file instead +b398e932 Fix: download task finish directly when total length is zero +2b415e37 Fix: download task progress/speed +54965e6c Improve some logs output +f62cb4df Refactory: impl download task progress +bbec1935 Fix: finish download leaf task +fd230411 Refactory: upload task group cancel/close +4c2f95b4 Refactory: Add logic leaf download task +eab160ec Refactory: chunk downloader send interest with group_path field +50db1d5c Refactory: chunk downloader not mergable +062bf19e Add from_str support for access string +2243fa7b Add alias for trans output requests +ebb67790 Improve the log and error codes for local file relate codes +ff7dd4c1 Use insert_chunk instead of update_chunk_state for chunk state updater +0525944c Improve insert_chunk logic with update state when already exists for ndc module +fc2d8b18 Improve some logs output for ndn relate codes +128a7cc5 Fix: some warning with while let +f1890ba3 Add chunk exists check for ndn get_data cache mechanism +18c94cf2 Improve some error process in std::io poll relate methods +06f03a6a Improve the conversion between BuckyError and std::io::Error +e801b468 Improve put_chunk for local chunk cache +23a61570 Add cache mechanism to ndn get_data +9055ec35 Refactory: add group_path field to interest packet +1093046b Add range support for ndn get_data with chunk +e3797e31 Add group test case +5061b962 Refactory: poll split read +e700a047 Use {dec_id}/ as default group when no group param is specified +14339d1a Remove dec_id field of context object Add global context support for context +6922dfa0 Put_context is adjusted to depend on context manager Add access field for put_context request +968e5e6d Fix context path fix error & add test case +b70f7990 Fix error when context manager parse context string with object_id +de18c885 Add ndn context test cases Fix compile errors of trans relate methods +8687e171 Fix ndn referer param encode error +be8f06b3 Add debug output for changed of context +abcc02d8 Remove context_id field for query tasks request +21421faf Fix: build error for cyfs-stack +4f62dbad Fix: build error for cyfs-stack +6d6ccad3 Improve resp process for trans & sync api methods +3eb6ca28 Refactor put_context and get_context methods for trans +5ad7e7f1 Improve the clone_from_slice method for ObjectId +9ece347b Refactor context support for trans +7340db07 Refactor ndn api target related codes to support context +458ad1f6 Refactor context to support target mode +9ea97744 Add context field for ndn get_data request +4a0aa1b6 Adapt to bdt new context relate params and types +b51eed19 Add cache and path search category to context manager +f0427489 Add dec_id field for context object, and add strict limit to context_path field +3441fdb0 Refactory: rename ChunkEncodeDesc => ChunkCodecDesc; declare context.source_of as async function; +04db0d46 Add context holder generator for context manager +6081a426 Add context manager and holder core impls +23eb4af0 Refactor the TransContext core object +73d7dcb1 Add dec limit for trans task group relate methods +abda8cfc Improve the param of TransOutputProcessor methods +a3678c4e Improve the trans.query_tasks request path +0fb35dbb Add task group relate methods for trans api +c78b3568 Add a common impl of serde code for JsonCodec +70366e60 Refactor get_task_state method's response to add group support +2d335eff Add group field for DownloadTaskState +ba606857 Add task group for ndn get_data resp +bbb16276 Improve the url query parse for referer and group params +5fae309c Add task group support for NDN/Trans modules +71414249 Rename the task range reader +a5107424 Optimize the ChunkWriter write method +b5ba81fb DirLoader switch to reply on chunk_store_reader instead of local_data_manager +89df6fcc NDN local_data_manager's get relate impls switch to reply on target_data_manager instead +bdfabe75 Fix: split read test +12610350 Fix: cyfs stack ndn event apply to new bdt ndn interface +816e7f6b Refactor the param model of ndc/tracker/chunk_manager +a397bd52 Adapt to bdt's new download stream model +2d5eb444 Impl: split read for download task reader +6cd9410e Impl: Add Single source context +95c8554a Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +5a1f23af Merge branch 'cyfs-bdt-task-group-impl' into 74-integrate-bdt-task-context-and-group +6111f439 Fix: Release chunk cache and downloader with weak reference +ffc56abe Refactory:create seperate downloader when context is not mergable +1ff8388e Refactory: add loading state to chunk cache +8e3590a2 Refactory: split chunk downloader from chunk cache +f2a3672f Fix: call cc on_loss with error loss count value +1dd8bae3 Fix: Donwload task path logic +4f3a92c4 Fix: return download task speed +371792c0 Fix: use BuckyError instead of BuckyErrorCode in some state +167664c9 Fix: add chunk_list_writer method to TrackedChunkStore +b4a67578 Merge branch 'cyfs-bdt-task-group-impl' into bdt-beta +2e42dae0 Fix: stream chunk encoder always read cache with sync reader +bb954d5f Impl: Unit test for upload from path +8b7aa861 Refactory: Add start_upload_from_cache method +81014478 Refactory: Move ndn default event handler to utils +def00192 Refactory: remove default ndc/tracker from bdt stack +67f29271 Refactory: Taskgroup makesure path +896b39ba Impl: File raw cache for chunk +bc043adc In SN statistic, add endpoint's statistic. +ecb58708 Call sn support MTU_LARGE +2cf4567b Add Mutlity SN。 +2321e02c Fix: tcp tunnel send piece buffer with mtu +2ac27f33 Refactory: add DownloadContext trait +6832e73e Refactory: add DownloadContext trait +330a8940 Support large mtu and question&answer +e03962a7 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +d1cc885e Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +06d89662 Fix: chunk list task reader +f4d20813 Fix: close/finish download task group +5bd2ec64 Fix: task.reader return unexpected not found error +7d2e6f6f Fix:panic on download reader +de837c47 Refactory: write chunk from task.reader +677e444b Refactory: Reader of download task +c0a479e3 Refactory: Upload session wait establish +22e9cc0f Refactory: download/upload differs in tcp/udp tunnel +638a8fc4 Refactory: download/upload differs in tcp/udp tunnel +23251581 Fix: bind tunnel with upload/download session +70292ce4 Fix: cache packages in tunnel.build_send, send them when tunnel actived +197e241a Merge branch 'ndn-cache' into bdt-beta +51d5b714 Merge branch 'ndn-cache' into bdt-beta +ea1dae46 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +16d25537 Merge branch 'ndn-cache' into bdt-beta +c6bf684a log decrypt aeskey error info +79bceeea Fix: chunk list task reader +bc380433 Fix: close/finish download task group +61714a7b Fix: task.reader return unexpected not found error +97c955d7 Fix:panic on download reader +1e95e4da Refactory: write chunk from task.reader +9ad964fb Refactory: Reader of download task +d8bf33a0 Refactory: Upload session wait establish +06f3affc Refactory: download/upload differs in tcp/udp tunnel +2ef44f99 Refactory: download/upload differs in tcp/udp tunnel +8519534c Fix: bind tunnel with upload/download session +b2925e95 Fix: cache packages in tunnel.build_send, send them when tunnel actived +7235f3dc Merge branch 'ndn-cache' into bdt-beta +04e2a5a0 Merge branch 'ndn-cache' into bdt-beta +eaa0b650 Merge remote-tracking branch 'origin/bdt-beta' into bdt-beta +3d711110 Merge branch 'ndn-cache' into bdt-beta +8c8b6039 log decrypt aeskey error info +43ccf15c Impl: Cancel download chunk task +6efb6eca Test: download from uploader test ok +439635f5 Merge branch 'ndn-cache' into bdt-beta +0e08b03a Refactory: download/upload session support reverse step stream +96ffaef7 Refactory: impl download/upload session with new cache +292cf4ae Refactory: impl download/upload session with new cache +d38e31ba Refactory: impl download/upload session with new cache +07b40c65 Refactory: impl download/upload session with new cache +d525a649 Refactory: implement memory raw cache +e07a4b0e Refactory: chunk downloader with stream cache + +## [1.0.0.703] -- 2023/1/13 +cfd654ac Temporarily disable all ipv6 addresses for bdt stack + +## [1.0.0.702] -- 2023/1/12 +bb72348e App Manager AppSource logic +413edbad AppManager supports more detailed configuration +7b0704ec WIP: add new config for app manager +2eb6dce1 Modify the way to start file uploader +6076a69f Improve the update state relate logic for service in ood-daemon service +44fbe781 Fix: avoid duplicate hole punching process when retry sn call +ea48e120 Merge remote-tracking branch 'origin/fix-container-dns' +56f22e21 Add --startup-mode for ood-daemon startup script +cf1f363c Add startup-mode to ood-daemon service with network verify on system startup +56b755e6 Add active check in daemon update and state check loop +b7943988 Fix compile +2b355960 Fix container dns, when resolv contain 127.0.0.53 +d6b5bb06 Add timeout for repo in ood-daemon service +628649f0 Start the monitor service synchronously on startup +de1e9960 Add service_list cache mechanism for meta config repo +a84bfafe Remove the local status of meta config repo in ood-daemon service +a807f171 Fix: retry sn list when builder not establish in time +5639e004 App-tool and app-tool-ex return error correctly +26b234cb Merge remote-tracking branch 'origin/75-add-de-initialization-mechanism-for-sharedobjectstack' into main +f136c262 Fix some compile errors and warnings +a4ece723 Remove the useless base project +2d216910 Add app-manager.toml config file support to ood-installer tool +e111f3b2 Remove the useless old configuration of acl.toml +eae9d604 Merge branch 'main' into beta +d5463188 Merge branch 'main' into beta +b34744c3 Merge branch 'main' into beta +180ae196 Remove handler and event manager's none mode +d10953b2 Improve ws session and manager stop-related timing logic +8b84ef3f Add delayed start mechanism for router handler and events +c13cc029 Add shared stack stop test case +faf04a09 Improve ws and event manager stop strategy +c5d02ab9 Improve ws session and ws client stop strategy +007247e2 Refactor ws session related logic and improve packet parser logic +b0463c83 Add stop method to shared stack with requestors +1b80f43a Enable none mode for handler and event system in shared stack +8ec0888b Optimize the use of requestor by the service component and adopt the shared mode +d9d69051 Remove http handler support for shared stack +bb0e005e Add stop method to handler and event manager +1a2ada09 Add stop method for ws client +77ea26c6 Fix: cyfs-client correct get sn list from local stack +e29cd15c Merge branch 'main' into beta +0bb5dcd7 Sync service list method use the lock for services in ood-daemon +19b338e6 Improve some logs output +7e8cb267 Improve cmd status check return value and compare mechanism +fc800657 Improve the agent check for the browser disable mode +67a2179e NamedDataClient use init config, use GetData instead of GetDataWithMeta +e160a62a Improve the get_data logic of chunk_manager +9f7263bc Add memory cache for chunk_manager get_data_with_meta Improve the get_chunk_data resp body mechanism and remove the chunk_id verify temporarily +270778a9 Fix: stream pool use sn list in device cache +b1abf319 Fix: ignore sn list in build param's remote desc +ff05f5ff Fix: beta use correct built-in sn list +02fe10ef Fix: Add logs for build params info +26989db3 Merge branch 'main' into beta +440b90f9 Merge branch 'main' into beta +c377c61f Merge branch 'main' into beta +b0fe871d Merge branch 'main' into beta +ef8a124a Merge branch 'main' into beta +71e9e52b Merge branch 'main' into beta +2fa6be68 Fix: disable cyfs_debug::mutex check in some fraquently called functions From 2b57069a6410da59919a1fd4d6c0b1472ea874e2 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 19:33:18 +0800 Subject: [PATCH 311/553] Remove config repo cache after discovering system-config changed --- src/component/cyfs-meta-lib/src/helper.rs | 4 ++++ src/service/ood-daemon/src/config/monitor.rs | 2 ++ src/service/ood-daemon/src/config_repo/meta.rs | 6 +++++- src/service/ood-daemon/src/config_repo/mod.rs | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-meta-lib/src/helper.rs b/src/component/cyfs-meta-lib/src/helper.rs index 6185450d4..55288f375 100644 --- a/src/component/cyfs-meta-lib/src/helper.rs +++ b/src/component/cyfs-meta-lib/src/helper.rs @@ -84,6 +84,10 @@ impl MetaClientHelperWithObjectCache { } } + pub async fn clear_cache(&self) { + self.objects.lock().await.clear(); + } + pub async fn get_object( &self, meta_client: &MetaClient, diff --git a/src/service/ood-daemon/src/config/monitor.rs b/src/service/ood-daemon/src/config/monitor.rs index d7246003f..e49a102f1 100644 --- a/src/service/ood-daemon/src/config/monitor.rs +++ b/src/service/ood-daemon/src/config/monitor.rs @@ -37,6 +37,8 @@ impl SystemConfigMonitor { } let _ = DEVICE_CONFIG_MANAGER.init_repo(); + + DEVICE_CONFIG_MANAGER.get_repo().clear_cache().await; daemon.wakeup_check_update(); diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index d2e4ee67c..ebd5892cc 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -143,7 +143,7 @@ impl DeviceConfigMetaRepo { meta_client, cache: Mutex::new(None), service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), - service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24), 16), + service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24 * 7), 16), } } @@ -457,4 +457,8 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { Ok(device_config_str) } + + async fn clear_cache(&self) { + self.service_objects.clear_cache().await; + } } diff --git a/src/service/ood-daemon/src/config_repo/mod.rs b/src/service/ood-daemon/src/config_repo/mod.rs index 1ae5761b5..e3f33a815 100644 --- a/src/service/ood-daemon/src/config_repo/mod.rs +++ b/src/service/ood-daemon/src/config_repo/mod.rs @@ -17,6 +17,9 @@ use std::sync::Arc; #[async_trait] pub trait DeviceConfigRepo: Send + Sync { async fn fetch(&self) -> BuckyResult; + async fn clear_cache(&self) { + // do nothing on default! + } fn get_type(&self) -> &'static str; } From ec5015e0fd18c8d95cd1e3522b70e0ab353d70c5 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 20:15:20 +0800 Subject: [PATCH 312/553] Add retry strategy into meta config repo in case of network error --- .../src/config/device_config_manager.rs | 6 +- .../ood-daemon/src/config_repo/meta.rs | 87 ++++++++++++++----- .../ood-daemon/src/service/service_manager.rs | 1 + 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/service/ood-daemon/src/config/device_config_manager.rs b/src/service/ood-daemon/src/config/device_config_manager.rs index 7394a575f..d5c6298a9 100644 --- a/src/service/ood-daemon/src/config/device_config_manager.rs +++ b/src/service/ood-daemon/src/config/device_config_manager.rs @@ -148,7 +148,7 @@ impl DeviceConfigManager { let repo = self.get_repo(); // 从mete-chain拉取对应desc - let ret = async_std::future::timeout(Duration::from_secs(60), repo.fetch()).await; + let ret = async_std::future::timeout(Duration::from_secs(60 * 5), repo.fetch()).await; if ret.is_err() { let msg = format!("fetch device config timeout! repo={}", repo.get_type()); @@ -160,10 +160,10 @@ impl DeviceConfigManager { let device_config_str = match ret.unwrap() { Ok(v) => v, Err(e) => { - let msg = format!("load desc from repo failed! err={}", e); + let msg = format!("load device config from repo failed! err={}", e); error!("{}", msg); - return Err(BuckyError::from(msg)); + return Err(BuckyError::new(e.code(), msg)); } }; diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index ebd5892cc..e9d54d2c2 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -3,7 +3,9 @@ use crate::config::*; use cyfs_base::*; use cyfs_core::*; use cyfs_debug::Mutex; -use cyfs_meta_lib::{MetaClient, MetaClientHelper, MetaClientHelperWithObjectCache, MetaMinerTarget}; +use cyfs_meta_lib::{ + MetaClient, MetaClientHelper, MetaClientHelperWithObjectCache, MetaMinerTarget, +}; use cyfs_util::LOCAL_DEVICE_MANAGER; use async_trait::async_trait; @@ -108,7 +110,7 @@ impl DeviceConfigGenerator { false => ServiceState::Stop, }; - debug!("new service item: id={}, version={}", id, version); + debug!("new service item: id={}, origin version in service list={}", id, version); let mut service = ServiceConfig::new(); service.id = id; service.version = version.to_owned(); @@ -142,8 +144,14 @@ impl DeviceConfigMetaRepo { Self { meta_client, cache: Mutex::new(None), - service_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 4), 16), - service_dir_objects: MetaClientHelperWithObjectCache::new(std::time::Duration::from_secs(3600 * 24 * 7), 16), + service_objects: MetaClientHelperWithObjectCache::new( + std::time::Duration::from_secs(3600 * 4), + 16, + ), + service_dir_objects: MetaClientHelperWithObjectCache::new( + std::time::Duration::from_secs(3600 * 24 * 7), + 16, + ), } } @@ -166,7 +174,10 @@ impl DeviceConfigMetaRepo { info!( "device config repo: config_desc={}, device_id={}, service_list_id={}, version={}", - get_system_config().config_desc, device_id, service_list_id, service_list_version + get_system_config().config_desc, + device_id, + service_list_id, + service_list_version ); Ok(service_list_id) @@ -186,7 +197,6 @@ impl DeviceConfigMetaRepo { } async fn load_service_list(&self) -> BuckyResult { - let service_list_id = Self::gen_service_list_id()?; let ret = MetaClientHelper::get_object(&self.meta_client, &service_list_id).await?; if ret.is_none() { @@ -203,7 +213,10 @@ impl DeviceConfigMetaRepo { // 解码 let list = AppList::clone_from_slice(&object_raw).map_err(|e| { - let msg = format!("decode service list object failed! id={}, {}", service_list_id, e); + let msg = format!( + "decode service list object failed! id={}, {}", + service_list_id, e + ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -219,7 +232,10 @@ impl DeviceConfigMetaRepo { } async fn load_service(&self, service_id: &ObjectId) -> BuckyResult { - let ret = self.service_objects.get_object_raw(&self.meta_client, service_id).await?; + let ret = self + .service_objects + .get_object_raw(&self.meta_client, service_id) + .await?; if ret.is_none() { let msg = format!( "load service object from meta chain but not found! id={}", @@ -244,7 +260,10 @@ impl DeviceConfigMetaRepo { } async fn load_service_dir(&self, dir_id: &ObjectId) -> BuckyResult { - let ret = self.service_dir_objects.get_object_raw(&self.meta_client, dir_id).await?; + let ret = self + .service_dir_objects + .get_object_raw(&self.meta_client, dir_id) + .await?; if ret.is_none() { let msg = format!( "load service dir from meta chain but not found! id={}", @@ -413,15 +432,8 @@ impl DeviceConfigMetaRepo { true } -} -#[async_trait] -impl DeviceConfigRepo for DeviceConfigMetaRepo { - fn get_type(&self) -> &'static str { - "meta" - } - - async fn fetch(&self) -> BuckyResult { + async fn fetch_inner(&self) -> BuckyResult { // 从mete-chain拉取对应的service_list let service_list = self.load_service_list().await?; @@ -450,13 +462,46 @@ impl DeviceConfigRepo for DeviceConfigMetaRepo { }); } - debug!( - "load device_config from meta: config={}", - device_config_str - ); + debug!("load device_config from meta: config={}", device_config_str); Ok(device_config_str) } +} + +#[async_trait] +impl DeviceConfigRepo for DeviceConfigMetaRepo { + fn get_type(&self) -> &'static str { + "meta" + } + + async fn fetch(&self) -> BuckyResult { + use rand::Rng; + + // Use a random retry interval + let mut retry_interval_secs: u64 = rand::thread_rng().gen_range(10, 60); + let mut retry_count = 0; + loop { + match self.fetch_inner().await { + Ok(ret) => break Ok(ret), + Err(e) => match e.code() { + BuckyErrorCode::HttpError => { + async_std::task::sleep(std::time::Duration::from_secs(retry_interval_secs)) + .await; + retry_interval_secs *= 2; + retry_count += 1; + + if retry_count > 3 { + break Err(e); + } + } + + _ => { + break Err(e); + } + }, + } + } + } async fn clear_cache(&self) { self.service_objects.clear_cache().await; diff --git a/src/service/ood-daemon/src/service/service_manager.rs b/src/service/ood-daemon/src/service/service_manager.rs index 4f656c614..2c88f76db 100644 --- a/src/service/ood-daemon/src/service/service_manager.rs +++ b/src/service/ood-daemon/src/service/service_manager.rs @@ -484,6 +484,7 @@ impl ServiceManager { } } } + debug!("sync all service packages complete!"); } async fn sync_service_package(service_info: &ServiceItem) -> BuckyResult<()> { From 3f32a70cce42d18577d59105f86339c2ec728417 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 20:34:04 +0800 Subject: [PATCH 313/553] Adjust the interval for checking for upgrades to 30 minutes --- src/service/ood-daemon/src/daemon/daemon.rs | 2 +- src/service/ood-daemon/src/main.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index 4c59ca60e..fb05c73ca 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -187,7 +187,7 @@ impl Daemon { } // 检查绑定状态 - let timer = task::sleep(Duration::from_secs(60 * 10)); + let timer = task::sleep(Duration::from_secs(60 * 30)); let (abort_handle, abort_registration) = AbortHandle::new_pair(); diff --git a/src/service/ood-daemon/src/main.rs b/src/service/ood-daemon/src/main.rs index 5ad479cd4..94856767f 100644 --- a/src/service/ood-daemon/src/main.rs +++ b/src/service/ood-daemon/src/main.rs @@ -1,4 +1,4 @@ -// #![windows_subsystem = "windows"] +#![windows_subsystem = "windows"] mod config; mod config_repo; @@ -22,9 +22,9 @@ const SERVICE_NAME: &str = ::cyfs_base::OOD_DAEMON_NAME; fn start_log() { cyfs_debug::CyfsLoggerBuilder::new_service(SERVICE_NAME) - .level("debug") + .level("info") .console("info") - .enable_bdt(Some("debug"), Some("debug")) + .enable_bdt(Some("info"), Some("info")) .build() .unwrap() .start(); From f0d8a714582a3ce17b6b59efb524e2464ab84fb5 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 12:52:44 +0800 Subject: [PATCH 314/553] Update nightly changelog --- CHANGELOG-nightly.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md index 527382d38..ec558d1e2 100644 --- a/CHANGELOG-nightly.md +++ b/CHANGELOG-nightly.md @@ -1,3 +1,23 @@ +## [1.0.0.722] -- 2023/2/24 +0d1eecc5 Add mechanism that trigger immediate update after system config changes +64f019fe Fix two log param errors +1776889e Add dynamic monitoring mechanism for system-config.toml +afb5c68c Add repeated loading supports to system-config.toml in ood-daemon +e81821d7 Fix two warning after package updated +8a2bba37 Switch meta repo to dynamic dependency on system config +1cf5799f Fix: pack script error +16eaf64c Fix: Missing app-manager lib.rs +de517952 Add app repo downloader for ood-installer +4eda0873 Add semver epoch check into ood-daemon +06717ad2 Add cache for meta config repo in ood-daemon +69f88233 Add meta client helper with object cache +0d5e5a69 Add service_version and preview relate supports into ood-daemon for better control of services update +7622e76a Add semver support into dec_app core object and with test cases +a976a6bf App-tool support change preview service version, pack script add preview version to service +b0e496bb Fix the panic that may be caused by check db in cyfs-noc +06201fbe Add api edition relate header to requestors +12d526f9 Add check mechanism to noc meta db in case of main table missing + ## [1.0.0.718] -- 2023/2/21 1b0cf118 Change sync services packages from parallel to serial 638848a2 Remove two spawn task using for cancel on timeout From 52994e810e04d8f22e446021f0fb9e49246e7eb1 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 15:43:40 +0800 Subject: [PATCH 315/553] Improve config with some comments --- src/tools/ood-installer/res/default/debug.toml | 3 +++ src/tools/ood-installer/res/synology/debug.toml | 3 +++ src/tools/ood-installer/res/vood/debug.toml | 3 +++ src/tools/ood-installer/src/system_config_gen.rs | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/tools/ood-installer/res/default/debug.toml b/src/tools/ood-installer/res/default/debug.toml index 9b42967de..45dda1079 100644 --- a/src/tools/ood-installer/res/default/debug.toml +++ b/src/tools/ood-installer/res/default/debug.toml @@ -1,6 +1,9 @@ [log.global] level = "info" console = "info" +#file = "off" +#file_max_size = 10485760 +#file_max_count = count [log.cyfs_bdt] level = "info" diff --git a/src/tools/ood-installer/res/synology/debug.toml b/src/tools/ood-installer/res/synology/debug.toml index 9b42967de..45dda1079 100644 --- a/src/tools/ood-installer/res/synology/debug.toml +++ b/src/tools/ood-installer/res/synology/debug.toml @@ -1,6 +1,9 @@ [log.global] level = "info" console = "info" +#file = "off" +#file_max_size = 10485760 +#file_max_count = count [log.cyfs_bdt] level = "info" diff --git a/src/tools/ood-installer/res/vood/debug.toml b/src/tools/ood-installer/res/vood/debug.toml index 94bbe6fbf..83acb1a57 100644 --- a/src/tools/ood-installer/res/vood/debug.toml +++ b/src/tools/ood-installer/res/vood/debug.toml @@ -1,6 +1,9 @@ [log.global] level = "info" console = "off" +#file = "off" +#file_max_size = 10485760 +#file_max_count = count [log.cyfs_bdt] level = "info" diff --git a/src/tools/ood-installer/src/system_config_gen.rs b/src/tools/ood-installer/src/system_config_gen.rs index 0f7824487..d02c3afa5 100644 --- a/src/tools/ood-installer/src/system_config_gen.rs +++ b/src/tools/ood-installer/src/system_config_gen.rs @@ -4,6 +4,9 @@ use cyfs_base::{BuckyError, BuckyResult}; const SYSTEM_CONFIG_TEMPLATE: &str = r#"[device] target = "${target}" config_desc = "${config_repo}" +#service_list_version = "nightly" +#service_version = "default" +#preview = false [[repository]] type = "${repo_type}" From d156502fd6e2c18ea527278b2500d9973fc266a7 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 16:18:03 +0800 Subject: [PATCH 316/553] Add system-config field to ood status --- src/service/ood-daemon/src/config/system_config.rs | 7 +++---- src/service/ood-daemon/src/status/service_status.rs | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 1f5341cc0..7ec69d578 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -55,14 +55,13 @@ impl SystemConfig { debug!("will load system-config file: {}", config_file.display()); - let node = self.load_as_json(&config_file).await?; + let node = Self::load_as_toml(&config_file)?; self.parse_config(node).await } - async fn load_as_json(&self, file_path: &Path) -> BuckyResult { - let content = async_std::fs::read_to_string(&file_path) - .await + pub fn load_as_toml(file_path: &Path) -> BuckyResult { + let content = std::fs::read_to_string(&file_path) .map_err(|e| { let msg = format!( "load system config to string error! file={}, {}", diff --git a/src/service/ood-daemon/src/status/service_status.rs b/src/service/ood-daemon/src/status/service_status.rs index e19b25b7f..b6dd37055 100644 --- a/src/service/ood-daemon/src/status/service_status.rs +++ b/src/service/ood-daemon/src/status/service_status.rs @@ -1,5 +1,5 @@ use crate::{SERVICE_MANAGER}; -use crate::config::{ServiceState, ServiceConfig, DEVICE_CONFIG_MANAGER}; +use crate::config::{ServiceState, ServiceConfig, DEVICE_CONFIG_MANAGER, SystemConfig, PATHS}; use crate::service::ServicePackageLocalState; use cyfs_base::bucky_time_now; @@ -21,6 +21,7 @@ pub struct OODServiceStatusItem { #[derive(Serialize)] pub struct OODDaemonStatus { last_update_time: u64, + system_config: Option, device_config: Vec, services: Vec, } @@ -29,6 +30,7 @@ impl Default for OODDaemonStatus { fn default() -> Self { Self { last_update_time: bucky_time_now(), + system_config: None, device_config: vec![], services: vec![], } @@ -76,10 +78,13 @@ impl OODDaemonStatusGenerator { Err(_) => vec![], }; + let system_config = SystemConfig::load_as_toml(&PATHS.system_config).ok(); + let services = SERVICE_MANAGER.collect_status(); OODDaemonStatus { last_update_time: bucky_time_now(), + system_config, device_config, services, } From d0b71d53def31d6b486721032b50195a1b3b305a Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:01:42 +0800 Subject: [PATCH 317/553] Fix app-manager leave defunct process when force kill app, kill app process when DApp dropped --- src/service/app-manager/src/app_controller.rs | 4 +-- src/service/app-manager/src/dapp.rs | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/service/app-manager/src/app_controller.rs b/src/service/app-manager/src/app_controller.rs index 1c3834fa3..0baf92a32 100644 --- a/src/service/app-manager/src/app_controller.rs +++ b/src/service/app-manager/src/app_controller.rs @@ -337,8 +337,8 @@ impl AppController { } } } else { - let reader = self.dapp_instance.read().unwrap(); - if let Some(dapp) = reader.get(app_id) { + let mut app_list = self.dapp_instance.write().unwrap(); + if let Some(dapp) = app_list.remove(app_id) { let result = dapp.stop().map_err(|e| { warn!("stop app directly failed, app:{}, err:{}", app_id, e); SubErrorCode::CommondFailed diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index f3bcb235f..012b5d26a 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -43,6 +43,16 @@ fn get_str(value: &Value, key: &str) -> BuckyResult { .to_owned()) } +impl Drop for DApp { + fn drop(&mut self) { + if let Some(mut child) = self.process.lock().unwrap().as_ref() { + warn!("dapp {} dropped when child process start! pid {}", &self.dec_id, child.id()); + child.kill(); + child.wait(); + } + } +} + impl DApp { pub fn load_from_app_id(app_id: &str) -> BuckyResult { let dapp = DApp::load_from(&get_app_dir(&app_id.to_string()))?; @@ -181,7 +191,6 @@ impl DApp { let mut command = Command::new(program); command.args(&args[1..]).current_dir(dir); if let Some(out) = stdout { - command.stdout(out); } #[cfg(target_os = "windows")] @@ -235,25 +244,22 @@ impl DApp { pub fn start(&self) -> BuckyResult { if !self.status()? { let child = DApp::run(&self.info.start, &self.work_dir, true, None)?; - + *self.process.lock().unwrap() = Some(child); // mark pid let id = child.id(); let lock_file = self.get_pid_file_path()?; let buf = format!("{}", id).into_bytes(); std::fs::write(lock_file, &buf).map_err(|e| { - error!( - "app[{}]{} write lock file failed! err {}", - self.dec_id, self.info.id, e - ); - BuckyError::from(BuckyErrorCode::ExecuteError) + let msg = format!("app[{}]{} write lock file failed! err {}", + self.dec_id, self.info.id, e); + error!("{}", &msg); + BuckyError::new(BuckyErrorCode::ExecuteError, msg) })?; info!( "start app:{} {} success! and write pid {:?}", self.dec_id, self.info.id, id ); - *self.process.lock().unwrap() = Some(child); - return Ok(true); } Ok(false) @@ -451,11 +457,11 @@ impl DApp { let pid = pid.unwrap(); info!( "stop app[{}] by inner cmd failed, try to force kill by pid {}", - &self.info.id, pid + &self.dec_id, pid ); #[cfg(windows)] { - Command::new("taskkill") + let mut child = Command::new("taskkill") .arg("/F") .arg("/T") .arg("/PID") @@ -465,10 +471,11 @@ impl DApp { error!("kill app:{} failed! err {}", pid, e); BuckyError::from(BuckyErrorCode::ExecuteError) })?; + let _ = child.wait(); } #[cfg(not(windows))] { - Command::new("kill") + let mut child = Command::new("kill") .arg("-9") .arg(&pid) .spawn() @@ -476,6 +483,7 @@ impl DApp { error!("kill app:{} failed! err {}", pid, e); BuckyError::from(BuckyErrorCode::ExecuteError) })?; + let _ = child.wait(); } let lock_file = self.get_pid_file_path()?; From ca38c6ffbedcc96f375a2f8beb2c52a69fb22532 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:02:06 +0800 Subject: [PATCH 318/553] Bump minor version to 1.1 --- scripts/pack.js | 2 +- src/component/cyfs-base/src/base/channel.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index 34432d425..d59ef46d2 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -78,7 +78,7 @@ function meta_url(channel) { } } -let version = `1.0.${version_from_channel(channel)}.${buildnumber}`; +let version = `1.1.${version_from_channel(channel)}.${buildnumber}`; let repo_path = process.env.FFS_SERVICE_REPO_DESC; if (!repo_path) { diff --git a/src/component/cyfs-base/src/base/channel.rs b/src/component/cyfs-base/src/base/channel.rs index b1abb388a..537e0556b 100644 --- a/src/component/cyfs-base/src/base/channel.rs +++ b/src/component/cyfs-base/src/base/channel.rs @@ -61,7 +61,7 @@ pub fn get_target() -> &'static str { fn get_version_impl() -> String { let channel_ver = get_channel().get_ver(); - format!("1.0.{}.{}-{} ({})", channel_ver, env!("VERSION"), get_channel(), env!("BUILDDATE")) + format!("1.1.{}.{}-{} ({})", channel_ver, env!("VERSION"), get_channel(), env!("BUILDDATE")) } fn get_channel_impl() -> CyfsChannel { From 6cba2c64d01a933391282620460471ebec9f955a Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 319/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index b892d402f..60531e1b7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1766,6 +1766,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1779,6 +1780,7 @@ dependencies = [ "semver 1.0.16", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1828,6 +1830,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.0" @@ -2179,6 +2240,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -3237,6 +3300,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.15" From 90339369caadf539bedad9f7208cf88c4eb5695d Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 320/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 1 + .../cyfs-lib/src/storage/remote_storage.rs | 12 ++ .../cyfs-perf/cyfs-perf-base/src/items.rs | 7 + .../cyfs-perf/cyfs-perf-client/Cargo.toml | 6 +- .../cyfs-perf/cyfs-perf-client/src/client.rs | 84 +++++----- .../cyfs-perf/cyfs-perf-client/src/config.rs | 13 ++ .../cyfs-perf-client/src/reporter.rs | 145 +++++++++++------- .../cyfs-perf/cyfs-perf-client/src/store.rs | 4 +- src/tests/cyfs-stack-test/src/case/perf.rs | 2 +- 9 files changed, 162 insertions(+), 112 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 60531e1b7..f09b84bc2 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2150,6 +2150,7 @@ dependencies = [ "android_logger", "async-std", "async-trait", + "chrono", "cyfs-base", "cyfs-core", "cyfs-debug", diff --git a/src/component/cyfs-lib/src/storage/remote_storage.rs b/src/component/cyfs-lib/src/storage/remote_storage.rs index 46200f2ee..20e16f389 100644 --- a/src/component/cyfs-lib/src/storage/remote_storage.rs +++ b/src/component/cyfs-lib/src/storage/remote_storage.rs @@ -1,3 +1,4 @@ +use cyfs_base::DeviceId; use super::collection::*; use super::remote_noc::*; use crate::stack::*; @@ -27,6 +28,17 @@ impl RemoteNOCStorage { NOCCollectionSync::new(id, remote_noc.into_noc()) } + pub fn new_noc_collection_sync_uni(id: &str, stack: &UniCyfsStackRef, device_id: &DeviceId) -> NOCCollectionSync + where + T: Default + CollectionCodec + Send + 'static, + { + let remote_noc = RemoteNamedObjectCache::new( + stack.non_service().clone(), + device_id, + ); + NOCCollectionSync::new(id, remote_noc.into_noc()) + } + pub fn new_noc_collection_rw_sync( id: &str, stack: &SharedCyfsStack, diff --git a/src/component/cyfs-perf/cyfs-perf-base/src/items.rs b/src/component/cyfs-perf/cyfs-perf-base/src/items.rs index 4eb54255f..2babb61b3 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/src/items.rs +++ b/src/component/cyfs-perf/cyfs-perf-base/src/items.rs @@ -4,6 +4,7 @@ use cyfs_lib::*; use serde::{Deserialize, Serialize}; use std::collections::{hash_map::Entry, HashMap}; +use std::fmt::{Display, Formatter}; // 统计所在的时间间隔 #[derive(Debug, Clone, Serialize, Deserialize)] @@ -12,6 +13,12 @@ pub struct PerfTimeRange { pub end: u64, } +impl Display for PerfTimeRange { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}-{}", self.begin, self.end) + } +} + impl Default for PerfTimeRange { fn default() -> Self { Self { diff --git a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml index 45bde7a0e..f9c167319 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml @@ -8,10 +8,7 @@ license = 'BSD-2-Clause' description = 'Rust cyfs-perf-client package' [dependencies] -log = { version = '0.4', features = [ - 'max_level_trace', - 'release_max_level_trace', -] } +log = { version = '0.4'} serde_json = '1.0' int-enum = '0.4' cyfs-perf-base = { path = '../cyfs-perf-base', version = '0.6' } @@ -25,6 +22,7 @@ async-std = { version = '1.11', features = ['unstable', 'attributes'] } rand = '0.7' sha2 = '0.8' async-trait = '0.1.53' +chrono = "0.4" [target.'cfg(target_os = "android")'.dependencies] jni = '0.19' diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs index 418859bd0..5d029c415 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs @@ -3,13 +3,13 @@ use crate::isolate::PerfIsolate; use crate::reporter::*; use crate::store::PerfStore; use cyfs_base::*; -use cyfs_core::*; use cyfs_debug::Mutex; use cyfs_lib::*; -use std::collections::{hash_map, HashMap}; +use std::collections::{HashMap}; use std::ops::Deref; use std::sync::Arc; +use std::time::Duration; // pub const PERF_DEC_ID_STR: &str = "5aSixgP8EPf6HkP54Qgybddhhsd1fgrkg7Atf2icJiiS"; @@ -17,12 +17,21 @@ pub struct PerfClientInner { id: String, version: String, dec_id: Option, - perf_server_config: PerfServerConfig, + perf_config: PerfConfig, - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, isolates: Mutex>, + + local_device: DeviceId, + owner: ObjectId +} + +pub struct PerfConfig { + pub reporter: PerfServerConfig, + pub save_to_file: bool, + pub report_interval: Duration } impl PerfClientInner { @@ -30,11 +39,11 @@ impl PerfClientInner { id: String, version: String, dec_id: Option, - perf_server_config: PerfServerConfig, - stack: SharedCyfsStack, + perf_config: PerfConfig, + stack: UniCyfsStackRef, + local_device: DeviceId, + owner: ObjectId ) -> Self { - let device_id = stack.local_device_id(); - let dec_name = match &dec_id { Some(id) => id.to_string(), None => "system".to_owned(), @@ -42,42 +51,44 @@ impl PerfClientInner { // 这里需要使用一个足够区分度的id,避免多个dec和内核共享协议栈情况下,同时使用PerfClient导致的冲突 // TODO version区别对待和,不同版本的数据是否可以合并 - let store_object_id = format!("{}-{}-{}-cyfs-perf-store", device_id, dec_name, id); + let store_object_id = format!("{}-{}-{}-cyfs-perf-store", &local_device, dec_name, id); - let store = PerfStore::new(store_object_id, &stack); + let store = PerfStore::new(store_object_id, &stack, &local_device); Self { id, version, dec_id, - perf_server_config, + perf_config, cyfs_stack: stack, store, isolates: Mutex::new(HashMap::new()), + local_device, + owner } } pub(crate) async fn start(&self) -> BuckyResult<()> { - let req = UtilGetZoneOutputRequest::new(None, None); - let resp = self.cyfs_stack.util().get_zone(req).await?; - let people_id = resp.zone.owner().to_owned(); - if let Err(e) = self.store.start().await { // FIXME 启动失败如何处理?一般只有从noc加载失败才会出问题 error!("perf client start error! {}", e); } - let perf_server = PerfServerLoader::load_perf_server(self.perf_server_config.clone()).await; + let save_to_local = self.perf_config.reporter.is_none(); + let perf_server = PerfServerLoader::load_perf_server(self.perf_config.reporter.clone()).await; let reporter = PerfReporter::new( self.id.clone(), self.version.clone(), - resp.device_id, - people_id, + self.local_device.clone(), + self.owner.clone(), self.dec_id.clone(), perf_server, self.cyfs_stack.clone(), self.store.clone(), + save_to_local, + self.perf_config.save_to_file, + self.perf_config.report_interval, ); reporter.start(); @@ -128,32 +139,12 @@ impl PerfClientInner { Ok(()) } - pub fn is_isolates_exists(&self, id: &str) -> bool { - self.isolates.lock().unwrap().contains_key(id) - } - - pub fn new_isolate(&self, id: &str) -> PerfIsolate { + pub fn get_isolate(&self, id: &str) -> PerfIsolate { let mut isolates = self.isolates.lock().unwrap(); - match isolates.entry(id.to_owned()) { - hash_map::Entry::Vacant(v) => { - log::info!("new isolate module: id={}", id); - - let isolate = PerfIsolate::new(id); - let temp_isolate = isolate.clone(); - v.insert(isolate); - temp_isolate.clone() - } - hash_map::Entry::Occupied(o) => { - let msg = format!("isolate module already exists: id={}", id); - log::error!("{}", msg); - - o.get().clone() - } - } - } - - pub fn get_isolate(&self, id: &str) -> Option { - self.isolates.lock().unwrap().get(id).map(|v| v.clone()) + isolates.entry(id.to_owned()).or_insert_with(|| { + log::info!("create isolate module: id={}", id); + PerfIsolate::new(id) + }).clone() } } @@ -165,10 +156,11 @@ impl PerfClient { id: String, version: String, dec_id: Option, - perf_server_config: PerfServerConfig, - stack: SharedCyfsStack, + perf_config: PerfConfig, + stack: UniCyfsStackRef, + local_device: DeviceId, owner: ObjectId ) -> Self { - let ret = PerfClientInner::new(id, version, dec_id, perf_server_config, stack); + let ret = PerfClientInner::new(id, version, dec_id, perf_config, stack, local_device, owner); Self(Arc::new(ret)) } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/config.rs b/src/component/cyfs-perf/cyfs-perf-client/src/config.rs index fe6b82a6e..bd5b2376d 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/config.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/config.rs @@ -18,6 +18,18 @@ pub enum PerfServerConfig { // 系统默认值,优先使用本地配置,其次使用链上的值 Default, + + // 只存储到本地,不上报到任何Server + None +} + +impl PerfServerConfig { + pub fn is_none(&self) -> bool { + match self { + PerfServerConfig::None => true, + _ => false + } + } } impl Default for PerfServerConfig { @@ -33,6 +45,7 @@ impl PerfServerLoader { PerfServerConfig::OOD => None, PerfServerConfig::Specified(device_id) => Some(device_id), PerfServerConfig::Default => Self::load_default_perf_server().await, + PerfServerConfig::None => None } } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index aff5d3c23..8a7592b55 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -1,13 +1,17 @@ +use std::path::{PathBuf}; use super::store::PerfStore; use cyfs_base::*; use cyfs_lib::*; use cyfs_perf_base::*; use std::sync::Arc; +use std::time::Duration; +use chrono::Local; +use crate::CYFS_PERF_SERVICE_NAME; // 用以实现统计项的上报 struct PerfReporterInner { - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, // PerfObject的依赖信息 @@ -19,6 +23,11 @@ struct PerfReporterInner { // 上报的目标 perf_server: Option, + save_to_local: bool, + save_path: Option, + + // 上报间隔 + report_interval: Duration, } impl PerfReporterInner { @@ -29,9 +38,31 @@ impl PerfReporterInner { people_id: ObjectId, dec_id: Option, perf_server: Option, - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, + save_to_local: bool, + save_to_file: bool, + report_interval: Duration ) -> Self { + let save_path = if save_to_file { + let path = if let Some(dec_id) = dec_id { + cyfs_util::get_app_data_dir(&dec_id.to_string()).join("stat").join(&id) + } else { + cyfs_util::get_service_data_dir(CYFS_PERF_SERVICE_NAME).join(&id) + }; + if !path.exists() { + if let Err(e) = std::fs::create_dir_all(&path) { + error!("create dir {} err {}, disable stat to file", path.display(), e); + None + } else { + Some(path) + } + } else { + Some(path) + } + } else { + None + }; Self { id, version, @@ -41,12 +72,15 @@ impl PerfReporterInner { perf_server, cyfs_stack, store, + save_to_local, + save_path, + report_interval } } pub async fn run(&self) { loop { - async_std::task::sleep(std::time::Duration::from_secs(60 * 10)).await; + async_std::task::sleep(self.report_interval).await; // 这里先按照等间隔均匀上报,忽略上报的结果 let _ = self.report_once().await; @@ -75,6 +109,16 @@ impl PerfReporterInner { return Ok(()); } + if let Some(path) = &self.save_path { + let begin: chrono::DateTime = bucky_time_to_system_time(data.time_range.begin).into(); + let end: chrono::DateTime = bucky_time_to_system_time(data.time_range.end).into(); + let pretty_format = "%Y%m%d_%H%M%S"; + let file_name = format!("{}-{}.stat", begin.format(pretty_format), end.format(pretty_format)); + if let Ok(file) = std::fs::File::create(path.join(file_name)) { + serde_json::to_writer_pretty(&file, &data); + } + } + debug!( "will report perf data: id={}, version={}, data={:?}", self.id, self.version, data @@ -90,17 +134,12 @@ impl PerfReporterInner { ); let perf_id = perf_obj.perf_id(); - info!( - "will report perf: id={}, version={}, target={:?}, perf_object={}", - self.id, self.version, self.perf_server, perf_id, - ); + info!("will report perf: id={}, version={}, target={:?}, perf_object={}", + self.id, self.version, self.perf_server, perf_id); - let perf_server = self - .perf_server - .as_ref() - .map(|id| id.object_id().to_owned()); + let perf_server = self.perf_server.as_ref().map(|id| id.object_id().to_owned()); - match self.put_object(&perf_obj, perf_server, 0).await { + match self.put_object(&perf_obj, perf_server, 0, self.save_to_local).await { Ok(_) => { info!( "report perf success! id={}, target={:?}, perf_object={}", @@ -119,18 +158,13 @@ impl PerfReporterInner { } // NON_REQUEST_FLAG_SIGN_BY_DEVICE | NON_REQUEST_FLAG_SIGN_SET_DESC | NON_REQUEST_FLAG_SIGN_SET_BODY - pub async fn put_object( + pub async fn put_object( &self, - obj: &N, + obj: &Perf, target: Option, sign_flags: u32, + save_to_local: bool ) -> BuckyResult<()> - where - D: ObjectType, - T: RawEncode, - N: RawConvertTo, - N: NamedObject, - ::ContentType: BodyContent, { let raw; let object_id = obj.desc().calculate_id(); @@ -139,11 +173,7 @@ impl PerfReporterInner { let req = CryptoSignObjectRequest::new(object_id.clone(), object_raw, sign_flags); // 先给Obj签名, 用Client的Device - let resp = self - .cyfs_stack - .crypto() - .sign_object(req) - .await + let resp = self.cyfs_stack.crypto_service().sign_object(req).await .map_err(|e| { error!("{} sign failed, err {}", &object_id, e); e @@ -154,45 +184,36 @@ impl PerfReporterInner { } // 把obj再put出去 - match self - .cyfs_stack - .non_service() - .put_object(NONPutObjectOutputRequest { - common: NONOutputRequestCommon { - req_path: None, - source: None, - target, - dec_id: obj.desc().dec_id().clone(), - flags: 0, - level: NONAPILevel::Router, - }, - object: NONObjectInfo { - object_id: object_id.clone(), - object_raw: raw, - object: None, - }, - access: None, - }) - .await - { + let mut req = NONPutObjectOutputRequest::new( + if save_to_local { NONAPILevel::NOC } else { NONAPILevel::Router }, + object_id.clone(), raw); + req.common.target = if save_to_local { None } else { target }; + req.common.dec_id = obj.desc().dec_id().clone(); + let str_target = if save_to_local { "local".to_owned() } else {target.map_or("ood".to_owned(), |id| id.to_string())}; + match self.cyfs_stack.non_service().put_object(req).await { Ok(_) => { - info!( - "### put perf obj [{}] to {} success!", - object_id, - target.map_or("ood".to_owned(), |id| id.to_string()) - ); + info!("### put perf obj {} to {} success!", &object_id, str_target); Ok(()) } Err(e) => { - error!( - "### put perf obj [{}] to {} failed! {}", - object_id, - target.map_or("ood".to_owned(), |id| id.to_string()), - e - ); + error!("### put perf obj [{}] to {} failed! {}", &object_id, str_target, e); Err(e) } - } + }?; + + // 存到root_state + let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); + req.access = access; + req.common.target = self.target.clone(); + req.common.target_dec_id = self.target_dec_id.clone(); + + let resp = self.cyfs_stack.root_state().create_op_env(req).await?; + let path_env = PathOpEnvStub::new(resp, self.target.clone(), self.target_dec_id.clone()); + let key = obj.get_time_range().to_string(); + path_env.set_with_key("/stat", key, &object_id, None, true).await?; + path_env.commit().await?; + + Ok(()) } } @@ -207,8 +228,11 @@ impl PerfReporter { people_id: ObjectId, dec_id: Option, perf_server: Option, - cyfs_stack: SharedCyfsStack, + cyfs_stack: UniCyfsStackRef, store: PerfStore, + save_to_local: bool, + save_to_file: bool, + report_interval: Duration, ) -> Self { let ret = PerfReporterInner::new( id, @@ -219,6 +243,9 @@ impl PerfReporter { perf_server, cyfs_stack, store, + save_to_local, + save_to_file, + report_interval ); Self(Arc::new(ret)) } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs index 965693649..3359ccd3d 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs @@ -19,8 +19,8 @@ pub(crate) struct PerfStore { } impl PerfStore { - pub fn new(id: String, stack: &SharedCyfsStack) -> Self { - let cache = RemoteNOCStorage::new_noc_collection_sync(&id, stack); + pub fn new(id: String, stack: &UniCyfsStackRef, device_id: &DeviceId) -> Self { + let cache = RemoteNOCStorage::new_noc_collection_sync_uni(&id, stack, device_id); let locked = Arc::new(AtomicBool::new(false)); Self { cache, locked } } diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index 978e205c4..f79043ee6 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -28,7 +28,7 @@ pub async fn test() { let ret = perf.start().await; assert!(ret.is_ok()); - let isolate = perf.new_isolate("main"); + let isolate = perf.get_isolate("main"); test_flush(perf.clone()).await; test_request(isolate.clone()).await; test_acc(isolate.clone()).await; From f19e05196489da3ca71fc7a59fafd5e27891122e Mon Sep 17 00:00:00 2001 From: liqirun Date: Fri, 24 Feb 2023 20:12:13 +0800 Subject: [PATCH 321/553] Fix stream & NDN send data bugs --- src/component/cyfs-bdt/examples/pacing.rs | 175 ++++++++++++++++++ src/component/cyfs-bdt/src/cc/bbr.rs | 46 ++--- src/component/cyfs-bdt/src/cc/cc.rs | 24 ++- src/component/cyfs-bdt/src/cc/cc_impl.rs | 6 +- src/component/cyfs-bdt/src/cc/ledbat.rs | 25 ++- src/component/cyfs-bdt/src/cc/mod.rs | 2 + src/component/cyfs-bdt/src/cc/pacing.rs | 93 ++++++++++ src/component/cyfs-bdt/src/datagram/tunnel.rs | 11 +- src/component/cyfs-bdt/src/debug/stub.rs | 1 - src/component/cyfs-bdt/src/lib.rs | 2 +- .../cyfs-bdt/src/ndn/channel/tunnel/udp.rs | 45 ++++- src/component/cyfs-bdt/src/protocol/v0.rs | 18 ++ src/component/cyfs-bdt/src/stack.rs | 8 +- .../cyfs-bdt/src/stream/package/stream.rs | 100 +++++++++- .../cyfs-bdt/src/stream/package/write.rs | 59 ++++-- .../cyfs-bdt/src/tunnel/container.rs | 3 +- src/component/cyfs-bdt/src/tunnel/tcp.rs | 5 +- src/component/cyfs-bdt/src/tunnel/tunnel.rs | 2 +- src/component/cyfs-bdt/src/tunnel/udp.rs | 6 +- 19 files changed, 554 insertions(+), 77 deletions(-) create mode 100644 src/component/cyfs-bdt/examples/pacing.rs create mode 100644 src/component/cyfs-bdt/src/cc/pacing.rs diff --git a/src/component/cyfs-bdt/examples/pacing.rs b/src/component/cyfs-bdt/examples/pacing.rs new file mode 100644 index 000000000..8b7af524d --- /dev/null +++ b/src/component/cyfs-bdt/examples/pacing.rs @@ -0,0 +1,175 @@ +use std::{ + sync::{atomic::{AtomicU64, Ordering, AtomicBool}, Mutex, Arc}, + time::{Instant, Duration}, + collections::LinkedList, + thread, +}; + +use cyfs_base::*; +use cyfs_bdt::{cc::pacing}; + +struct PacePackage { + send_time: Instant, + package_size: u64, +} +struct PackageStreamMockImpl { + pacer: Mutex, + package_queue: Arc>>, + sent_bytes: AtomicU64, + finish: AtomicBool, + end: Mutex>, + thread: Mutex>>, +} + +#[derive(Clone)] +pub struct PackageStreamMock(Arc); + +fn mss() -> usize { + 1472 +} + +impl PackageStreamMock { + pub fn new(rate: u64) -> BuckyResult { + let mut pacer = pacing::Pacer::new(true, mss()*4, mss()); + pacer.update(rate); + + let stream = Self(Arc::new(PackageStreamMockImpl { + pacer: Mutex::new(pacer), + package_queue: Arc::new(Mutex::new(Default::default())), + sent_bytes: AtomicU64::new(0), + finish: AtomicBool::new(false), + end: Mutex::new(None), + thread: Mutex::new(None), + })); + + Ok(stream) + } + + pub fn send_packages(&self, packages: Vec) -> Result<(), BuckyError> { + let mut pacer = self.0.pacer.lock().unwrap(); + let now = Instant::now(); + let mut sent_bytes = 0; + for package in packages { + if let Some(next_time) = pacer.send(package as usize, now) { + self.package_delay(package, next_time); + } else { + sent_bytes += package; + } + } + self.0.sent_bytes.fetch_add(sent_bytes, Ordering::SeqCst); + + Ok(()) + } + + pub fn package_delay(&self, package_size: u64, send_time: Instant) { + let mut package_queue = self.0.package_queue.lock().unwrap(); + package_queue.push_back(PacePackage { + send_time, + package_size, + }); + + if package_queue.len() == 1 { + let mut delay = Instant::now() - send_time; + let package_queue = self.0.package_queue.clone(); + let stream = self.clone(); + let t = thread::spawn(move || { + loop { + thread::sleep(delay); + + let now = Instant::now(); + { + let mut packages = package_queue.lock().unwrap(); + let mut n = 0; + + for (_, package) in packages.iter().enumerate() { + if package.send_time > now { + delay = package.send_time.checked_duration_since(now).unwrap(); + break ; + } + n += 1; + } + + let mut sent_bytes = 0; + while n > 0 { + if let Some(package) = packages.pop_front() { + sent_bytes += package.package_size; + } + n -= 1; + } + stream.0.sent_bytes.fetch_add(sent_bytes, Ordering::SeqCst); + + if packages.len() == 0 { + if stream.0.finish.load(Ordering::SeqCst) { + let mut end = stream.0.end.lock().unwrap(); + *end = Some(Instant::now()); + } + return true; + } + } + } + }); + + let mut thread = self.0.thread.lock().unwrap(); + *thread = Some(t); + } + } +} + +fn packages_gen(n: usize) -> Vec { + let mut packages = vec![0u64]; + + let mut n = n; + loop { + if n == 0 { + break; + } + n -= 1; + + packages.push(mss() as u64); + } + + packages +} + +fn pacing_test(data_size: usize, rate: u64) { + println!("data_size={} | {} MB, rate={} | {} KB/s", data_size, data_size/1024/1024, rate, rate/1024); + + let n = 1000; + + let stream = PackageStreamMock::new(rate).unwrap(); + + let mut num = (data_size / mss() + 1) / n + 1; + + let start = Instant::now(); + loop { + let _ = stream.send_packages(packages_gen(n)); + std::thread::sleep(Duration::from_millis(20)); + + num -= 1; + if num == 0 { + stream.0.finish.store(true, Ordering::SeqCst); + break ; + } + } + + { + let t = stream.0.thread.lock().unwrap().take(); + if let Some(thread) = t { + let _ = thread.join(); + } + } + + let end = (*stream.0.end.lock().unwrap()).unwrap(); + let cost = end.checked_duration_since(start).unwrap(); + let sent_bytes = stream.0.sent_bytes.load(Ordering::SeqCst); + + println!("cost={:?} sent_bytes={} rate={:.1} KB/s", + cost, sent_bytes, sent_bytes as f64 / 1024.0 / cost.as_secs_f64()); +} + +#[async_std::main] +async fn main() { + pacing_test(1024*1024*30, 1024*1024*3); + pacing_test(1024*1024*30, 1024*1024*7); + pacing_test(1024*1024*50, 1024*1024*9); +} \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/cc/bbr.rs b/src/component/cyfs-bdt/src/cc/bbr.rs index 9b560a170..761c85548 100644 --- a/src/component/cyfs-bdt/src/cc/bbr.rs +++ b/src/component/cyfs-bdt/src/cc/bbr.rs @@ -234,7 +234,7 @@ impl Default for Config { fn default() -> Self { Self { min_cwnd: 2, - init_cwnd: 200, + init_cwnd: 10, probe_rtt_time: Duration::from_millis(200), probe_rtt_based_on_bdp: true, drain_to_target: true, @@ -648,30 +648,32 @@ impl Bbr { impl CcImpl for Bbr { - fn cwnd(&self) -> u64 { - let cwnd_rate = (self.pacing_rate as f64) / 1000.0; + fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64) { + self.max_sent_packet_number = last_packet_number; + self.max_bandwidth.on_sent(now, bytes); + } - if self.is_at_full_bandwidth && cwnd_rate > 0.0 { - (cwnd_rate * (self.min_rtt.as_millis() as f64)) as u64 + fn cwnd(&self) -> u64 { + if self.mode == Mode::ProbeRtt { + self.get_probe_rtt_cwnd() + } else if self.recovery_state.in_recovery() + && self.mode != Mode::Startup { + self.cwnd.min(self.recovery_window) } else { - if self.mode == Mode::ProbeRtt { - self.get_probe_rtt_cwnd() - } else if self.recovery_state.in_recovery() - && self.mode != Mode::Startup { - self.cwnd.min(self.recovery_window) - } else { - self.cwnd - } + self.cwnd } } - fn on_estimate(&mut self, rtt: Duration, _rto: Duration, _delay: Duration) { - self.rtt = rtt; + fn on_estimate(&mut self, rtt: Duration, _rto: Duration, _delay: Duration, app_limited: bool) { + let now = bucky_time_now(); + + if self.is_min_rtt_expired(now, app_limited) || self.min_rtt > rtt { + self.min_rtt = rtt; + } } - fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp) { //ret cwnd + fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp, app_limited: bool) { //ret cwnd let now = bucky_time_now(); - let app_limited = false; self.max_bandwidth.on_ack( now, @@ -682,10 +684,6 @@ impl CcImpl for Bbr { ); self.acked_bytes += ack; - if self.is_min_rtt_expired(now, app_limited) || self.min_rtt > self.rtt { - self.min_rtt = self.rtt; - } - let ack_in_wnd = self.max_bandwidth.bytes_acked_this_window(); let excess_acked = self.ack_aggregation.update_ack_aggregation_bytes( ack_in_wnd, @@ -740,9 +738,13 @@ impl CcImpl for Bbr { fn on_no_resp(&mut self, rto: Duration, lost: u64) -> Duration { self.loss_state.lost_bytes += lost; - rto + rto * 2 } fn on_time_escape(&mut self, _: Timestamp) { } + + fn rate(&self) -> u64 { + self.max_bandwidth.get_estimate() + } } diff --git a/src/component/cyfs-bdt/src/cc/cc.rs b/src/component/cyfs-bdt/src/cc/cc.rs index 6cf1e22bd..b22c6a974 100644 --- a/src/component/cyfs-bdt/src/cc/cc.rs +++ b/src/component/cyfs-bdt/src/cc/cc.rs @@ -16,6 +16,7 @@ struct EstimateRtt { mdev_max: i64, //maximal m_dev for the last rtt period rttvar: i64, //smoothed m_dev_max // rtt_seq: i64, //sequence number to update rtt_var + min_rtt: i64, } impl EstimateRtt { @@ -26,6 +27,7 @@ impl EstimateRtt { mdev_max: 0, rttvar: 0, // rtt_seq: 0, + min_rtt: 0, } } @@ -35,6 +37,11 @@ impl EstimateRtt { rtt = 1; } + if self.min_rtt == 0 || + self.min_rtt > rtt { + self.min_rtt = rtt; + } + if self.srtt != 0 { rtt -= self.srtt / 8; self.srtt += rtt; @@ -111,6 +118,10 @@ impl CongestionControl { } } + pub fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64) { + self.cc.on_sent(now, bytes, last_packet_number); + } + pub fn cwnd(&self) -> u64 { self.cc.cwnd() } @@ -123,19 +134,20 @@ impl CongestionControl { self.rtt } - pub fn on_estimate(&mut self, est_rtt: Duration, est_delay: Duration) { + pub fn on_estimate(&mut self, est_rtt: Duration, est_delay: Duration, app_limited: bool) { let (rtt, rto) = self.est_rtt.update(&self.config, est_rtt); self.rto = rto; self.rtt = rtt; - self.cc.on_estimate(rtt, rto, est_delay); + self.cc.on_estimate(Duration::from_micros(self.est_rtt.min_rtt as u64), rto, est_delay, app_limited); } pub fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, - sent_time: Timestamp) { - self.cc.on_ack(flight, ack, largest_packet_num_acked, sent_time) + sent_time: Timestamp, + app_limited: bool) { + self.cc.on_ack(flight, ack, largest_packet_num_acked, sent_time, app_limited) } pub fn on_loss(&mut self, lost: u64) { @@ -150,4 +162,8 @@ impl CongestionControl { pub fn on_time_escape(&mut self, now: Timestamp) { self.cc.on_time_escape(now) } + + pub fn rate(&self) -> u64 { + self.cc.rate() + } } \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/cc/cc_impl.rs b/src/component/cyfs-bdt/src/cc/cc_impl.rs index f538c014d..fd6cc01e5 100644 --- a/src/component/cyfs-bdt/src/cc/cc_impl.rs +++ b/src/component/cyfs-bdt/src/cc/cc_impl.rs @@ -4,9 +4,11 @@ use crate::{ }; pub trait CcImpl: Send { + fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64); + fn rate(&self) -> u64; fn cwnd(&self) -> u64; - fn on_estimate(&mut self, rtt: Duration, rto: Duration, delay: Duration); - fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp); + fn on_estimate(&mut self, rtt: Duration, rto: Duration, delay: Duration, app_limited: bool); + fn on_ack(&mut self, flight: u64, ack: u64, largest_packet_num_acked: Option, sent_time: Timestamp, app_limited: bool); fn on_loss(&mut self, lost: u64); fn on_no_resp(&mut self, rto: Duration, lost: u64) -> Duration; fn on_time_escape(&mut self, now: Timestamp); diff --git a/src/component/cyfs-bdt/src/cc/ledbat.rs b/src/component/cyfs-bdt/src/cc/ledbat.rs index 4a8b66e99..1b367e8ae 100644 --- a/src/component/cyfs-bdt/src/cc/ledbat.rs +++ b/src/component/cyfs-bdt/src/cc/ledbat.rs @@ -16,6 +16,19 @@ pub struct Config { pub history_roll_interval: Duration } +impl Default for Config { + fn default() -> Self { + Self { + target_delay: Duration::from_millis(100), + min_cwnd: 2, + max_cwnd_inc: 8, + cwnd_gain: 1, + history_count: 10, + history_roll_interval: Duration::from_secs(60), + } + } +} + struct EstimateDelay { last_roll: Timestamp, base_delay: LinkedList, @@ -111,11 +124,14 @@ impl Ledbat { impl CcImpl for Ledbat { + fn on_sent(&mut self, _: Timestamp, _: u64, _: u64) { + } + fn cwnd(&self) -> u64 { self.cwnd } - fn on_estimate(&mut self, _rtt: Duration, _rto: Duration, delay: Duration) { + fn on_estimate(&mut self, _rtt: Duration, _rto: Duration, delay: Duration, _app_limited: bool) { self.est_delay.update(delay.as_micros() as i64); } @@ -124,7 +140,8 @@ impl CcImpl for Ledbat { _flight: u64, ack: u64, _largest_packet_num_acked: Option, - _sent_time: Timestamp + _sent_time: Timestamp, + _app_limited: bool ) { let cwnd = self.cwnd(); let cur_delay = self.est_delay.current_delay(); @@ -153,5 +170,9 @@ impl CcImpl for Ledbat { fn on_time_escape(&mut self, now: Timestamp) { self.est_delay.check_roll(&self.config, now); } + + fn rate(&self) -> u64 { + 0 + } } diff --git a/src/component/cyfs-bdt/src/cc/mod.rs b/src/component/cyfs-bdt/src/cc/mod.rs index c6006a10b..33069bdc9 100644 --- a/src/component/cyfs-bdt/src/cc/mod.rs +++ b/src/component/cyfs-bdt/src/cc/mod.rs @@ -1,6 +1,8 @@ mod cc_impl; mod cc; + pub mod ledbat; pub mod bbr; +pub mod pacing; pub use cc::*; diff --git a/src/component/cyfs-bdt/src/cc/pacing.rs b/src/component/cyfs-bdt/src/cc/pacing.rs new file mode 100644 index 000000000..73d217bf6 --- /dev/null +++ b/src/component/cyfs-bdt/src/cc/pacing.rs @@ -0,0 +1,93 @@ +use std::time::{Instant, Duration}; + +#[derive(Debug)] +pub struct Pacer { + capacity: usize, + used: usize, + rate: u64, + last_update: Instant, + next_time: Instant, + mss: usize, + last_packet_size: Option, + tick: Duration, + enable: bool, +} + +impl Pacer { + pub fn new(enable: bool, capacity: usize, mss: usize) -> Self { + let capacity = capacity / mss * mss; + + Pacer { + capacity, + used: 0, + rate: 0, + last_update: Instant::now(), + next_time: Instant::now(), + mss, + last_packet_size: None, + tick: Duration::ZERO, + enable, + } + } + + pub fn update(&mut self, rate: u64) { + if self.rate != rate { + self.rate = rate; + } + } + + pub fn reset(&mut self, now: Instant) { + self.used = 0; + self.last_update = now; + self.next_time = self.next_time.max(now); + self.last_packet_size = None; + self.tick = Duration::ZERO; + } + + pub fn send(&mut self, packet_size: usize, now: Instant) -> Option { + if !self.enable { + return None; + } + if self.rate == 0 { + self.reset(now); + + return None; + } + + if !self.tick.is_zero() { + self.next_time = self.next_time.max(now) + self.tick; + self.tick = Duration::ZERO; + } + + let interval = Duration::from_secs_f64(self.capacity as f64 / self.rate as f64); + + let elapsed = now.saturating_duration_since(self.last_update); + + if elapsed > interval { + self.reset(now); + } + + self.used += packet_size; + + let same_size = if let Some(last_packet_size) = self.last_packet_size { + last_packet_size == packet_size + } else { + true + }; + + self.last_packet_size = Some(packet_size); + + if self.used >= self.capacity || !same_size { + self.tick = Duration::from_secs_f64(self.used as f64 / self.rate as f64); + self.used = 0; + self.last_update = now; + self.last_packet_size = None; + }; + + if self.next_time <= now { + None + } else { + Some(self.next_time) + } + } +} diff --git a/src/component/cyfs-bdt/src/datagram/tunnel.rs b/src/component/cyfs-bdt/src/datagram/tunnel.rs index d725dc783..52406a3a7 100644 --- a/src/component/cyfs-bdt/src/datagram/tunnel.rs +++ b/src/component/cyfs-bdt/src/datagram/tunnel.rs @@ -340,12 +340,19 @@ impl DatagramTunnel { vport: u16, ) -> Result<(), std::io::Error> { let mtu = MTU; - let datagram = self.build_datagram(buf, options, remote, vport, None); - let fragment_len = datagram.fragment_len(mtu, options.plaintext); + let mut datagram = self.build_datagram(buf, options, remote, vport, None); + let mut fragment_len = datagram.fragment_len(mtu, options.plaintext); if fragment_len == 0 { self.send_datagram(datagram, remote, options.plaintext) } else { + if options.sequence.is_none() { + let seq = self.0.sequence.generate(); + options.sequence = Some(seq); + datagram.sequence = Some(seq); + fragment_len = datagram.fragment_len(mtu, options.plaintext); + } + let count = (buf.len() as f64 / fragment_len as f64).ceil() as u8; let mut start = 0; let mut end = fragment_len; diff --git a/src/component/cyfs-bdt/src/debug/stub.rs b/src/component/cyfs-bdt/src/debug/stub.rs index b6315c236..8c7289566 100644 --- a/src/component/cyfs-bdt/src/debug/stub.rs +++ b/src/component/cyfs-bdt/src/debug/stub.rs @@ -533,7 +533,6 @@ async fn watchdog_download_finished(task: Box, timeout: u32) - NdnTaskState::Finished => { break Ok(()); }, - NdnTaskState::Running => { if task.cur_speed() > 0 { i = 0; diff --git a/src/component/cyfs-bdt/src/lib.rs b/src/component/cyfs-bdt/src/lib.rs index 86491ce43..273b0a139 100644 --- a/src/component/cyfs-bdt/src/lib.rs +++ b/src/component/cyfs-bdt/src/lib.rs @@ -9,7 +9,7 @@ mod finder; pub mod sn; pub mod tunnel; pub mod pn; -mod cc; +pub mod cc; mod stream; mod datagram; mod dht; diff --git a/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs b/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs index ffa3bee6e..3c98312da 100644 --- a/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs +++ b/src/component/cyfs-bdt/src/ndn/channel/tunnel/udp.rs @@ -1,8 +1,8 @@ use log::*; use std::{ collections::{LinkedList}, - time::{Duration}, - cell::RefCell, + time::{Duration, Instant}, + cell::RefCell, sync::Mutex }; use async_std::{ @@ -70,6 +70,11 @@ struct RespEstimateStub { recved: u64, } +struct PacePackage { + send_time: Instant, + data: Vec, +} + struct TunnelImpl { config: channel::Config, raw_tunnel: RawTunnel, @@ -77,7 +82,8 @@ struct TunnelImpl { active_timestamp: Timestamp, cc: Mutex, resp_estimate: Mutex, - uploaders: Uploaders + uploaders: Uploaders, + package_queue: Arc>>, } #[derive(Clone)] @@ -105,7 +111,8 @@ impl UdpTunnel { seq: TempSeq::default(), recved: 0 }), - uploaders: Uploaders::new() + uploaders: Uploaders::new(), + package_queue: Arc::new(Mutex::new(Default::default())), })) } @@ -131,6 +138,8 @@ impl UdpTunnel { let mut pre_buf_index: Option = None; let mut sent = 0; let tunnel = &self.0.raw_tunnel; + let mut send_bytes = 0; + let mut last_est_seq = TempSeq::default(); for _ in 0..piece_count { let mut buf_index = if let Some(bi) = &pre_buf_index { if bi.index == 0 { @@ -149,7 +158,9 @@ impl UdpTunnel { buf_index.len = piece_len; if pre_buf_index.is_some() { std::mem::swap(pre_buf_index.as_mut().unwrap(), &mut buf_index); - let _ = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]); + if let Ok(size) = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]) { + send_bytes += size; + } } else { pre_buf_index = Some(buf_index); } @@ -172,7 +183,16 @@ impl UdpTunnel { }; debug!("{} send estimate sequence:{:?} sent:{}", self, est_seq, sent); PieceData::reset_estimate(&mut buffers[buf_index.index][tunnel.raw_data_header_len()..], est_seq); - let _ = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]); + last_est_seq = est_seq; + + if let Ok(size) = tunnel.send_raw_data(&mut buffers[buf_index.index][..buf_index.len + tunnel.raw_data_header_len()]) { + send_bytes += size; + } + } + + { + let mut cc = self.0.cc.lock().unwrap(); + cc.cc.on_sent(bucky_time_now(), send_bytes as u64, last_est_seq.value() as u64); } }) }); @@ -231,7 +251,8 @@ impl ChannelTunnel for UdpTunnel { self, est_seq ); - let _ = tunnel.send_raw_data(&mut buffer[..]); + if let Ok(_) = tunnel.send_raw_data(&mut buffer[..]) { + } } } else { let mut est_stub = self.0.resp_estimate.lock().unwrap(); @@ -252,7 +273,7 @@ impl ChannelTunnel for UdpTunnel { let rtt = Duration::from_micros(bucky_time_now() - stub.send_time); let delay = rtt / 2; - cc.cc.on_estimate(rtt, delay); + cc.cc.on_estimate(rtt, delay, false); debug!("{} estimate rtt:{:?} delay:{:?} rto:{:?}", self, rtt, delay, cc.cc.rto()); est_index = Some(cc.est_stubs.len() - 1 - index); @@ -265,8 +286,10 @@ impl ChannelTunnel for UdpTunnel { let mut resp_count = 0; let est_stubs = cc.est_stubs.split_off(est_index + 1); + let mut send_time = 0; for stub in &cc.est_stubs { resp_count += stub.sent; + send_time = stub.send_time; } cc.est_stubs = est_stubs; @@ -276,11 +299,13 @@ impl ChannelTunnel for UdpTunnel { debug!("{} cc on ack on_air:{}, ack:{}", self, on_air, resp_count); cc.no_resp_counter = 0; cc.break_counter = 0; + cc.cc.on_ack( (on_air * PieceData::max_payload()) as u64, (resp_count * PieceData::max_payload()) as u64, - None, - bucky_time_now()); + Some(est_index as u64), + send_time, + false); } Ok(()) diff --git a/src/component/cyfs-bdt/src/protocol/v0.rs b/src/component/cyfs-bdt/src/protocol/v0.rs index c38540a8b..69f3a88e0 100644 --- a/src/component/cyfs-bdt/src/protocol/v0.rs +++ b/src/component/cyfs-bdt/src/protocol/v0.rs @@ -970,6 +970,24 @@ impl SessionData { id_part: None, } } + + pub fn is_ctrl_package(&self) -> bool { + if self.is_syn() || + self.is_syn_ack() || + self.is_flags_contain(SESSIONDATA_FLAG_ACK_PACKAGEID) || + self.is_flags_contain(SESSIONDATA_FLAG_FIN) || + self.is_flags_contain(SESSIONDATA_FLAG_FINACK) || + self.is_flags_contain(SESSIONDATA_FLAG_RESET) { + true + } else { + false + } + } + + pub fn data_size(&self) -> usize { + self.payload.as_ref().len() + } + pub fn is_syn(&self) -> bool { self.syn_info.is_some() && (self.flags & SESSIONDATA_FLAG_ACK == 0) } diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index 1d038f7af..a20becf1a 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -122,10 +122,10 @@ impl StackConfig { listener: stream::listener::Config { backlog: 100 }, stream: stream::container::Config { nagle: Duration::from_millis(0), - recv_buffer: 1024 * 256, + recv_buffer: 1024 * 1024, recv_timeout: Duration::from_millis(200), drain: 0.5, - send_buffer: 1024 * 256, // 这个值不能小于下边的max_record + send_buffer: 1024 * 512, // 这个值不能小于下边的max_record retry_sn_timeout: Duration::from_secs(2), connect_timeout: Duration::from_secs(5), tcp: stream::tcp::Config { @@ -134,7 +134,7 @@ impl StackConfig { }, package: stream::package::Config { connect_resend_interval: Duration::from_millis(100), - atomic_interval: Duration::from_millis(1), + atomic_interval: Duration::from_millis(10), break_overtime: Duration::from_secs(60), msl: Duration::from_secs(60), cc: cc::Config { @@ -170,7 +170,7 @@ impl StackConfig { cc: cc::Config { init_rto: Duration::from_secs(1), min_rto: Duration::from_millis(200), - cc_impl: cc::ImplConfig::BBR(Default::default()), + cc_impl: cc::ImplConfig::Ledbat(Default::default()), } }, history_speed: HistorySpeedConfig { diff --git a/src/component/cyfs-bdt/src/stream/package/stream.rs b/src/component/cyfs-bdt/src/stream/package/stream.rs index 58e76fea8..6377f237b 100644 --- a/src/component/cyfs-bdt/src/stream/package/stream.rs +++ b/src/component/cyfs-bdt/src/stream/package/stream.rs @@ -1,12 +1,14 @@ use log::*; use std::{ - time::Duration, + time::{Duration, Instant}, task::{Context, Poll}, + sync::Mutex, + collections::LinkedList, }; use async_std::{ sync::Arc, task, - future + future, }; use async_trait::{async_trait}; use cyfs_base::*; @@ -22,7 +24,7 @@ use super::super::{ stream_provider::{Shutdown, StreamProvider}}; use super::{ write::WriteProvider, - read::ReadProvider + read::ReadProvider, }; #[derive(Clone)] @@ -34,14 +36,21 @@ pub struct Config { pub cc: cc::Config } +struct PacePackage { + send_time: Instant, + package: DynamicPackage, +} + struct PackageStreamImpl { config: super::super::container::Config, owner_disp: String, tunnel: UdpTunnel, - local_id: IncreaseId, + local_id: IncreaseId, remote_id: IncreaseId, write_provider: WriteProvider, - read_provider: ReadProvider + read_provider: ReadProvider, + pacer: Mutex, + package_queue: Arc>>, } #[derive(Clone)] @@ -66,6 +75,7 @@ impl PackageStream { ) -> BuckyResult { let owner_disp = format!("{}", owner); let config = tunnel.stack().config().stream.stream.clone(); + let pacer_enable = false; let write_provider = WriteProvider::new(&config); let read_provider = ReadProvider::new(&config); @@ -76,7 +86,9 @@ impl PackageStream { local_id, remote_id, write_provider, - read_provider + read_provider, + pacer: Mutex::new(cc::pacing::Pacer::new(pacer_enable, PackageStream::mss() * 10, PackageStream::mss())), + package_queue: Arc::new(Mutex::new(Default::default())), })); Ok(stream) @@ -94,6 +106,40 @@ impl PackageStream { &self.0.read_provider } + fn package_delay(&self, package: DynamicPackage, send_time: Instant) { + let mut package_queue = self.0.package_queue.lock().unwrap(); + package_queue.push_back(PacePackage { + send_time, + package, + }); + } + + fn drain_delay(&self) { + let now = Instant::now(); + let mut package_queue = self.0.package_queue.lock().unwrap(); + let mut n = 0; + for (_, package) in package_queue.iter().enumerate() { + if package.send_time > now { + break ; + } + n += 1; + } + + while n > 0 { + if let Some(package) = package_queue.pop_front() { + match self.0.tunnel.send_package(package.package) { + Ok(sent_len) => { + trace!("package_delay send_package {}", sent_len); + }, + Err(err) => { + error!("stream send_package err={}", err); + } + } + } + n -= 1; + } + } + pub fn send_packages(&self, packages: Vec) -> Result<(), BuckyError> { if packages.len() == 0 { return Ok(()); @@ -117,9 +163,39 @@ impl PackageStream { // trace!("{} will send session data package {}", self, session_data); } - for package in packages { - let _ = self.0.tunnel.send_package(package); + let mut sent_bytes = 0; + let mut last_packet_number = 0; + { + let mut pacer = self.0.pacer.lock().unwrap(); + let now = Instant::now(); + for package in packages { + let session_data: & SessionData = package.as_ref(); + if !session_data.is_ctrl_package() || !session_data.is_flags_contain(SESSIONDATA_FLAG_ACK) { + let package_size = session_data.data_size(); + if let Some(next_time) = pacer.send(package_size, now) { + sent_bytes += package_size; + + self.package_delay(package, next_time); + continue; + } + last_packet_number = session_data.send_time; + } + + match self.0.tunnel.send_package(package) { + Ok(sent_len) => { + sent_bytes += sent_len; + }, + Err(err) => { + error!("stream send_package err={}", err); + } + } + } + } + + if sent_bytes > 0 { + self.write_provider().on_sent(sent_bytes as u64, last_packet_number); } + Ok(()) } } @@ -158,6 +234,7 @@ impl StreamProvider for PackageStream { break; } let _ = stream.send_packages(packages); + stream.drain_delay(); let _ = future::timeout(stream.config().package.atomic_interval, future::pending::<()>()).await; } }); @@ -238,7 +315,14 @@ impl OnPackage for PackageStream { _ => unreachable!() } }; + + { + let mut pacer = self.0.pacer.lock().unwrap(); + pacer.update(self.write_provider().rate()); + } + let _ = self.send_packages(packages); + Ok(r) } } diff --git a/src/component/cyfs-bdt/src/stream/package/write.rs b/src/component/cyfs-bdt/src/stream/package/write.rs index 132acaef0..59ea4935e 100644 --- a/src/component/cyfs-bdt/src/stream/package/write.rs +++ b/src/component/cyfs-bdt/src/stream/package/write.rs @@ -32,13 +32,16 @@ struct WriteProviderImpl { est_stubs: LinkedList, est_id: IncreaseIdGenerator, last_recv: Timestamp, - cc: CongestionControl + cc: CongestionControl, + app_limited: bool, } impl WriteProviderImpl { fn check_wnd(&mut self, stream: &PackageStream, now: Timestamp, timeout: Duration, packages: &mut Vec, logging: bool) { self.queue.check_wnd(stream, now, timeout, self.cc.cwnd(), packages, logging); self.on_pre_send_package(stream, packages); + + self.app_limited = packages.len() == 0; } fn on_time_escape(&mut self, stream: &PackageStream, now: Timestamp, packages: &mut Vec) -> BuckyResult<()> { @@ -46,19 +49,23 @@ impl WriteProviderImpl { let nagle = self.queue.check_nagle(stream, now); let (lost, _break) = if self.queue.flight() > 0 { let lost = self.queue.check_timeout(now, self.cc.rto()); - if lost >= self.queue.flight() { - let d = Duration::from_micros(now - self.last_recv); - if d > stream.config().package.break_overtime { - (true, true) + if lost > 0 { + if lost >= self.queue.flight() { + let d = Duration::from_micros(now - self.last_recv); + if d > stream.config().package.break_overtime { + (true, true) + } else { + debug!("{} cc no ack in rto, lost={}", stream, lost); + self.cc.on_no_resp(lost as u64); + (true, false) + } } else { - debug!("{} cc no ack in rto", stream); - self.cc.on_no_resp(lost as u64); + debug!("{} cc lost some package's ack, lost={}", stream, lost); + self.cc.on_loss(lost as u64); (true, false) } } else { - debug!("{} cc lost some package's ack", stream); - self.cc.on_loss(lost as u64); - (true, false) + (false, false) } } else { (false, false) @@ -119,7 +126,8 @@ impl WriteProvider { est_id: IncreaseIdGenerator::new(), est_stubs: LinkedList::new(), last_recv: bucky_time_now(), - cc: CongestionControl::new(PackageStream::mss(), &config.package.cc) + cc: CongestionControl::new(PackageStream::mss(), &config.package.cc), + app_limited: false, }))) } @@ -234,6 +242,28 @@ impl WriteProvider { result } + pub fn on_sent(&self, sent_bytes: u64, last_packet_number: u64) { + let state = &mut *cyfs_debug::lock!(self.0).unwrap(); + match state { + WriteProviderState::Open(provider) => { + provider.cc.on_sent(bucky_time_now(), sent_bytes, last_packet_number); + } + _ => {} + } + } + + pub fn rate(&self) -> u64 { + let state = &mut *cyfs_debug::lock!(self.0).unwrap(); + match state { + WriteProviderState::Open(provider) => { + provider.cc.rate() + } + _ => { + 0 + } + } + } + pub fn reset(&self, stream: &PackageStream) { let waiters = { let mut waiters = LinkedList::new(); @@ -282,7 +312,7 @@ impl OnPackage)> for Writ if sample.id == package_id { let rtt = Duration::from_micros(bucky_time_now() - sample.send_time); let delay = rtt / 2; - provider.cc.on_estimate(rtt, delay); + provider.cc.on_estimate(rtt, delay, provider.app_limited); debug!("{} estimate rtt:{:?} delay:{:?} rto:{:?}", stream, rtt, delay, provider.cc.rto()); to_remove = Some(index); break; @@ -312,8 +342,9 @@ impl OnPackage)> for Writ trace!("{} newly ack {} to {}", stream, newly_acked, provider.queue.start()); provider.cc.on_ack(provider.queue.flight() as u64, newly_acked as u64, - Some(newly_acked as u64), - bucky_time_now()); + Some(session_data.send_time), + bucky_time_now(), + provider.app_limited); debug!("{} update cwnd: {}", stream, provider.cc.cwnd()); provider.check_wnd(stream, now, provider.cc.rto(), &mut packages, false); diff --git a/src/component/cyfs-bdt/src/tunnel/container.rs b/src/component/cyfs-bdt/src/tunnel/container.rs index 721b23d51..6c5edc03f 100644 --- a/src/component/cyfs-bdt/src/tunnel/container.rs +++ b/src/component/cyfs-bdt/src/tunnel/container.rs @@ -289,7 +289,8 @@ impl TunnelContainer { Ok(()) } else { let tunnel = self.default_tunnel()?; - tunnel.as_ref().send_package(package) + let _ = tunnel.as_ref().send_package(package)?; + Ok(()) } } diff --git a/src/component/cyfs-bdt/src/tunnel/tcp.rs b/src/component/cyfs-bdt/src/tunnel/tcp.rs index d747619f6..2b675e35b 100644 --- a/src/component/cyfs-bdt/src/tunnel/tcp.rs +++ b/src/component/cyfs-bdt/src/tunnel/tcp.rs @@ -1022,7 +1022,7 @@ impl tunnel::Tunnel for Tunnel { } } - fn send_package(&self, package: DynamicPackage) -> Result<(), BuckyError> { + fn send_package(&self, package: DynamicPackage) -> Result { if package.cmd_code() == PackageCmdCode::SessionData { return Err(BuckyError::new(BuckyErrorCode::UnSupport, "session data should not send from tcp tunnel")); } @@ -1043,7 +1043,8 @@ impl tunnel::Tunnel for Tunnel { if to_connect { let _ = self.connect(); } - Ok(()) + + Ok(0) } fn raw_data_header_len(&self) -> usize { diff --git a/src/component/cyfs-bdt/src/tunnel/tunnel.rs b/src/component/cyfs-bdt/src/tunnel/tunnel.rs index 213033205..474ed8444 100644 --- a/src/component/cyfs-bdt/src/tunnel/tunnel.rs +++ b/src/component/cyfs-bdt/src/tunnel/tunnel.rs @@ -34,7 +34,7 @@ pub trait Tunnel: Send + Sync + std::fmt::Display { fn remote(&self) -> &Endpoint; fn state(&self) -> TunnelState; fn proxy(&self) -> ProxyType; - fn send_package(&self, packages: protocol::DynamicPackage) -> Result<(), BuckyError>; + fn send_package(&self, packages: protocol::DynamicPackage) -> Result; fn raw_data_header_len(&self) -> usize; fn send_raw_data(&self, data: &mut [u8]) -> Result; fn ptr_eq(&self, other: &DynamicTunnel) -> bool; diff --git a/src/component/cyfs-bdt/src/tunnel/udp.rs b/src/component/cyfs-bdt/src/tunnel/udp.rs index f027e055f..8d5bc5c99 100644 --- a/src/component/cyfs-bdt/src/tunnel/udp.rs +++ b/src/component/cyfs-bdt/src/tunnel/udp.rs @@ -356,7 +356,7 @@ impl tunnel::Tunnel for Tunnel { interface.send_raw_data_to(&key, data, tunnel::Tunnel::remote(self)) } - fn send_package(&self, package: DynamicPackage) -> Result<(), BuckyError> { + fn send_package(&self, package: DynamicPackage) -> Result { let (tunnel_container, interface, key) = { if let TunnelState::Active(active_state) = &*self.0.state.read().unwrap() { Ok((active_state.container.clone(), active_state.interface.clone(), active_state.key.clone())) @@ -367,8 +367,8 @@ impl tunnel::Tunnel for Tunnel { let package_box = PackageBox::from_package(tunnel_container.remote().clone(), key, package); let mut context = PackageBoxEncodeContext::default(); context.set_ignore_exchange(ProxyType::None != self.0.proxy); - interface.send_box_to(&mut context, &package_box, tunnel::Tunnel::remote(self))?; - Ok(()) + let sent_len = interface.send_box_to(&mut context, &package_box, tunnel::Tunnel::remote(self))?; + Ok(sent_len) } fn retain_keeper(&self) { From d8a9f65fbaead844788c85081191957ab1e8bc82 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 19:14:24 +0800 Subject: [PATCH 322/553] Fix usage of lru cache in meta relate cache --- src/component/cyfs-meta-lib/src/helper.rs | 3 +++ src/component/cyfs-stack/src/meta/cache.rs | 6 +++++- src/component/cyfs-stack/src/meta/fail_cache.rs | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-meta-lib/src/helper.rs b/src/component/cyfs-meta-lib/src/helper.rs index 55288f375..9db23db71 100644 --- a/src/component/cyfs-meta-lib/src/helper.rs +++ b/src/component/cyfs-meta-lib/src/helper.rs @@ -108,6 +108,9 @@ impl MetaClientHelperWithObjectCache { object_id: &ObjectId, ) -> BuckyResult>> { let mut list = self.objects.lock().await; + // force remove expired items + list.iter(); + if let Some(item) = list.peek(object_id) { return Ok(item.into_object_raw()); } diff --git a/src/component/cyfs-stack/src/meta/cache.rs b/src/component/cyfs-stack/src/meta/cache.rs index 74e36cf1a..48b311bcb 100644 --- a/src/component/cyfs-stack/src/meta/cache.rs +++ b/src/component/cyfs-stack/src/meta/cache.rs @@ -46,7 +46,11 @@ where Key: Borrow, Q: Ord, { - self.list.get(&key).map(|v| v.value.clone()) + // force remove expired items + self.list.iter(); + + // do not update the last used timestamp + self.list.peek(&key).map(|v| v.value.clone()) } } diff --git a/src/component/cyfs-stack/src/meta/fail_cache.rs b/src/component/cyfs-stack/src/meta/fail_cache.rs index b0b16c468..c6c9d6188 100644 --- a/src/component/cyfs-stack/src/meta/fail_cache.rs +++ b/src/component/cyfs-stack/src/meta/fail_cache.rs @@ -97,7 +97,11 @@ impl MetaFailCacheImpl { pub fn get(&mut self, key: &MetaCacheKey) -> Option { // 首先查询是不是存在缓存 - let ret = self.list.get(&key).map(|v| v.error.clone()); + // force remove expired items + self.list.iter(); + + // use peek instead of get, do not update the last use timestamp! + let ret = self.list.peek(&key).map(|v| v.error.clone()); if ret.is_some() { return ret; } From c8f785867f3d522226c15e81aadf7eb61e61cf4c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 24 Feb 2023 19:55:32 +0800 Subject: [PATCH 323/553] Fix usage of lru cache in failed relate cache --- .../cyfs-stack/src/ndn_api/bdt/cache.rs | 9 +++- src/component/cyfs-stack/src/resolver/mod.rs | 1 - .../cyfs-stack/src/resolver/ood_cache.rs | 51 ------------------- .../src/root_state_api/validate/cache.rs | 5 +- .../cyfs-stack/src/zone/failed_cache.rs | 21 ++++++-- 5 files changed, 27 insertions(+), 60 deletions(-) delete mode 100644 src/component/cyfs-stack/src/resolver/ood_cache.rs diff --git a/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs b/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs index eea8b7356..bf6af0af5 100644 --- a/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs +++ b/src/component/cyfs-stack/src/ndn_api/bdt/cache.rs @@ -24,7 +24,8 @@ pub(super) struct BdtDataAclCache { impl BdtDataAclCache { pub fn new() -> Self { - let list = LruCache::with_expiry_duration(std::time::Duration::from_secs(60 * 5)); + let list = LruCache::with_expiry_duration_and_capacity( + std::time::Duration::from_secs(60 * 5), 256); Self { list: Arc::new(Mutex::new(list)), @@ -45,6 +46,10 @@ impl BdtDataAclCache { pub fn get(&self, key: &BdtDataAclCacheKey) -> Option> { let mut list = self.list.lock().unwrap(); - list.get(&key).map(|v| v.result.clone()) + + // force remove expired items + list.iter(); + + list.peek(&key).map(|v| v.result.clone()) } } diff --git a/src/component/cyfs-stack/src/resolver/mod.rs b/src/component/cyfs-stack/src/resolver/mod.rs index 95929bcdd..e7a24f064 100644 --- a/src/component/cyfs-stack/src/resolver/mod.rs +++ b/src/component/cyfs-stack/src/resolver/mod.rs @@ -1,7 +1,6 @@ mod device_manager; mod obj_searcher; mod ood_resolver; -mod ood_cache; pub(crate) use device_manager::*; pub(crate) use obj_searcher::*; diff --git a/src/component/cyfs-stack/src/resolver/ood_cache.rs b/src/component/cyfs-stack/src/resolver/ood_cache.rs deleted file mode 100644 index 87baf1d62..000000000 --- a/src/component/cyfs-stack/src/resolver/ood_cache.rs +++ /dev/null @@ -1,51 +0,0 @@ -use cyfs_base::*; - -use lru_time_cache::{Entry, LruCache}; -use std::sync::Arc; -use std::time::Duration; -use cyfs_debug::Mutex; - -#[derive(Clone)] -pub struct OodInfo { - pub ood_list: Vec, -} - -pub(super) struct OodCache { - list: Arc>>, -} - -impl OodCache { - pub fn new() -> Self { - let list = - LruCache::with_expiry_duration_and_capacity(Duration::from_secs(3600 * 24 * 7), 1024); - - Self { - list: Arc::new(Mutex::new(list)), - } - } - - pub fn add(&self, object_id: &ObjectId, ood_list: Vec) { - match self.list.lock().unwrap().entry(object_id.clone()) { - Entry::Occupied(v) => { - info!("will replace resolved ood list: {}", object_id); - (*v.into_mut()).ood_list = ood_list; - } - Entry::Vacant(v) => { - info!("will save resolved ood list: {}, {:?}", object_id, ood_list); - let item = OodInfo { ood_list }; - - v.insert(item); - } - } - } - - pub fn get(&mut self, object_id: &ObjectId) -> Option> { - let mut list = self.list.lock().unwrap(); - let info = list.get(object_id); - if info.is_none() { - return None; - } - - Some(info.unwrap().ood_list.clone()) - } -} diff --git a/src/component/cyfs-stack/src/root_state_api/validate/cache.rs b/src/component/cyfs-stack/src/root_state_api/validate/cache.rs index 826d2bbcb..35b7aaf65 100644 --- a/src/component/cyfs-stack/src/root_state_api/validate/cache.rs +++ b/src/component/cyfs-stack/src/root_state_api/validate/cache.rs @@ -37,7 +37,10 @@ impl GlobalStatePathCacheInner { return Ok(ret.cloned()); } - if let Some(item) = self.failed_cache.get(key) { + // force remove expired items + self.failed_cache.iter(); + + if let Some(item) = self.failed_cache.peek(key) { return Err(item.error.clone()); } diff --git a/src/component/cyfs-stack/src/zone/failed_cache.rs b/src/component/cyfs-stack/src/zone/failed_cache.rs index d7ed23c3f..27c3ea988 100644 --- a/src/component/cyfs-stack/src/zone/failed_cache.rs +++ b/src/component/cyfs-stack/src/zone/failed_cache.rs @@ -30,10 +30,13 @@ impl OrphanZoneCache { } pub fn get_by_device(&mut self, device_id: &DeviceId) -> Option { - let ret = self.device_list.get(device_id); + // force remove expired items + self.device_list.iter(); + self.zone_list.iter(); + + let ret = self.device_list.peek(device_id); match ret { Some(v) => { - self.zone_list.get(&v.zone_id); Some(v.zone.clone()) } None => None, @@ -41,9 +44,13 @@ impl OrphanZoneCache { } pub fn get(&mut self, zone_id: &ZoneId) -> Option { - let ret = self.zone_list.get(zone_id); + // force remove expired items + self.device_list.iter(); + self.zone_list.iter(); + + let ret = self.zone_list.peek(zone_id); match ret { - Some(device_id) => self.device_list.get(device_id).map(|v| v.zone.clone()), + Some(device_id) => self.device_list.peek(device_id).map(|v| v.zone.clone()), None => None, } } @@ -93,7 +100,11 @@ impl ZoneFailedCache { pub fn get_failed_owner(&self, object_id: &ObjectId) -> Option { let mut cache = self.owner_cache.lock().unwrap(); - cache.get(object_id).map(|v| v.clone()) + + // force remove expired items + cache.iter(); + + cache.peek(object_id).map(|v| v.clone()) } // device搜寻zone失败,创建孤儿zone并缓存 From 43e8b988413afab26d6bc779fc6b58e25218afc6 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 20:37:21 +0800 Subject: [PATCH 324/553] Perf-client can use in cyfs-stack --- src/component/cyfs-lib/src/root_state/stub.rs | 2 +- .../cyfs-perf/cyfs-perf-client/src/reporter.rs | 10 +++++----- src/tests/cyfs-stack-test/src/case/perf.rs | 17 ++++++++++++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-lib/src/root_state/stub.rs b/src/component/cyfs-lib/src/root_state/stub.rs index 3577f4ca2..bb56ca3b5 100644 --- a/src/component/cyfs-lib/src/root_state/stub.rs +++ b/src/component/cyfs-lib/src/root_state/stub.rs @@ -338,7 +338,7 @@ pub struct PathOpEnvStub { } impl PathOpEnvStub { - pub(crate) fn new( + pub fn new( processor: OpEnvOutputProcessorRef, target: Option, target_dec_id: Option, diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index 8a7592b55..9a83fe7af 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -184,10 +184,11 @@ impl PerfReporterInner { } // 把obj再put出去 + let target = if save_to_local { None } else { target }; let mut req = NONPutObjectOutputRequest::new( if save_to_local { NONAPILevel::NOC } else { NONAPILevel::Router }, object_id.clone(), raw); - req.common.target = if save_to_local { None } else { target }; + req.common.target = target.clone(); req.common.dec_id = obj.desc().dec_id().clone(); let str_target = if save_to_local { "local".to_owned() } else {target.map_or("ood".to_owned(), |id| id.to_string())}; match self.cyfs_stack.non_service().put_object(req).await { @@ -203,12 +204,11 @@ impl PerfReporterInner { // 存到root_state let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); - req.access = access; - req.common.target = self.target.clone(); - req.common.target_dec_id = self.target_dec_id.clone(); + req.common.target = target.clone(); + req.common.target_dec_id = self.dec_id.clone(); let resp = self.cyfs_stack.root_state().create_op_env(req).await?; - let path_env = PathOpEnvStub::new(resp, self.target.clone(), self.target_dec_id.clone()); + let path_env = PathOpEnvStub::new(resp, target.clone(), self.dec_id.clone()); let key = obj.get_time_range().to_string(); path_env.set_with_key("/stat", key, &object_id, None, true).await?; path_env.commit().await?; diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index f79043ee6..49ba595b8 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -1,6 +1,7 @@ +use std::time::Duration; use cyfs_base::*; use cyfs_core::*; -use cyfs_perf_client::{PerfClient, PerfIsolate, PerfServerConfig}; +use cyfs_perf_client::{PerfClient, PerfConfig, PerfIsolate, PerfServerConfig}; use zone_simulator::*; fn new_dec(name: &str) -> ObjectId { @@ -16,13 +17,23 @@ fn new_dec(name: &str) -> ObjectId { pub async fn test() { let dec_id = new_dec("test-perf"); let stack = TestLoader::get_shared_stack(DeviceIndex::User1Device2); + stack.online().await; + let device = stack.local_device(); + let owner = device.desc().owner().as_ref().unwrap().clone(); + let device_id = device.desc().device_id(); let perf = PerfClient::new( "test-perf".to_owned(), "1.0.0".to_owned(), Some(dec_id), - PerfServerConfig::Default, - stack, + PerfConfig { + reporter: PerfServerConfig::Default, + save_to_file: false, + report_interval: Duration::from_secs(60*10), + }, + stack.uni_stack().clone(), + device_id, + owner ); let ret = perf.start().await; From 1bdd0073c534cbff490ac6acc7607c78fa5bbfda Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 21:41:54 +0800 Subject: [PATCH 325/553] Fix app-manager compile error --- src/service/app-manager/src/dapp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index 012b5d26a..628de11f7 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -45,7 +45,7 @@ fn get_str(value: &Value, key: &str) -> BuckyResult { impl Drop for DApp { fn drop(&mut self) { - if let Some(mut child) = self.process.lock().unwrap().as_ref() { + if let Some(child) = self.process.lock().unwrap().as_mut() { warn!("dapp {} dropped when child process start! pid {}", &self.dec_id, child.id()); child.kill(); child.wait(); @@ -244,9 +244,9 @@ impl DApp { pub fn start(&self) -> BuckyResult { if !self.status()? { let child = DApp::run(&self.info.start, &self.work_dir, true, None)?; + let id = child.id(); *self.process.lock().unwrap() = Some(child); // mark pid - let id = child.id(); let lock_file = self.get_pid_file_path()?; let buf = format!("{}", id).into_bytes(); std::fs::write(lock_file, &buf).map_err(|e| { From f14fce1666eb5b72095f4710f6d54b72e1178bc7 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Sat, 25 Feb 2023 15:47:24 +0800 Subject: [PATCH 326/553] Change old-chunk-client`s get header timeout to 30 secs, DecApp Install Command timeout to 15 mins, remove app-manager`s intermediate state`s timeout --- src/service/app-manager/src/app_manager_ex.rs | 51 ------------------- src/service/app-manager/src/dapp.rs | 2 +- .../cyfs-chunk-client/src/chunk_request.rs | 2 +- 3 files changed, 2 insertions(+), 53 deletions(-) diff --git a/src/service/app-manager/src/app_manager_ex.rs b/src/service/app-manager/src/app_manager_ex.rs index 0175f6501..7da7d0be5 100644 --- a/src/service/app-manager/src/app_manager_ex.rs +++ b/src/service/app-manager/src/app_manager_ex.rs @@ -431,8 +431,6 @@ impl AppManager { } /* 根据local_status检查app状态 - Starting,Stopping,Installing,Uninstalling为中间状态, - 处于此种状态超过一定时间(STATUS_LASTED_TIME_LIMIT_IN_MICROS 10分钟)会进入错误状态。 已经入错误状态的app不用管。等下一个命令纠正它。 已经入Running状态的app要确保它正在运行。 除Running状态的其他非中间状态,不用管。 @@ -452,55 +450,6 @@ impl AppManager { self.check_running_app(&app_id, status.clone()).await; continue; } - - let mut status_clone = None; - { - //要在锁里操作,因为执行器也可能改变App的状态 - let mut status = status.lock().unwrap(); - let status_code = status.status(); - let status_lasted_time = bucky_time_now() - status.last_status_update_time(); - let is_lasted_exceeds_limit = - status_lasted_time > STATUS_LASTED_TIME_LIMIT_IN_MICROS; - let mut target_status_code = None; - if is_lasted_exceeds_limit { - //中间状态超过持续时间,认为失败 - match status_code { - AppLocalStatusCode::Starting => { - target_status_code = Some(AppLocalStatusCode::StartFailed); - } - AppLocalStatusCode::Stopping => { - target_status_code = Some(AppLocalStatusCode::StopFailed); - } - AppLocalStatusCode::Installing => { - target_status_code = Some(AppLocalStatusCode::InstallFailed); - } - AppLocalStatusCode::Uninstalling => { - target_status_code = Some(AppLocalStatusCode::UninstallFailed); - } - _ => { - //info!("check status pass, app:{}, status: {}", app_id, v); - } - } - } - - match target_status_code { - Some(target_status) => { - info!( - "[STATUS CHECK] will change status by checker, app:{}, from [{}] to [{}], is lasted exceeds limit: {}", - app_id, status_code, target_status, is_lasted_exceeds_limit - ); - - status.set_status(target_status); - status_clone = Some(status.clone()); - } - None => { - info!("check status pass, app:{}, status: {}", app_id, status_code); - } - } - } - if let Some(new_status) = status_clone { - let _ = self.non_helper.put_local_status(&new_status).await; - } } } diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index 628de11f7..9f3e52df7 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -14,7 +14,7 @@ use wait_timeout::ChildExt; const STATUS_CMD_TIME_OUT_IN_SECS: u64 = 15; const STOP_CMD_TIME_OUT_IN_SECS: u64 = 60; const START_CMD_TIME_OUT_IN_SECS: u64 = 5 * 60; -const INSTALL_CMD_TIME_OUT_IN_SECS: u64 = 10 * 60; +const INSTALL_CMD_TIME_OUT_IN_SECS: u64 = 15 * 60; #[derive(Deserialize, Clone)] pub struct DAppInfo { diff --git a/src/tools/cyfs-chunk-client/src/chunk_request.rs b/src/tools/cyfs-chunk-client/src/chunk_request.rs index d00aca7b6..9769b29eb 100644 --- a/src/tools/cyfs-chunk-client/src/chunk_request.rs +++ b/src/tools/cyfs-chunk-client/src/chunk_request.rs @@ -7,7 +7,7 @@ pub async fn process_req(req: Request, stream: RW) -> BuckyResult where RW: Read + Write + Send + Sync + Unpin + 'static, { - let resp = cyfs_util::async_h1_helper::connect_timeout(stream, req,std::time::Duration::from_secs(60 * 5)).await.map_err(|e| { + let resp = cyfs_util::async_h1_helper::connect_timeout(stream, req,std::time::Duration::from_secs(30)).await.map_err(|e| { error!("read resp from stream error: {}", e); e })?; From 8708a0ef603d4f1c0cda8c6e7ea255355ef1bb23 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 12:15:03 +0800 Subject: [PATCH 327/553] Add perf related definitions to cyfs-base --- src/component/cyfs-base/src/lib.rs | 2 + src/component/cyfs-base/src/perf/auxi.rs | 69 +++++++++++++++++++++++ src/component/cyfs-base/src/perf/dummy.rs | 29 ++++++++++ src/component/cyfs-base/src/perf/mod.rs | 15 +++++ src/component/cyfs-base/src/perf/perf.rs | 31 ++++++++++ 5 files changed, 146 insertions(+) create mode 100644 src/component/cyfs-base/src/perf/auxi.rs create mode 100644 src/component/cyfs-base/src/perf/dummy.rs create mode 100644 src/component/cyfs-base/src/perf/mod.rs create mode 100644 src/component/cyfs-base/src/perf/perf.rs diff --git a/src/component/cyfs-base/src/lib.rs b/src/component/cyfs-base/src/lib.rs index 627477b70..74e41d155 100644 --- a/src/component/cyfs-base/src/lib.rs +++ b/src/component/cyfs-base/src/lib.rs @@ -2,6 +2,7 @@ mod codec; mod crypto; mod base; mod objects; +mod perf; pub use base::endpoint; @@ -18,6 +19,7 @@ pub use base::*; pub use codec::*; pub use cyfs_base_derive::*; pub use objects::*; +pub use perf::*; #[macro_use] extern crate log; diff --git a/src/component/cyfs-base/src/perf/auxi.rs b/src/component/cyfs-base/src/perf/auxi.rs new file mode 100644 index 000000000..5a3da8418 --- /dev/null +++ b/src/component/cyfs-base/src/perf/auxi.rs @@ -0,0 +1,69 @@ +#[macro_export] +macro_rules! declare_module_perf_isolate { + ( $id:expr ) => { + pub const PERF_ISOLATE_ID: &str = $id; + pub fn get_current_perf_instance() -> Option<&'static cyfs_base::PerfIsolateRef> { + static CURRENT_PERF_INSTANCE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + match CURRENT_PERF_INSTANCE.get() { + Some(ins) => Some(ins), + None => { + match cyfs_base::PERF_MANGER.get() { + Some(manager) => { + let ins = manager.get_isolate(PERF_ISOLATE_ID); + let _ = CURRENT_PERF_INSTANCE.set(ins); + CURRENT_PERF_INSTANCE.get() + } + None => { + None + } + } + } + } + } + } +} + +#[macro_export] +macro_rules! perf_begin_request { + ( $id:expr, $key:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.begin_request($id, $key); + } + } +} + +#[macro_export] +macro_rules! perf_end_request { + ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request($id, $key, $err, $bytes); + } + } +} + +#[macro_export] +macro_rules! perf_acc { + ( $id:expr, $err:expr, $size:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.acc($id, $err, $size); + } + } +} + +#[macro_export] +macro_rules! perf_action { + ( $id:expr, $err:expr, $name:expr, $value:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.action($id, $err, $name, $value); + } + } +} + +#[macro_export] +macro_rules! perf_record { + ( $id:expr, $total:expr, $total_size:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.record($id, $total, $total_size); + } + } +} \ No newline at end of file diff --git a/src/component/cyfs-base/src/perf/dummy.rs b/src/component/cyfs-base/src/perf/dummy.rs new file mode 100644 index 000000000..3b918ec91 --- /dev/null +++ b/src/component/cyfs-base/src/perf/dummy.rs @@ -0,0 +1,29 @@ +#[macro_export] +macro_rules! declare_module_perf_isolate { + ( $id:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_begin_request { + ( $id:expr, $key:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_end_request { + ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_acc { + ( $id:expr, $err:expr, $size:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_action { + ( $id:expr, $err:expr, $name:expr, $value:expr ) => {}; +} + +#[macro_export] +macro_rules! perf_record { + ( $id:expr, $total:expr, $total_size:expr ) => {}; +} diff --git a/src/component/cyfs-base/src/perf/mod.rs b/src/component/cyfs-base/src/perf/mod.rs new file mode 100644 index 000000000..bcba02ef0 --- /dev/null +++ b/src/component/cyfs-base/src/perf/mod.rs @@ -0,0 +1,15 @@ +mod perf; + +pub use perf::*; + +#[cfg(not(feature = "perf"))] +mod dummy; + +#[cfg(not(feature = "perf"))] +pub use dummy::*; + +#[cfg(feature = "perf")] +mod auxi; + +#[cfg(feature = "perf")] +pub use auxi::*; \ No newline at end of file diff --git a/src/component/cyfs-base/src/perf/perf.rs b/src/component/cyfs-base/src/perf/perf.rs new file mode 100644 index 000000000..2c81117b4 --- /dev/null +++ b/src/component/cyfs-base/src/perf/perf.rs @@ -0,0 +1,31 @@ +use crate::{BuckyErrorCode, BuckyResult}; + +use once_cell::sync::OnceCell; +use std::sync::Arc; + +pub trait PerfIsolate: Send + Sync { + fn begin_request(&self, id: &str, key: &str); + fn end_request(&self, id: &str, key: &str, err: BuckyErrorCode, bytes: Option); + + fn acc(&self, id: &str, err: BuckyErrorCode, size: Option); + + fn action( + &self, + id: &str, + err: BuckyErrorCode, + name: &str, + value: &str, + ); + + fn record(&self, id: &str, total: u64, total_size: Option); +} + +pub type PerfIsolateRef = Arc>; + +#[async_trait::async_trait] +pub trait PerfManager: Send + Sync { + async fn flush(&self) -> BuckyResult<()>; + fn get_isolate(&self, id: &str) -> PerfIsolateRef; +} + +pub static PERF_MANGER: OnceCell> = OnceCell::new(); From 6b7bf888513ea003efa33323d04b553b66863adc Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 13:16:44 +0800 Subject: [PATCH 328/553] Adapts perf relate impls in cyfs-perf-client with the perf definition in cyfs-base --- .../cyfs-perf/cyfs-perf-client/src/client.rs | 24 ++++++++++--- .../cyfs-perf/cyfs-perf-client/src/isolate.rs | 35 +++++++++++++++++-- .../cyfs-perf-client/src/reporter.rs | 7 ++-- .../cyfs-perf/cyfs-perf-client/src/store.rs | 2 +- src/tests/cyfs-stack-test/src/case/perf.rs | 6 ++-- 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs index 5d029c415..15dddeb42 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/client.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/client.rs @@ -1,5 +1,5 @@ use crate::config::*; -use crate::isolate::PerfIsolate; +use crate::isolate::PerfIsolateInstance; use crate::reporter::*; use crate::store::PerfStore; use cyfs_base::*; @@ -22,7 +22,7 @@ pub struct PerfClientInner { cyfs_stack: UniCyfsStackRef, store: PerfStore, - isolates: Mutex>, + isolates: Mutex>, local_device: DeviceId, owner: ObjectId @@ -139,11 +139,11 @@ impl PerfClientInner { Ok(()) } - pub fn get_isolate(&self, id: &str) -> PerfIsolate { + pub fn get_isolate(&self, id: &str) -> PerfIsolateInstance { let mut isolates = self.isolates.lock().unwrap(); isolates.entry(id.to_owned()).or_insert_with(|| { log::info!("create isolate module: id={}", id); - PerfIsolate::new(id) + PerfIsolateInstance::new(id) }).clone() } } @@ -164,6 +164,10 @@ impl PerfClient { Self(Arc::new(ret)) } + pub fn get_isolate(&self, id: &str) -> PerfIsolateInstance { + self.0.get_isolate(id) + } + pub async fn start(&self) -> BuckyResult<()> { self.0.start().await?; @@ -184,3 +188,15 @@ impl Deref for PerfClient { &self.0 } } + + +#[async_trait::async_trait] +impl PerfManager for PerfClient { + async fn flush(&self) -> BuckyResult<()> { + self.0.flush().await + } + + fn get_isolate(&self, id: &str) -> PerfIsolateRef { + self.0.get_isolate(id).into_isolate() + } +} \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs b/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs index 15b884494..2743f3d9e 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/isolate.rs @@ -231,13 +231,17 @@ impl PerfItemMerge for PerfIsolateImpl { } #[derive(Clone)] -pub struct PerfIsolate(Arc>); +pub struct PerfIsolateInstance(Arc>); -impl PerfIsolate { +impl PerfIsolateInstance { pub fn new(id: &str) -> Self { Self(Arc::new(Mutex::new(PerfIsolateImpl::new(id)))) } + pub fn into_isolate(self) -> PerfIsolateRef { + Arc::new(Box::new(self)) + } + pub fn begin_request(&self, id: &str, key: &str) { self.0.lock().unwrap().begin_request(id, key) } @@ -273,3 +277,30 @@ impl PerfIsolate { self.0.lock().unwrap().id.clone() } } + +impl PerfIsolate for PerfIsolateInstance { + fn begin_request(&self, id: &str, key: &str) { + Self::begin_request(&self, id, key) + } + fn end_request(&self, id: &str, key: &str, err: BuckyErrorCode, bytes: Option) { + Self::end_request(&self, id, key, err, bytes) + } + + fn acc(&self, id: &str, err: BuckyErrorCode, size: Option) { + Self::acc(&self, id, err, size) + } + + fn action( + &self, + id: &str, + err: BuckyErrorCode, + name: &str, + value: &str, + ) { + Self::action(&self, id, err, name, value) + } + + fn record(&self, id: &str, total: u64, total_size: Option) { + Self::record(&self, id, total, total_size) + } +} \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index 9a83fe7af..5d386c0e0 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -114,8 +114,11 @@ impl PerfReporterInner { let end: chrono::DateTime = bucky_time_to_system_time(data.time_range.end).into(); let pretty_format = "%Y%m%d_%H%M%S"; let file_name = format!("{}-{}.stat", begin.format(pretty_format), end.format(pretty_format)); - if let Ok(file) = std::fs::File::create(path.join(file_name)) { - serde_json::to_writer_pretty(&file, &data); + let file_path = path.join(file_name); + if let Ok(file) = std::fs::File::create(&file_path) { + if let Err(e) = serde_json::to_writer_pretty(&file, &data) { + error!("save perf data to local file failed! file={}, {}", file_path.display(), e); + } } } diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs index 3359ccd3d..c657ec90e 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/store.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/store.rs @@ -59,7 +59,7 @@ impl PerfStore { } // 尝试保存到noc,保存成功后会清空isolates内容 - pub fn save(&self, isolates: &HashMap) { + pub fn save(&self, isolates: &HashMap) { // 锁定状态下,不可修改数据 if self.is_locked() { warn!("perf store still in locked state!"); diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index 49ba595b8..66cde49c7 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -1,7 +1,7 @@ use std::time::Duration; use cyfs_base::*; use cyfs_core::*; -use cyfs_perf_client::{PerfClient, PerfConfig, PerfIsolate, PerfServerConfig}; +use cyfs_perf_client::{PerfClient, PerfConfig, PerfIsolateInstance, PerfServerConfig}; use zone_simulator::*; fn new_dec(name: &str) -> ObjectId { @@ -47,7 +47,7 @@ pub async fn test() { // async_std::task::sleep(std::time::Duration::from_secs(1000)).await; } -async fn test_request(perf: PerfIsolate) { +async fn test_request(perf: PerfIsolateInstance) { async_std::task::spawn(async move { loop { perf.begin_request("connect", "address"); @@ -59,7 +59,7 @@ async fn test_request(perf: PerfIsolate) { }); } -async fn test_acc(perf: PerfIsolate) { +async fn test_acc(perf: PerfIsolateInstance) { async_std::task::spawn(async move { loop { async_std::task::sleep(std::time::Duration::from_secs(1)).await; From e5fde0cbef72e8f53a47341118d9ef4b261b6f7d Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 13:26:58 +0800 Subject: [PATCH 329/553] Integrate perf module into cyfs-stack --- src/Cargo.lock | 1 + src/component/cyfs-base/Cargo.toml | 1 + src/component/cyfs-stack/Cargo.toml | 1 + .../cyfs-stack/src/stack/cyfs_stack.rs | 42 +++++++++++++++++++ src/component/cyfs-stack/src/stack/params.rs | 4 ++ 5 files changed, 49 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index f09b84bc2..7f1d76f21 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2247,6 +2247,7 @@ dependencies = [ "cyfs-meta-lib", "cyfs-ndc", "cyfs-noc", + "cyfs-perf-client", "cyfs-task-manager", "cyfs-tracker-cache", "cyfs-util", diff --git a/src/component/cyfs-base/Cargo.toml b/src/component/cyfs-base/Cargo.toml index 3d972b259..9ce32803e 100644 --- a/src/component/cyfs-base/Cargo.toml +++ b/src/component/cyfs-base/Cargo.toml @@ -16,6 +16,7 @@ protoc-bin-vendored = '3' [features] default = [] sqlx-error = ['dep:sqlx'] +perf = [] [dependencies] cyfs-base-derive = { path = '../cyfs-base-derive', version = '0.5' } diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index faaaf23ec..48f201a85 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -27,6 +27,7 @@ cyfs-task-manager = { path = "../../component/cyfs-task-manager" } cyfs-chunk-cache = { path = "../../component/cyfs-chunk-cache" } cyfs-util = { path = "../cyfs-util" } cyfs-meta-lib = { path = "../cyfs-meta-lib" } +cyfs-perf-client = { path = "../cyfs-perf/cyfs-perf-client" } #dsg-client = { path = "../dsg/dsg-client" } log = "0.4" serde = "1.0" diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 7f6f75ef7..d562319ca 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -593,6 +593,10 @@ impl CyfsStackImpl { } }); + if param.config.perf_service { + let _ = stack.init_perf().await; + } + Ok(stack) } @@ -1029,6 +1033,44 @@ impl CyfsStackImpl { processors } + + async fn init_perf(&self) -> BuckyResult<()> { + use cyfs_perf_client::*; + + // The same process can only be initialized once, there may be other cyfs-stacks in the same process + if !cyfs_base::PERF_MANGER.get().is_none() { + warn!("perf manager already initialized!"); + return Ok(()); + } + + let info = self.zone_manager.get_current_info().await?; + + let perf = PerfClient::new( + "cyfs-stack".to_owned(), + cyfs_base::get_version().to_owned(), + None, + PerfConfig { + reporter: PerfServerConfig::Default, + save_to_file: false, + report_interval: std::time::Duration::from_secs(60 * 10), + }, + self.open_uni_stack(&None).await, + info.device_id.clone(), + info.owner_id.clone(), + ); + + if let Err(e) = perf.start().await { + error!("init perf client failed! {}", e); + } + + if let Err(_) = cyfs_base::PERF_MANGER.set(Box::new(perf)) { + warn!("init perf manager but already initialized!"); + } + + info!("init perf manager success! current={}", info.device_id); + + Ok(()) + } } #[derive(Clone)] diff --git a/src/component/cyfs-stack/src/stack/params.rs b/src/component/cyfs-stack/src/stack/params.rs index 37af157e8..7ebcc448d 100644 --- a/src/component/cyfs-stack/src/stack/params.rs +++ b/src/component/cyfs-stack/src/stack/params.rs @@ -13,6 +13,9 @@ pub struct CyfsStackConfigParams { // 是否开启shared_object_stack服务,默认为true pub shared_stack: bool, + + // Whether to enable perf_service + pub perf_service: bool, } impl Default for CyfsStackConfigParams { @@ -21,6 +24,7 @@ impl Default for CyfsStackConfigParams { isolate: None, sync_service: true, shared_stack: true, + perf_service: true, } } } From 5a347476a8077a769c09ed6f7fa99cc9e7b769a0 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 16:18:14 +0800 Subject: [PATCH 330/553] Add scope relate perf helper macros --- src/component/cyfs-base/src/perf/auxi.rs | 90 ++++++++++++++++++++++- src/component/cyfs-base/src/perf/dummy.rs | 16 ++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-base/src/perf/auxi.rs b/src/component/cyfs-base/src/perf/auxi.rs index 5a3da8418..01bb4b4ce 100644 --- a/src/component/cyfs-base/src/perf/auxi.rs +++ b/src/component/cyfs-base/src/perf/auxi.rs @@ -20,6 +20,65 @@ macro_rules! declare_module_perf_isolate { } } } + + pub struct PerfScopeRequest<'a> { + id: &'a str, + key: String, + } + + impl<'a> PerfScopeRequest<'a> { + pub fn new( + id: &'a str, + ) -> Self { + let key = cyfs_base::perf_request_unique_id(); + if let Some(ins) = crate::get_current_perf_instance() { + ins.begin_request(id, &key); + } + + Self { + id, + key, + } + } + } + + impl<'a> Drop for PerfScopeRequest<'a> { + fn drop(&mut self) { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request(self.id, &self.key, cyfs_base::BuckyErrorCode::Ok, None); + } + } + } + } +} + +use std::sync::atomic::{AtomicU64, Ordering}; + +pub fn perf_request_unique_id() -> String { + static INDEX: AtomicU64 = AtomicU64::new(0); + let ret = INDEX.fetch_add(1, Ordering::SeqCst); + ret.to_string() +} + +#[macro_export] +macro_rules! perf_scope_request { + ( $id:expr, $block:block ) => { + if let Some(ins) = crate::get_current_perf_instance() { + let req_id = cyfs_base::perf_request_unique_id(); + ins.begin_request($id, &req_id); + match $block { + Ok(v) => { + ins.end_request($id, &req_id, cyfs_base::BuckyErrorCode::Ok, None); + Ok(v) + } + Err(e) => { + ins.end_request($id, &req_id, e.code(), None); + Err(e) + } + } + } else { + $block + } } } @@ -34,20 +93,49 @@ macro_rules! perf_begin_request { #[macro_export] macro_rules! perf_end_request { + ( $id:expr, $key:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request($id, $key, cyfs_base::BuckyErrorCode::Ok, None); + } + }; + ( $id:expr, $key:expr, $err:expr ) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.end_request($id, $key, $err, None); + } + }; ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => { if let Some(ins) = crate::get_current_perf_instance() { ins.end_request($id, $key, $err, $bytes); } + }; +} + + +#[macro_export] +macro_rules! perf_simple_scope_request { + ( $id:expr ) => { + let __perf_simple_scope_request = crate::PerfScopeRequest::new($id); } } + #[macro_export] macro_rules! perf_acc { + ($id:expr) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.acc($id, cyfs_base::BuckyErrorCode::Ok, None); + } + }; + ($id:expr, $err:expr) => { + if let Some(ins) = crate::get_current_perf_instance() { + ins.acc($id, $err, None); + } + }; ( $id:expr, $err:expr, $size:expr ) => { if let Some(ins) = crate::get_current_perf_instance() { ins.acc($id, $err, $size); } - } + }; } #[macro_export] diff --git a/src/component/cyfs-base/src/perf/dummy.rs b/src/component/cyfs-base/src/perf/dummy.rs index 3b918ec91..913b908d0 100644 --- a/src/component/cyfs-base/src/perf/dummy.rs +++ b/src/component/cyfs-base/src/perf/dummy.rs @@ -3,6 +3,13 @@ macro_rules! declare_module_perf_isolate { ( $id:expr ) => {}; } +#[macro_export] +macro_rules! perf_scope_request { + ( $id:expr, $block:block ) => { + $block + }; +} + #[macro_export] macro_rules! perf_begin_request { ( $id:expr, $key:expr ) => {}; @@ -10,11 +17,20 @@ macro_rules! perf_begin_request { #[macro_export] macro_rules! perf_end_request { + ( $id:expr, $key:expr ) => {}; + ( $id:expr, $key:expr, $err:expr ) => {}; ( $id:expr, $key:expr, $err:expr, $bytes:expr ) => {}; } +#[macro_export] +macro_rules! perf_simple_scope_request { + ( $id:expr ) => {}; +} + #[macro_export] macro_rules! perf_acc { + ($id:expr) => {}; + ($id:expr, $err:expr) => {}; ( $id:expr, $err:expr, $size:expr ) => {}; } From e808a569dc7a19b99330d897c1febf43a66104c5 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 16:23:02 +0800 Subject: [PATCH 331/553] Add some perf stub codec into cyfs-noc and cyfs-lib projects --- src/component/cyfs-lib/src/lib.rs | 5 +++- src/component/cyfs-noc/Cargo.toml | 2 +- src/component/cyfs-noc/src/lib.rs | 4 +++- src/component/cyfs-noc/src/meta/sqlite/db.rs | 24 ++++++++++--------- .../cyfs-stack/src/stack/cyfs_stack.rs | 4 ++-- src/tests/cyfs-stack-test/src/case/mod.rs | 7 +++--- src/tests/cyfs-stack-test/src/case/perf.rs | 2 +- 7 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index 80b572e2c..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -53,8 +53,11 @@ pub fn register_core_objects_format() { FORMAT_FACTORY.register(cyfs_core::CoreObjectType::Admin, format_json::); } +cyfs_base::declare_module_perf_isolate!("cyfs-lib"); + #[cfg(test)] mod tests { #[test] - fn main() {} + fn main() { + } } diff --git a/src/component/cyfs-noc/Cargo.toml b/src/component/cyfs-noc/Cargo.toml index 39fc1ff83..ce8b9608a 100644 --- a/src/component/cyfs-noc/Cargo.toml +++ b/src/component/cyfs-noc/Cargo.toml @@ -17,7 +17,7 @@ async-trait = "0.1.53" lazy_static = "1.4" cyfs-util = { path = "../../component/cyfs-util" } cyfs-lib = { path = "../../component/cyfs-lib" } -cyfs-base = { path = "../../component/cyfs-base" } +cyfs-base = { path = "../../component/cyfs-base", features = ["perf"]} cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-core = { path = "../../component/cyfs-core" } async-std = { version = "1.11", features = ["unstable", "attributes"] } diff --git a/src/component/cyfs-noc/src/lib.rs b/src/component/cyfs-noc/src/lib.rs index aa801b1ba..438e04a2e 100644 --- a/src/component/cyfs-noc/src/lib.rs +++ b/src/component/cyfs-noc/src/lib.rs @@ -9,4 +9,6 @@ mod noc; pub use noc::*; #[macro_use] -extern crate log; \ No newline at end of file +extern crate log; + +cyfs_base::declare_module_perf_isolate!("cyfs-noc"); \ No newline at end of file diff --git a/src/component/cyfs-noc/src/meta/sqlite/db.rs b/src/component/cyfs-noc/src/meta/sqlite/db.rs index bcd8aeb1e..645441d12 100644 --- a/src/component/cyfs-noc/src/meta/sqlite/db.rs +++ b/src/component/cyfs-noc/src/meta/sqlite/db.rs @@ -1306,53 +1306,55 @@ impl NamedObjectMeta for SqliteMetaStorage { &self, req: &NamedObjectMetaPutObjectRequest, ) -> BuckyResult { - self.update(req).await + perf_scope_request!("noc.meta.put_object", { self.update(req).await }) } async fn get_object( &self, req: &NamedObjectMetaGetObjectRequest, ) -> BuckyResult> { - self.get(req).await + perf_scope_request!("noc.meta.get_object", { self.get(req).await }) } async fn delete_object( &self, req: &NamedObjectMetaDeleteObjectRequest, ) -> BuckyResult { - self.delete(req).await + perf_scope_request!("noc.meta.delete_object", { self.delete(req).await }) } async fn exists_object(&self, req: &NamedObjectMetaExistsObjectRequest) -> BuckyResult { - self.exists(req) + perf_scope_request!("noc.meta.exists_object", { self.exists(req) }) } async fn update_last_access( &self, req: &NamedObjectMetaUpdateLastAccessRequest, ) -> BuckyResult { - match Self::update_last_access(&self, req)? { - n if n >= 1 => Ok(true), - _ => Ok(false), - } + perf_scope_request!("noc.meta.update_last_access", { + match Self::update_last_access(&self, req)? { + n if n >= 1 => Ok::(true), + _ => Ok(false), + } + }) } async fn update_object_meta( &self, req: &NamedObjectMetaUpdateObjectMetaRequest, ) -> BuckyResult<()> { - Self::update_object_meta(&self, req).await + perf_scope_request!("noc.meta.update_object_meta", { Self::update_object_meta(&self, req).await }) } async fn check_object_access( &self, req: &NamedObjectMetaCheckObjectAccessRequest, ) -> BuckyResult> { - Self::check_object_access(&self, req).await + perf_scope_request!("noc.meta.check_object_access", { Self::check_object_access(&self, req).await }) } async fn stat(&self) -> BuckyResult { - Self::stat(&self).await + perf_scope_request!("noc.meta.stat", { Self::stat(&self).await }) } fn bind_object_meta_access_provider( diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index d562319ca..f03d529e9 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -1051,7 +1051,7 @@ impl CyfsStackImpl { None, PerfConfig { reporter: PerfServerConfig::Default, - save_to_file: false, + save_to_file: true, report_interval: std::time::Duration::from_secs(60 * 10), }, self.open_uni_stack(&None).await, @@ -1068,7 +1068,7 @@ impl CyfsStackImpl { } info!("init perf manager success! current={}", info.device_id); - + Ok(()) } } diff --git a/src/tests/cyfs-stack-test/src/case/mod.rs b/src/tests/cyfs-stack-test/src/case/mod.rs index 25a71bee3..f1d5bde1b 100644 --- a/src/tests/cyfs-stack-test/src/case/mod.rs +++ b/src/tests/cyfs-stack-test/src/case/mod.rs @@ -45,8 +45,6 @@ pub async fn test() { // role::test().await; - // meta::test().await; - // crypto::test().await; noc::test().await; @@ -60,6 +58,9 @@ pub async fn test() { ndn::test().await; call::test().await; object_meta_access::test().await; + + async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; + return; test_restart().await; @@ -69,7 +70,7 @@ pub async fn test() { // test_drive::test().await; events::test().await; - // crypto::test().await; + zone::test().await; non_handlers::test().await; diff --git a/src/tests/cyfs-stack-test/src/case/perf.rs b/src/tests/cyfs-stack-test/src/case/perf.rs index 66cde49c7..7df91fe42 100644 --- a/src/tests/cyfs-stack-test/src/case/perf.rs +++ b/src/tests/cyfs-stack-test/src/case/perf.rs @@ -17,7 +17,7 @@ fn new_dec(name: &str) -> ObjectId { pub async fn test() { let dec_id = new_dec("test-perf"); let stack = TestLoader::get_shared_stack(DeviceIndex::User1Device2); - stack.online().await; + stack.online().await.unwrap(); let device = stack.local_device(); let owner = device.desc().owner().as_ref().unwrap().clone(); let device_id = device.desc().device_id(); From 069512194c47f7461ace3d92992ba63a3dc0fd78 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Sat, 25 Feb 2023 17:20:14 +0800 Subject: [PATCH 332/553] Perf-client use post_object when send perf to other device --- src/Cargo.lock | 3 +- .../cyfs-perf/cyfs-perf-base/Cargo.toml | 3 +- .../cyfs-perf/cyfs-perf-base/src/lib.rs | 14 ++- .../cyfs-perf-client/src/reporter.rs | 90 +++++++++---------- 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 7f1d76f21..1d9ae081b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2127,7 +2127,7 @@ dependencies = [ [[package]] name = "cyfs-perf-base" -version = "0.6.1" +version = "0.6.2" dependencies = [ "async-std", "cyfs-base", @@ -2135,6 +2135,7 @@ dependencies = [ "cyfs-lib", "cyfs-util", "int-enum", + "lazy_static", "log 0.4.17", "protobuf", "protoc-bin-vendored", diff --git a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml index 0320550cc..9ff1ed0a6 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-perf-base' -version = '0.6.1' +version = '0.6.2' authors = ['wangzhi '] edition = '2021' license = 'BSD-2-Clause' @@ -21,6 +21,7 @@ int-enum = '0.4' protobuf = { version = '2', features = ['with-bytes'] } serde = { version = '1.0', features = ['derive'] } serde_json = '1.0' +lazy_static = "1.4" [dev-dependencies] async-std = { version = '1.11', features = ['attributes'] } diff --git a/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs b/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs index 62fbd7928..728b5a584 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs +++ b/src/component/cyfs-perf/cyfs-perf-base/src/lib.rs @@ -3,6 +3,18 @@ mod items; mod perf; mod merge; +#[macro_use] +extern crate lazy_static; + +use cyfs_base::ObjectId; +use std::str::FromStr; + pub use items::*; pub use perf::*; -pub use merge::*; \ No newline at end of file +pub use merge::*; + +lazy_static! { + pub static ref PERF_DEC_ID: ObjectId = ObjectId::from_str("9tGpLNnAAYE9Dd4ooNiSjtP5MeL9CNLf9Rxu6AFEc12M").unwrap(); +} + +pub static PERF_REPORT_PATH: &str = "/.perf/report"; \ No newline at end of file diff --git a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs index 5d386c0e0..a8bedb2ba 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs +++ b/src/component/cyfs-perf/cyfs-perf-client/src/reporter.rs @@ -142,7 +142,7 @@ impl PerfReporterInner { let perf_server = self.perf_server.as_ref().map(|id| id.object_id().to_owned()); - match self.put_object(&perf_obj, perf_server, 0, self.save_to_local).await { + match self.send_perf(perf_obj, perf_server, self.save_to_local).await { Ok(_) => { info!( "report perf success! id={}, target={:?}, perf_object={}", @@ -161,61 +161,59 @@ impl PerfReporterInner { } // NON_REQUEST_FLAG_SIGN_BY_DEVICE | NON_REQUEST_FLAG_SIGN_SET_DESC | NON_REQUEST_FLAG_SIGN_SET_BODY - pub async fn put_object( + pub async fn send_perf( &self, - obj: &Perf, + obj: Perf, target: Option, - sign_flags: u32, save_to_local: bool ) -> BuckyResult<()> { - let raw; + let raw= obj.to_vec().unwrap(); let object_id = obj.desc().calculate_id(); - if sign_flags != 0 { - let object_raw = obj.to_vec().unwrap(); - let req = CryptoSignObjectRequest::new(object_id.clone(), object_raw, sign_flags); - // 先给Obj签名, 用Client的Device - let resp = self.cyfs_stack.crypto_service().sign_object(req).await - .map_err(|e| { - error!("{} sign failed, err {}", &object_id, e); - e - })?; - raw = resp.object.unwrap().object_raw; + // 如果存到本地,就直接用put + if save_to_local { + let mut req = NONPutObjectOutputRequest::new( + NONAPILevel::NOC, + object_id.clone(), raw); + req.common.dec_id = Some(PERF_DEC_ID.clone()); + match self.cyfs_stack.non_service().put_object(req).await { + Ok(_) => { + info!("### save perf obj {} to local success!", &object_id); + Ok(()) + } + Err(e) => { + error!("### save perf obj {} to local failed! {}", &object_id, e); + Err(e) + } + }?; + // 存到root_state + let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); + req.common.target = target.clone(); + req.common.target_dec_id = self.dec_id.clone(); + + let resp = self.cyfs_stack.root_state().create_op_env(req).await?; + let path_env = PathOpEnvStub::new(resp, target.clone(), self.dec_id.clone()); + let key = obj.get_time_range().to_string(); + path_env.set_with_key("/stat", key, &object_id, None, true).await?; + path_env.commit().await?; } else { - raw = obj.to_vec().unwrap(); + let mut req = NONPostObjectRequest::new_router(target, object_id.clone(), raw); + req.common.dec_id = Some(PERF_DEC_ID.clone()); + req.common.req_path = Some(PERF_REPORT_PATH.to_owned()); + let str_target = target.map_or("ood".to_owned(), |id| id.to_string()); + match self.cyfs_stack.non_service().post_object(req).await { + Ok(_) => { + info!("### send perf obj {} to {} success!", &object_id, str_target); + Ok(()) + } + Err(e) => { + error!("### send perf obj {} to {} failed! {}", &object_id, str_target, e); + Err(e) + } + }?; } - // 把obj再put出去 - let target = if save_to_local { None } else { target }; - let mut req = NONPutObjectOutputRequest::new( - if save_to_local { NONAPILevel::NOC } else { NONAPILevel::Router }, - object_id.clone(), raw); - req.common.target = target.clone(); - req.common.dec_id = obj.desc().dec_id().clone(); - let str_target = if save_to_local { "local".to_owned() } else {target.map_or("ood".to_owned(), |id| id.to_string())}; - match self.cyfs_stack.non_service().put_object(req).await { - Ok(_) => { - info!("### put perf obj {} to {} success!", &object_id, str_target); - Ok(()) - } - Err(e) => { - error!("### put perf obj [{}] to {} failed! {}", &object_id, str_target, e); - Err(e) - } - }?; - - // 存到root_state - let mut req = RootStateCreateOpEnvOutputRequest::new(ObjectMapOpEnvType::Path); - req.common.target = target.clone(); - req.common.target_dec_id = self.dec_id.clone(); - - let resp = self.cyfs_stack.root_state().create_op_env(req).await?; - let path_env = PathOpEnvStub::new(resp, target.clone(), self.dec_id.clone()); - let key = obj.get_time_range().to_string(); - path_env.set_with_key("/stat", key, &object_id, None, true).await?; - path_env.commit().await?; - Ok(()) } } From 3281479d3f3dfa5342ccca1ac39088af731bf906 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Sat, 25 Feb 2023 18:50:35 +0800 Subject: [PATCH 333/553] Modify: add reset known sn method to bdt stack --- src/component/cyfs-bdt/examples/call_with_tcp.rs | 2 +- src/component/cyfs-bdt/examples/sn_with_ipv6.rs | 2 +- src/component/cyfs-bdt/examples/use_next_sn.rs | 2 +- src/component/cyfs-bdt/src/sn/client/cache.rs | 10 +++++++++- src/component/cyfs-bdt/src/stack.rs | 14 ++++++++------ src/component/cyfs-bdt/tests/sn.rs | 11 +++++------ 6 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/component/cyfs-bdt/examples/call_with_tcp.rs b/src/component/cyfs-bdt/examples/call_with_tcp.rs index c0693c515..e3ddab943 100644 --- a/src/component/cyfs-bdt/examples/call_with_tcp.rs +++ b/src/component/cyfs-bdt/examples/call_with_tcp.rs @@ -91,7 +91,7 @@ async fn main() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>>(1); diff --git a/src/component/cyfs-bdt/examples/sn_with_ipv6.rs b/src/component/cyfs-bdt/examples/sn_with_ipv6.rs index eb3fe568f..78a74ce7a 100644 --- a/src/component/cyfs-bdt/examples/sn_with_ipv6.rs +++ b/src/component/cyfs-bdt/examples/sn_with_ipv6.rs @@ -95,7 +95,7 @@ async fn main() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>>(1); diff --git a/src/component/cyfs-bdt/examples/use_next_sn.rs b/src/component/cyfs-bdt/examples/use_next_sn.rs index b83baa77e..0a7cb4990 100644 --- a/src/component/cyfs-bdt/examples/use_next_sn.rs +++ b/src/component/cyfs-bdt/examples/use_next_sn.rs @@ -111,7 +111,7 @@ async fn main() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn1.clone(), sn2.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); diff --git a/src/component/cyfs-bdt/src/sn/client/cache.rs b/src/component/cyfs-bdt/src/sn/client/cache.rs index 4d54b4f94..a469764c8 100644 --- a/src/component/cyfs-bdt/src/sn/client/cache.rs +++ b/src/component/cyfs-bdt/src/sn/client/cache.rs @@ -26,8 +26,16 @@ impl SnCache { for sn in sn_list { known_list.insert(sn.clone()); } - } + + pub fn reset_known_sn(&self, sn_list: &Vec) { + let mut known_list = self.known_list.write().unwrap(); + known_list.clear(); + for sn in sn_list { + known_list.insert(sn.clone()); + } + } + pub fn nearest_sn_of(remote: &DeviceId, sn_list: &[DeviceId]) -> Option { sn_list.iter().min_by(|l, r| l.object_id().distance(remote.object_id()).cmp(&r.object_id().distance(remote.object_id()))).cloned() } diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index a20becf1a..c7f556e85 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -378,8 +378,7 @@ impl Stack { if params.known_sn.is_some() { std::mem::swap(&mut known_sn, params.known_sn.as_mut().unwrap()); } - stack.reset_sn_list(known_sn); - + stack.reset_known_sn(known_sn.clone()); stack.ndn().start(); if let Some(debug_stub) = debug_stub { @@ -465,13 +464,16 @@ impl Stack { pub fn reset_sn_list(&self, sn_list: Vec) -> PingClients { let sn_id_list: Vec = sn_list.iter().map(|sn| sn.desc().device_id()).collect(); info!("{} reset_sn_list {:?}", self, sn_id_list); - + self.sn_client().reset_sn_list(sn_list) + } + + pub fn reset_known_sn(&self, sn_list: Vec) { + let sn_id_list: Vec = sn_list.iter().map(|sn| sn.desc().device_id()).collect(); + info!("{} reset_known_sn_list {:?}", self, sn_id_list); for (id, sn) in sn_id_list.iter().zip(sn_list.iter()) { self.device_cache().add_static(id, sn); } - self.sn_client().cache().add_known_sn(&sn_id_list); - - self.sn_client().reset_sn_list(sn_list) + self.sn_client().cache().reset_known_sn(&sn_id_list); } pub async fn reset_endpoints(&self, endpoints: &Vec) -> PingClients { diff --git a/src/component/cyfs-bdt/tests/sn.rs b/src/component/cyfs-bdt/tests/sn.rs index 816487a16..7d475babe 100644 --- a/src/component/cyfs-bdt/tests/sn.rs +++ b/src/component/cyfs-bdt/tests/sn.rs @@ -80,7 +80,7 @@ async fn call_sn_without_ping() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -168,8 +168,7 @@ async fn reset_sn_list() { rn_dev, rn_secret, rn_params).await.unwrap(); - - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn1.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -288,7 +287,7 @@ async fn use_next_sn() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn1.clone(), sn2.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -358,7 +357,7 @@ async fn call_with_tcp() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); @@ -428,7 +427,7 @@ async fn sn_with_ipv6() { rn_secret, rn_params).await.unwrap(); - assert_eq!(SnStatus::Online, rn_stack.sn_client().ping().wait_online().await.unwrap()); + assert_eq!(SnStatus::Online, rn_stack.reset_sn_list(vec![sn.clone()]).wait_online().await.unwrap()); let (sample_size, sample) = utils::random_mem(1024, 512); let (signal_sender, signal_recver) = channel::bounded::>(1); From 9f1fb4ec5e08d09341eefc9a3d10925960daaa50 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Sat, 25 Feb 2023 19:03:51 +0800 Subject: [PATCH 334/553] NamedDataClient use bdt no-sn mode, not listen on tcp port --- src/service/app-manager/src/app_controller.rs | 2 +- src/tools/cyfs-client/src/named_data_client.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/service/app-manager/src/app_controller.rs b/src/service/app-manager/src/app_controller.rs index 0baf92a32..ec07fb2bc 100644 --- a/src/service/app-manager/src/app_controller.rs +++ b/src/service/app-manager/src/app_controller.rs @@ -104,7 +104,7 @@ impl AppController { let old_hash = this.sn_hash.read().unwrap().clone(); if old_hash != sn_hash { info!("sn list from stack changed, {:?}", &sn_list); - match this.named_cache_client.get().unwrap().reset_sn_list(sn_list).await { + match this.named_cache_client.get().unwrap().reset_known_sn_list(sn_list) { Ok(_) => { *this.sn_hash.write().unwrap() = sn_hash; } diff --git a/src/tools/cyfs-client/src/named_data_client.rs b/src/tools/cyfs-client/src/named_data_client.rs index 87b4776fd..0f676297d 100644 --- a/src/tools/cyfs-client/src/named_data_client.rs +++ b/src/tools/cyfs-client/src/named_data_client.rs @@ -187,7 +187,6 @@ impl NamedCacheClient { let port = rand::thread_rng().gen_range(30000, 50000) as u16; for ip in cyfs_util::get_all_ips().unwrap() { if ip.is_ipv4() { - endpoints.push(Endpoint::from((Protocol::Tcp, ip, port))); endpoints.push(Endpoint::from((Protocol::Udp, ip, port))); } } @@ -242,12 +241,12 @@ impl NamedCacheClient { } } - pub async fn reset_sn_list(&self, sn_list: Vec) -> BuckyResult<()> { + pub fn reset_known_sn_list(&self, sn_list: Vec) -> BuckyResult<()> { if let Some(stack) = self.stack.get() { info!("named data client reset sn list {:?}", sn_list.iter().map(|device|{ device.desc().calculate_id() }).collect::>()); - stack.reset_sn_list(sn_list).wait_online().await?; + stack.reset_known_sn(sn_list); Ok(()) } else { Err(BuckyError::from(BuckyErrorCode::NotInit)) From 36f97a20f7802c430e9184d454f2e87b9b13a498 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 17:21:12 +0800 Subject: [PATCH 335/553] Fix a panic that may be caused by an object field being empty in cyfs-noc --- src/component/cyfs-lib/src/non/def.rs | 21 +++++++++++++++++++++ src/component/cyfs-noc/src/storage/local.rs | 10 +++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-lib/src/non/def.rs b/src/component/cyfs-lib/src/non/def.rs index 82c97a02d..7845871bf 100644 --- a/src/component/cyfs-lib/src/non/def.rs +++ b/src/component/cyfs-lib/src/non/def.rs @@ -5,6 +5,7 @@ use serde_json::{Map, Value}; use std::fmt; use std::str::FromStr; use std::sync::Arc; +use std::borrow::Cow; // 请求的数据类型 #[derive(Clone)] @@ -251,6 +252,26 @@ impl NONObjectInfo { self.object.as_ref().unwrap() } + + pub fn object_if_none_then_decode(&self) -> BuckyResult> { + match &self.object { + Some(object) => { + Ok(Cow::Borrowed(object.as_ref())) + } + None => { + let (object, _) = AnyNamedObject::raw_decode(&self.object_raw).map_err(|e| { + error!( + "decode object from object_raw error: obj={} {}", + self.object_id, e, + ); + e + })?; + + Ok(Cow::Owned(object)) + } + } + } + pub fn take_object(&mut self) -> Arc { self.object.take().unwrap() } diff --git a/src/component/cyfs-noc/src/storage/local.rs b/src/component/cyfs-noc/src/storage/local.rs index 3d7345f34..93e27b6f4 100644 --- a/src/component/cyfs-noc/src/storage/local.rs +++ b/src/component/cyfs-noc/src/storage/local.rs @@ -71,7 +71,7 @@ impl NamedObjectLocalStorage { &self, request: &NamedObjectCachePutObjectRequest, ) -> BuckyResult { - let meta_req = self.gen_meta_put_request(request); + let meta_req = self.gen_meta_put_request(request)?; let meta_ret = self.meta.put_object(&meta_req).await?; info!( @@ -145,8 +145,8 @@ impl NamedObjectLocalStorage { fn gen_meta_put_request( &self, request: &NamedObjectCachePutObjectRequest, - ) -> NamedObjectMetaPutObjectRequest { - let obj = request.object.object.as_ref().unwrap(); + ) -> BuckyResult { + let obj = request.object.object_if_none_then_decode()?; let object_create_time = match obj.create_time() { 0 => None, @@ -169,7 +169,7 @@ impl NamedObjectLocalStorage { None => AccessString::default().value(), }; - NamedObjectMetaPutObjectRequest { + Ok(NamedObjectMetaPutObjectRequest { source: request.source.clone(), object_id: request.object.object_id.clone(), owner_id, @@ -190,7 +190,7 @@ impl NamedObjectLocalStorage { context: request.context.clone(), last_access_rpath: request.last_access_rpath.clone(), access_string, - } + }) } fn merge_body_and_signs( From d6ce01d97c7cc7280ccebc2da7887b4e53f666a0 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 17:24:41 +0800 Subject: [PATCH 336/553] Ensure that the object field is not empty during the non output->input direct conversion --- src/component/cyfs-stack/src/non/transform.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-stack/src/non/transform.rs b/src/component/cyfs-stack/src/non/transform.rs index 486928cdb..f17e3565e 100644 --- a/src/component/cyfs-stack/src/non/transform.rs +++ b/src/component/cyfs-stack/src/non/transform.rs @@ -218,8 +218,11 @@ impl NONOutputTransformer { async fn put_object( &self, - req: NONPutObjectOutputRequest, + mut req: NONPutObjectOutputRequest, ) -> BuckyResult { + // Make sure the object field is not empty! + req.object.try_decode()?; + let in_req = NONPutObjectInputRequest { common: self.convert_common(req.common), @@ -263,8 +266,11 @@ impl NONOutputTransformer { async fn post_object( &self, - req: NONPostObjectOutputRequest, + mut req: NONPostObjectOutputRequest, ) -> BuckyResult { + // Make sure the object field is not empty! + req.object.try_decode()?; + let in_req = NONPostObjectInputRequest { common: self.convert_common(req.common), From d6530cd7912afa3dfaf7b8e50c4847fbc076c15e Mon Sep 17 00:00:00 2001 From: liyaxing Date: Sat, 25 Feb 2023 18:47:38 +0800 Subject: [PATCH 337/553] Add sn_mode to cyfs-stack and loaders --- .../cyfs-bdt-ext/src/sn/sn_config.rs | 91 +++++++++++++------ src/component/cyfs-bdt-ext/src/stack/param.rs | 48 +++++++++- src/component/cyfs-bdt-ext/src/stack/stack.rs | 73 ++++++--------- .../cyfs-stack-loader/src/bdt_loader.rs | 35 +++++++ .../src/cyfs_loader_config.rs | 3 +- .../cyfs-stack-loader/src/stack_info.rs | 1 + .../cyfs-stack/src/config/sn_config.rs | 5 +- .../src/root_state_api/core/test.rs | 1 + 8 files changed, 179 insertions(+), 78 deletions(-) diff --git a/src/component/cyfs-bdt-ext/src/sn/sn_config.rs b/src/component/cyfs-bdt-ext/src/sn/sn_config.rs index 91d32bf9f..70051612e 100644 --- a/src/component/cyfs-bdt-ext/src/sn/sn_config.rs +++ b/src/component/cyfs-bdt-ext/src/sn/sn_config.rs @@ -1,19 +1,21 @@ +use crate::stack::SNMode; use cyfs_base::*; -use cyfs_bdt::{retry_sn_list_when_offline, SnStatus, StackGuard}; +use cyfs_bdt::{retry_sn_list_when_offline, sn::client::PingClients, SnStatus, StackGuard}; use once_cell::sync::OnceCell; use std::sync::Arc; -use std::time::Duration; #[derive(Clone)] pub struct BdtStackSNHelper { bdt_stack: Arc>, + sn_mode: SNMode, } impl BdtStackSNHelper { - pub fn new() -> Self { + pub fn new(sn_mode: SNMode) -> Self { Self { bdt_stack: Arc::new(OnceCell::new()), + sn_mode, } } @@ -23,37 +25,72 @@ impl BdtStackSNHelper { } } - pub async fn on_sn_list_changed(&self, sn_list: Vec) { + pub async fn on_sn_list_changed(&self, config_sn_list: Vec) { // notify bdt stack if let Some(bdt_stack) = self.bdt_stack.get() { - let ping_clients = bdt_stack.reset_sn_list(sn_list); - match ping_clients.wait_online().await { - Err(err) => { - error!("reset bdt sn list error! {}", err); + let sn_list = match self.sn_mode { + SNMode::Normal => Some(config_sn_list.clone()), + SNMode::None => { + warn!("sn_mode is none, now will clear the sn_list!"); + None } - Ok(status) => match status { - SnStatus::Online => { - info!("reset bdt sn list success!"); - let bdt_stack = bdt_stack.clone(); - async_std::task::spawn(async move { - let _ = ping_clients.wait_offline().await; - retry_sn_list_when_offline( - bdt_stack.clone(), - ping_clients, - Duration::from_secs(30), - ); - }); - } - SnStatus::Offline => { - error!("reset bdt sn list error! offline"); + }; + + bdt_stack.reset_known_sn(config_sn_list); + + if let Some(sn_list) = sn_list { + let ping_clients = bdt_stack.reset_sn_list(sn_list); + Self::wait_sn_online(&bdt_stack, ping_clients).await; + } + } + } + + pub async fn wait_sn_online(bdt_stack: &StackGuard, ping_clients: PingClients) { + // Waiting for SN to go online + info!( + "now will wait for sn online {}......", + bdt_stack.local_device_id() + ); + let begin = std::time::Instant::now(); + match ping_clients.wait_online().await { + Err(e) => { + error!( + "bdt stack wait sn online failed! {}, during={}ms, {}", + bdt_stack.local_device_id(), + begin.elapsed().as_millis(), + e + ); + } + Ok(status) => match status { + SnStatus::Online => { + info!( + "bdt stack sn online success! {}, during={}ms", + bdt_stack.local_device_id(), + begin.elapsed().as_millis(), + ); + let bdt_stack = bdt_stack.clone(); + async_std::task::spawn(async move { + let _ = ping_clients.wait_offline().await; retry_sn_list_when_offline( bdt_stack.clone(), ping_clients, - Duration::from_secs(30), + std::time::Duration::from_secs(30), ); - } - }, - } + }); + } + SnStatus::Offline => { + error!( + "bdt stack wait sn online failed! {}, during={}ms, offline", + bdt_stack.local_device_id(), + begin.elapsed().as_millis(), + ); + retry_sn_list_when_offline( + bdt_stack.clone(), + ping_clients, + std::time::Duration::from_secs(30), + ); + } + }, } } } diff --git a/src/component/cyfs-bdt-ext/src/stack/param.rs b/src/component/cyfs-bdt-ext/src/stack/param.rs index 8934f311d..c287f2cba 100644 --- a/src/component/cyfs-bdt-ext/src/stack/param.rs +++ b/src/component/cyfs-bdt-ext/src/stack/param.rs @@ -1,5 +1,50 @@ use cyfs_base::*; +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum SNMode { + Normal, + None, +} + +impl SNMode { + pub fn as_str(&self) -> &str { + match *self { + Self::Normal => "normal", + Self::None => "none", + } + } +} + +impl Default for SNMode { + fn default() -> Self { + Self::Normal + } +} + +impl std::fmt::Display for SNMode { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl std::str::FromStr for SNMode { + type Err = BuckyError; + + fn from_str(str: &str) -> BuckyResult { + let ret = match str { + "normal" => Self::Normal, + "none" => Self::None, + _ => { + let msg = format!("unknown SNMode {}", str); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + } + }; + + Ok(ret) + } +} + #[derive(Clone)] pub struct BdtStackParams { pub device: Device, @@ -9,4 +54,5 @@ pub struct BdtStackParams { pub known_device: Vec, pub known_passive_pn: Vec, pub udp_sn_only: Option, -} \ No newline at end of file + pub sn_mode: SNMode, +} diff --git a/src/component/cyfs-bdt-ext/src/stack/stack.rs b/src/component/cyfs-bdt-ext/src/stack/stack.rs index 32050c4ea..c854f3c58 100644 --- a/src/component/cyfs-bdt-ext/src/stack/stack.rs +++ b/src/component/cyfs-bdt-ext/src/stack/stack.rs @@ -1,6 +1,8 @@ use super::com::*; use super::param::*; use crate::context::ContextManager; +use crate::sn::BdtStackSNHelper; + use cyfs_base::*; use cyfs_bdt::*; use cyfs_chunk_cache::{ChunkManager, ChunkManagerRef}; @@ -74,6 +76,20 @@ impl BdtStackHelper { bdt_params.config.interface.udp.sn_only = sn_only; } + // select sn_list via the sn_mode config + let wait_online; + let sn_list = match params.sn_mode { + SNMode::Normal => { + wait_online = true; + Some(params.known_sn.clone()) + } + SNMode::None => { + wait_online = false; + warn!("sn_mode is none, now will clear the sn_list!"); + None + } + }; + bdt_params.known_sn = Some(params.known_sn); if !params.known_device.is_empty() { @@ -84,7 +100,7 @@ impl BdtStackHelper { } bdt_params.outer_cache = Some(device_cache); bdt_params.chunk_store = Some(chunk_store); - + bdt_params.ndn_event = ndn_event; let ret = Stack::open(params.device, params.secret, bdt_params).await; @@ -96,52 +112,15 @@ impl BdtStackHelper { let bdt_stack = ret.unwrap(); - // 等待sn上线 - info!( - "now will wait for sn online {}......", - bdt_stack.local_device_id() - ); - let begin = std::time::Instant::now(); - let ping_clients = bdt_stack.sn_client().ping(); - match ping_clients.wait_online().await { - Err(e) => { - error!( - "bdt stack wait sn online failed! {}, during={}ms, {}", - bdt_stack.local_device_id(), - begin.elapsed().as_millis(), - e - ); - } - Ok(status) => match status { - SnStatus::Online => { - info!( - "bdt stack sn online success! {}, during={}ms", - bdt_stack.local_device_id(), - begin.elapsed().as_millis(), - ); - let bdt_stack = bdt_stack.clone(); - async_std::task::spawn(async move { - let _ = ping_clients.wait_offline().await; - retry_sn_list_when_offline( - bdt_stack.clone(), - ping_clients, - std::time::Duration::from_secs(30), - ); - }); - } - SnStatus::Offline => { - error!( - "bdt stack wait sn online failed! {}, during={}ms, offline", - bdt_stack.local_device_id(), - begin.elapsed().as_millis(), - ); - retry_sn_list_when_offline( - bdt_stack.clone(), - ping_clients, - std::time::Duration::from_secs(30), - ); - } - }, + // apply the sn list + let ping_clients = if let Some(sn_list) = sn_list { + bdt_stack.sn_client().reset_sn_list(sn_list) + } else { + bdt_stack.sn_client().ping() + }; + + if wait_online { + BdtStackSNHelper::wait_sn_online(&bdt_stack, ping_clients).await; } Ok(bdt_stack) diff --git a/src/component/cyfs-stack-loader/src/bdt_loader.rs b/src/component/cyfs-stack-loader/src/bdt_loader.rs index 670086932..bfe863d86 100644 --- a/src/component/cyfs-stack-loader/src/bdt_loader.rs +++ b/src/component/cyfs-stack-loader/src/bdt_loader.rs @@ -1,5 +1,6 @@ use crate::VAR_MANAGER; use cyfs_base::*; +use cyfs_bdt_ext::SNMode; use cyfs_util::TomlHelper; use std::str::FromStr; @@ -13,6 +14,9 @@ const BDT_PORT_KEY: &str = "CYFS_BDT_PORT"; // udp_sn_only const UDP_SN_ONLY_KEY: &str = "CYFS_UDP_SN_ONLY"; +// sn_mode +const SN_MODE_KEY: &str = "CYFS_SN_MODE"; + // bdt层的配置参数 pub(crate) struct BdtParams { pub device: String, @@ -24,6 +28,8 @@ pub(crate) struct BdtParams { // disable udp transport but sn online via udp pub udp_sn_only: Option, + + pub sn_mode: SNMode, } impl Default for BdtParams { @@ -34,6 +40,7 @@ impl Default for BdtParams { endpoint: vec![], tcp_port_mapping: None, udp_sn_only: None, + sn_mode: SNMode::default(), } } } @@ -123,6 +130,9 @@ impl BdtConfigLoader { "udp_sn_only" => { self.params.udp_sn_only = Some(TomlHelper::decode_from_boolean(v)?); } + "sn_mode" => { + self.params.sn_mode = TomlHelper::decode_from_string(v)?; + } _ => { warn!("unknown stack.bdt.config field: {}", k.as_str()); } @@ -133,6 +143,10 @@ impl BdtConfigLoader { self.params.udp_sn_only = Some(udp_sn_only); } + if let Some(sn_mode) = Self::load_sn_mode_from_env() { + self.params.sn_mode = sn_mode; + } + Ok(()) } @@ -349,4 +363,25 @@ impl BdtConfigLoader { Err(_) => None, } } + + fn load_sn_mode_from_env() -> Option { + match std::env::var(SN_MODE_KEY) { + Ok(val) => { + info!( + "got sn_mode from env var: env={}, val={}", + SN_MODE_KEY, val + ); + + let value = val.trim(); + match SNMode::from_str(&value) { + Ok(v) => Some(v), + Err(e) => { + error!("invalid sn_mode value got from env! val={}, {}", value, e); + None + } + } + } + Err(_) => None, + } + } } diff --git a/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs b/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs index 919bf0194..8c32bfe22 100644 --- a/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs +++ b/src/component/cyfs-stack-loader/src/cyfs_loader_config.rs @@ -39,6 +39,7 @@ const BDT_CONFIG: &str = r#" #tcp_port_mapping = 0 device = "${device_file_name}" #udp_sn_only = false +#sn_mode = "normal" ${endpoints} "#; @@ -73,7 +74,7 @@ type = "ws" enable = ${ws_enable} listen = "${ws_listener}" -# bdt配置部分,可替换默认值 +# bdt configuration part, can replace the default value ${bdt_config} "#; diff --git a/src/component/cyfs-stack-loader/src/stack_info.rs b/src/component/cyfs-stack-loader/src/stack_info.rs index c7f048a86..13c49c032 100644 --- a/src/component/cyfs-stack-loader/src/stack_info.rs +++ b/src/component/cyfs-stack-loader/src/stack_info.rs @@ -153,6 +153,7 @@ impl StackInfo { known_passive_pn: init_pn_peers, known_device: init_known_peers, udp_sn_only: self.bdt_params.udp_sn_only, + sn_mode: self.bdt_params.sn_mode, }; bdt_param diff --git a/src/component/cyfs-stack/src/config/sn_config.rs b/src/component/cyfs-stack/src/config/sn_config.rs index 2d4eccd96..052a37ecb 100644 --- a/src/component/cyfs-stack/src/config/sn_config.rs +++ b/src/component/cyfs-stack/src/config/sn_config.rs @@ -82,11 +82,12 @@ impl SNConfigManager { meta_cache, root_state, noc, - config, sn_list: Arc::new(Mutex::new(vec![])), coll: Arc::new(OnceCell::new()), - bdt_stack: BdtStackSNHelper::new(), + bdt_stack: BdtStackSNHelper::new(config.get_bdt_params().sn_mode), + + config, } } diff --git a/src/component/cyfs-stack/src/root_state_api/core/test.rs b/src/component/cyfs-stack/src/root_state_api/core/test.rs index b32829707..c19d5617e 100644 --- a/src/component/cyfs-stack/src/root_state_api/core/test.rs +++ b/src/component/cyfs-stack/src/root_state_api/core/test.rs @@ -190,6 +190,7 @@ async fn create_global_state_manager() -> GlobalStateManager { known_device: vec![], known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Default, }; let config = StackGlobalConfig::new(params, bdt_params); From fd5068a3689bd84caf1becf837f87570a88fb2d3 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 16:28:17 +0800 Subject: [PATCH 338/553] Fix task type mismatch error for chunk task in trans service --- .../src/trans_api/local/download_task_tracker.rs | 2 ++ .../src/trans_api/local/task/download_task.rs | 2 +- .../cyfs-task-manager/src/task_manager.rs | 14 +++++++++++++- src/component/cyfs-util/src/util/toml_helper.rs | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs b/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs index 0c134bcc9..d315fc92a 100644 --- a/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs +++ b/src/component/cyfs-stack/src/trans_api/local/download_task_tracker.rs @@ -14,6 +14,8 @@ pub trait DownloadTaskTracker { #[async_trait::async_trait] impl DownloadTaskTracker for SqlConnection { async fn add_task_info(&mut self, task_id: &TaskId, context_id: &Option, task_status: TaskStatus, dec_list: Vec<(DeviceId, ObjectId)>) -> BuckyResult<()> { + info!("task tracker add task: id={}, context={:?}, dec_list={:?}", task_id, context_id, dec_list); + for (source, dec) in dec_list.iter() { let sql = r#"insert into download_task_tracker (source, dec_id, task_id, context_id, task_status) values (?1, ?2, ?3, ?4, ?5)"#; let context_id = if context_id.is_some() { diff --git a/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs b/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs index 33c1242d5..4b9d76842 100644 --- a/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs +++ b/src/component/cyfs-stack/src/trans_api/local/task/download_task.rs @@ -410,7 +410,7 @@ impl Task for DownloadFileTask { } fn get_task_type(&self) -> TaskType { - DOWNLOAD_FILE_TASK + self.params.task_type } fn get_task_category(&self) -> TaskCategory { diff --git a/src/component/cyfs-task-manager/src/task_manager.rs b/src/component/cyfs-task-manager/src/task_manager.rs index ec3054da3..b623941ce 100644 --- a/src/component/cyfs-task-manager/src/task_manager.rs +++ b/src/component/cyfs-task-manager/src/task_manager.rs @@ -162,10 +162,22 @@ impl TaskManager { match self.get_task_factory(&task_type) { Some(factory) => { let param = task_param.to_vec()?; - let mut task = factory.create(param.as_slice()).await?; + let mut task = factory.create(param.as_slice()).await.map_err(|e| { + let msg = format!("create task failed! dec={}, source={}, task_type={}, {}", dec_id, source, task_type, e); + error!("{}", msg); + BuckyError::new(e.code(), msg) + })?; + + if task.get_task_type() != task_type { + let msg = format!("create task but task_type mismatch! dec={}, source={}, create task_type={}, got={}", dec_id, source, task_type, task.get_task_type()); + error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + if task.need_persist() { task.set_task_store(self.task_store.clone()).await; } + let task_id = task.get_task_id(); let _locker = Locker::get_locker(format!("task_manager_{}", task_id.to_string())).await; { diff --git a/src/component/cyfs-util/src/util/toml_helper.rs b/src/component/cyfs-util/src/util/toml_helper.rs index 67545c2c9..80b8ac116 100644 --- a/src/component/cyfs-util/src/util/toml_helper.rs +++ b/src/component/cyfs-util/src/util/toml_helper.rs @@ -19,7 +19,7 @@ impl TomlHelper { let v = T::from_str(v.as_str().unwrap()).map_err(|e| { let msg = format!( - "parse json string error: value={}, {}", + "parse toml string error: value={}, {}", v.as_str().unwrap(), e ); From b6a7f8407645cb4a463853ee278a6a827565533c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 17:06:30 +0800 Subject: [PATCH 339/553] Improve test cases --- .../cyfs-stack-test/src/case/app_manager.rs | 15 +++++++++-- .../cyfs-stack-test/src/case/mnemonic.rs | 4 +++ src/tests/cyfs-stack-test/src/case/mod.rs | 26 ++++++++----------- src/tests/cyfs-stack-test/src/case/trans.rs | 5 ++++ src/tests/cyfs-stack-test/src/main.rs | 2 +- src/tools/pack-tools/Cargo.toml | 2 +- 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/tests/cyfs-stack-test/src/case/app_manager.rs b/src/tests/cyfs-stack-test/src/case/app_manager.rs index 3083d45c4..20ed9a93c 100644 --- a/src/tests/cyfs-stack-test/src/case/app_manager.rs +++ b/src/tests/cyfs-stack-test/src/case/app_manager.rs @@ -24,7 +24,15 @@ async fn register_app(stack: &SharedCyfsStack, dec_id: &ObjectId) { let action_id = action.desc().calculate_id(); let buf = action.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + let ret = stack.non_service().post_object(req.clone()).await; + assert!(ret.is_err()); + + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_APP_VIRTUAL_PATH.to_owned()); + let ret = stack.non_service().post_object(req.clone()).await; + assert!(ret.is_err()); + + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await.unwrap(); assert!(resp.object.is_none()); @@ -41,8 +49,11 @@ async fn unregister_app(stack: &SharedCyfsStack, dec_id: &ObjectId) { let action_id = action.desc().calculate_id(); let buf = action.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(None, action_id, buf); + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_APP_VIRTUAL_PATH.to_owned()); + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await.unwrap(); + assert!(resp.object.is_none()); info!("register dec success!"); diff --git a/src/tests/cyfs-stack-test/src/case/mnemonic.rs b/src/tests/cyfs-stack-test/src/case/mnemonic.rs index 595178eee..ba97751e7 100644 --- a/src/tests/cyfs-stack-test/src/case/mnemonic.rs +++ b/src/tests/cyfs-stack-test/src/case/mnemonic.rs @@ -26,6 +26,10 @@ async fn check_user() { user2.user_data().check_equal(&USER2_DATA); } +pub async fn test() { + check_user().await; +} + #[cfg(test)] mod test { #[test] diff --git a/src/tests/cyfs-stack-test/src/case/mod.rs b/src/tests/cyfs-stack-test/src/case/mod.rs index f1d5bde1b..2c4edf860 100644 --- a/src/tests/cyfs-stack-test/src/case/mod.rs +++ b/src/tests/cyfs-stack-test/src/case/mod.rs @@ -42,7 +42,8 @@ pub async fn test() { shared_stack::test().await; }); - + test_restart().await; + // role::test().await; // crypto::test().await; @@ -59,30 +60,25 @@ pub async fn test() { call::test().await; object_meta_access::test().await; - async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; - - return; - - test_restart().await; - test_obj_searcher::test().await; + events::test().await; + zone::test().await; + // mnemonic::test().await; + app_manager::test().await; + trans::test().await; - // test_drive::test().await; + async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; - events::test().await; + return; - zone::test().await; + + // test_drive::test().await; non_handlers::test().await; //non_file::test().await; - trans::test().await; - router_handlers::test().await; - //mnemonic::test().await; - app_manager::test().await; - admin::test().await; sync::test().await; diff --git a/src/tests/cyfs-stack-test/src/case/trans.rs b/src/tests/cyfs-stack-test/src/case/trans.rs index e61c9c394..a074770db 100644 --- a/src/tests/cyfs-stack-test/src/case/trans.rs +++ b/src/tests/cyfs-stack-test/src/case/trans.rs @@ -603,6 +603,8 @@ async fn test_shared_data() { unreachable!(); } + info!("pub chunk as shared data success!"); + { let req = NDNGetDataRequest::new_ndc(id.object_id().to_owned(), None); @@ -620,7 +622,10 @@ async fn test_shared_data() { let new_id = shared_chunk.calculate_id(); assert_eq!(new_id, id); } + + info!("test shared data success!"); } + async fn download_chunk(chunk_id: ChunkId, chunk: Vec, device_id: DeviceId) { let data_dir = cyfs_util::get_app_data_dir("cyfs-stack-test").join("trans"); let local_path = data_dir.join("test-chunk"); diff --git a/src/tests/cyfs-stack-test/src/main.rs b/src/tests/cyfs-stack-test/src/main.rs index eb8730f22..3edaa6874 100644 --- a/src/tests/cyfs-stack-test/src/main.rs +++ b/src/tests/cyfs-stack-test/src/main.rs @@ -12,7 +12,7 @@ async fn main_run() { CyfsLoggerBuilder::new_app("cyfs-stack-test") .level("debug") .console("debug") - .enable_bdt(Some("error"), Some("error")) + .enable_bdt(Some("debug"), Some("debug")) .disable_file_config(true) .file(true) .build() diff --git a/src/tools/pack-tools/Cargo.toml b/src/tools/pack-tools/Cargo.toml index 0511ad8e4..2a22c5de5 100644 --- a/src/tools/pack-tools/Cargo.toml +++ b/src/tools/pack-tools/Cargo.toml @@ -14,5 +14,5 @@ clap = "2.34.0" simple_logger = "2.1" log = "0.4" sha2 = "0.8" -zip = "0.6.2" +zip = "0.6" cyfs-base = { path = "../../component/cyfs-base" } From b93ca4c165f2d0e14e3abf00f22426e21dab74fd Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 17:19:58 +0800 Subject: [PATCH 340/553] Fix the bug that the full version cannot be parsed correctly when service_version = "default" --- .../ood-daemon/src/config_repo/meta.rs | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index e9d54d2c2..d260420a5 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -333,29 +333,35 @@ impl DeviceConfigMetaRepo { let service = self.load_service(service_id).await?; // first find the correct version - let config_version = match &get_system_config().service_version { - ServiceVersion::Default => version_in_service_list.to_owned(), - ServiceVersion::Specific(v) => v.clone(), - }; + let version = match &get_system_config().service_version { + ServiceVersion::Default => { + // direct use the full version configed in the service list + version_in_service_list + }, + ServiceVersion::Specific(config_version) => { + let preview = match get_system_config().preview { + true => Some("preview"), + false => None, + }; + + let (version, semver) = service.find_version(&config_version, preview).map_err(|e| { + let msg = format!( + "find version from service object failed! id={}, configed version={}, preview={:?}, {}", + service_id, config_version, preview, e, + ); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::NotFound, msg) + })?; + + // check if the target service version is valid + SemVerEpochCheck::check_version_with_semver_epoch(&semver)?; - let preview = match get_system_config().preview { - true => Some("preview"), - false => None, + version + } }; - let (version, semver) = service.find_version(&config_version, preview).map_err(|e| { - let msg = format!( - "find version from service object failed! id={}, configed version={}, preview={:?}, {}", - service_id, config_version, preview, e, - ); - error!("{}", msg); - - BuckyError::new(BuckyErrorCode::NotFound, msg) - })?; - - // check if the target service version is valid - SemVerEpochCheck::check_version_with_semver_epoch(&semver)?; - + let ret = service.find_source(&version); if ret.is_err() { let msg = format!( From b5b970cabd5e1d47a83fbf02358bb09c195b9a8e Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 18:03:01 +0800 Subject: [PATCH 341/553] Fix the bug when system-config's service_version = "default" updated cannot trigger the device-config updating's bug in some cases --- .../ood-daemon/src/config/system_config.rs | 4 ++ .../ood-daemon/src/config_repo/meta.rs | 42 +++++++++++-------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 7ec69d578..9ae346c60 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -41,6 +41,10 @@ impl SystemConfig { } } + pub fn compare(&self, other: &SystemConfig) -> bool { + *self == *other + } + pub async fn load_config(&mut self) -> BuckyResult<()> { let config_file = PATHS.system_config.clone(); diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index d260420a5..90f3aa98e 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -11,6 +11,7 @@ use cyfs_util::LOCAL_DEVICE_MANAGER; use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::str::FromStr; +use std::sync::Arc; #[derive(Serialize, Deserialize)] struct DeviceConfigGenerator { @@ -123,6 +124,7 @@ impl DeviceConfigGenerator { } struct LocalCache { + system_config: Arc, service_list: AppList, device_config_str: String, } @@ -156,14 +158,15 @@ impl DeviceConfigMetaRepo { } pub fn init(&self) -> BuckyResult<()> { - Self::gen_service_list_id()?; + // just for verify system-config on init + Self::gen_service_list_id(&get_system_config())?; Ok(()) } - fn gen_service_list_id() -> BuckyResult { - let device_id = Self::load_device(&get_system_config().config_desc)?; - let service_list_version = get_system_config().service_list_version.to_string(); + fn gen_service_list_id(system_config: &Arc) -> BuckyResult { + let device_id = Self::load_device(&system_config.config_desc)?; + let service_list_version = system_config.service_list_version.to_string(); // 计算ServiceList对象id let service_list_id = AppList::generate_id( @@ -174,7 +177,7 @@ impl DeviceConfigMetaRepo { info!( "device config repo: config_desc={}, device_id={}, service_list_id={}, version={}", - get_system_config().config_desc, + system_config.config_desc, device_id, service_list_id, service_list_version @@ -196,8 +199,8 @@ impl DeviceConfigMetaRepo { Ok(ret) } - async fn load_service_list(&self) -> BuckyResult { - let service_list_id = Self::gen_service_list_id()?; + async fn load_service_list(&self, system_config: &Arc,) -> BuckyResult { + let service_list_id = Self::gen_service_list_id(system_config)?; let ret = MetaClientHelper::get_object(&self.meta_client, &service_list_id).await?; if ret.is_none() { let msg = format!( @@ -288,8 +291,8 @@ impl DeviceConfigMetaRepo { } // 从dir里面加载当前target对应的fid - fn load_fid(&self, dir_id: &str, dir: Dir) -> BuckyResult { - let mut target = get_system_config().target.clone(); + fn load_fid(&self, system_config: &Arc, dir_id: &str, dir: Dir) -> BuckyResult { + let mut target = system_config.target.clone(); match dir.desc().content().obj_list() { NDNObjectInfo::ObjList(entries) => { @@ -326,6 +329,7 @@ impl DeviceConfigMetaRepo { async fn load_service_fid( &self, + system_config: &Arc, device_config: &mut DeviceConfigGenerator, service_id: &ObjectId, version_in_service_list: &str, @@ -333,13 +337,13 @@ impl DeviceConfigMetaRepo { let service = self.load_service(service_id).await?; // first find the correct version - let version = match &get_system_config().service_version { + let version = match &system_config.service_version { ServiceVersion::Default => { // direct use the full version configed in the service list version_in_service_list }, ServiceVersion::Specific(config_version) => { - let preview = match get_system_config().preview { + let preview = match system_config.preview { true => Some("preview"), false => None, }; @@ -381,7 +385,7 @@ impl DeviceConfigMetaRepo { // 查找当前平台对应的fid let dir_id = dir_id.to_string(); - let fid = self.load_fid(&dir_id, dir)?; + let fid = self.load_fid(&system_config, &dir_id, dir)?; // 更新 device_config.update_service(&service, &fid, version); @@ -391,6 +395,7 @@ impl DeviceConfigMetaRepo { async fn gen_service_list_to_device_config( &self, + system_config: &Arc, service_list: &AppList, ) -> BuckyResult { let mut device_config = DeviceConfigGenerator::new(); @@ -399,7 +404,7 @@ impl DeviceConfigMetaRepo { let version = status.version(); - self.load_service_fid(&mut device_config, id.object_id(), version) + self.load_service_fid(&system_config, &mut device_config, id.object_id(), version) .await .map_err(|e| { error!( @@ -440,21 +445,23 @@ impl DeviceConfigMetaRepo { } async fn fetch_inner(&self) -> BuckyResult { + let current_system_config = get_system_config(); + // 从mete-chain拉取对应的service_list - let service_list = self.load_service_list().await?; + let service_list = self.load_service_list(¤t_system_config).await?; // Only in the default version case, it will use the cache of servicelist - if get_system_config().service_version.is_default() { + if current_system_config.service_version.is_default() { let cache = self.cache.lock().unwrap(); if let Some(cache) = &*cache { - if Self::compare_service_list(&cache.service_list, &service_list) { + if cache.system_config.compare(¤t_system_config) && Self::compare_service_list(&cache.service_list, &service_list) { return Ok(cache.device_config_str.clone()); } } } let mut device_config = self - .gen_service_list_to_device_config(&service_list) + .gen_service_list_to_device_config(¤t_system_config, &service_list) .await?; device_config.sort(); @@ -463,6 +470,7 @@ impl DeviceConfigMetaRepo { { let mut cache = self.cache.lock().unwrap(); *cache = Some(LocalCache { + system_config: current_system_config, service_list, device_config_str: device_config_str.clone(), }); From 09bd5bcf1f84f6b26a97536bd4b59dc05195b020 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 18:16:47 +0800 Subject: [PATCH 342/553] Fix the bug that the modification of system-config cannot take effect immediately during the check loop --- src/service/ood-daemon/src/daemon/daemon.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/daemon/daemon.rs b/src/service/ood-daemon/src/daemon/daemon.rs index fb05c73ca..9b967b499 100644 --- a/src/service/ood-daemon/src/daemon/daemon.rs +++ b/src/service/ood-daemon/src/daemon/daemon.rs @@ -9,7 +9,7 @@ use ood_control::OOD_CONTROLLER; use async_std::task; use futures::future::{AbortHandle, Abortable}; -use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::atomic::{AtomicU64, Ordering, AtomicBool}; use std::sync::{Arc, Mutex}; use std::time::Duration; @@ -49,6 +49,7 @@ pub struct Daemon { no_monitor: bool, last_active: Arc, check_update_waker: Arc>>, + wakedup_once: Arc, } impl Daemon { @@ -59,6 +60,7 @@ impl Daemon { no_monitor, last_active: Arc::new(ActionActive::default()), check_update_waker: Arc::new(Mutex::new(None)), + wakedup_once: Arc::new(AtomicBool::new(false)), } } @@ -92,6 +94,9 @@ impl Daemon { if let Some(abort_handle) = self.check_update_waker.lock().unwrap().take() { info!("will wakeup check update now!"); abort_handle.abort(); + } else { + info!("wakeup check udpate but still in checking loop! now will mark"); + self.wakedup_once.store(true, Ordering::SeqCst); } } @@ -186,11 +191,16 @@ impl Daemon { } } - // 检查绑定状态 + let ret = self.wakedup_once.swap(false, Ordering::SeqCst); + if ret { + continue; + } + let timer = task::sleep(Duration::from_secs(60 * 30)); let (abort_handle, abort_registration) = AbortHandle::new_pair(); + // check ood's binding status if !OOD_CONTROLLER.is_bind() { *notify.abort_handle.lock().unwrap() = Some(abort_handle.clone()); } @@ -198,6 +208,7 @@ impl Daemon { match Abortable::new(timer, abort_registration).await { Ok(_) => { + self.check_update_waker.lock().unwrap().take(); debug!("check update loop wait timeout, now will check once"); } Err(futures::future::Aborted { .. }) => { From b6ab5b927674efeb68ea2994ab81021fd97ca3a3 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Mon, 27 Feb 2023 21:11:48 +0800 Subject: [PATCH 343/553] Clear meta cache when service list changed --- src/component/cyfs-core/src/app/dec_app.rs | 12 ++++++------ .../ood-daemon/src/config/system_config.rs | 3 ++- .../ood-daemon/src/config_repo/meta.rs | 19 ++++++++++++++++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/component/cyfs-core/src/app/dec_app.rs b/src/component/cyfs-core/src/app/dec_app.rs index e5a0d9b8a..578ee27c9 100644 --- a/src/component/cyfs-core/src/app/dec_app.rs +++ b/src/component/cyfs-core/src/app/dec_app.rs @@ -219,8 +219,8 @@ impl DecAppObj for DecApp { let req_version = semver::VersionReq::parse(req_semver).map_err(|e| { let msg = format!( - "invalid semver request string! id={}, name={}, value={}, {}", - id, name, req_semver, e + "invalid semver request string! id={}, name={}, value={}, pre={:?}, {}", + id, name, req_semver, pre, e ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -241,8 +241,8 @@ impl DecAppObj for DecApp { for (version, new_version) in list { let mut semver = semver::Version::parse(&new_version).map_err(|e| { let msg = format!( - "invalid semver string! id={}, name={}, value={}, {}", - id, name, version, e, + "invalid semver string! id={}, name={}, value={}, pre={:?}, {}", + id, name, version, pre, e, ); error!("{}", msg); BuckyError::new(BuckyErrorCode::InvalidFormat, msg) @@ -267,8 +267,8 @@ impl DecAppObj for DecApp { let ret = semver_list.iter().find(|(version, semver)| { if req_version.matches(semver) { info!( - "app version matched: id={}, name={}, req={}, got={}", - id, name, req_semver, version + "app version matched: id={}, name={}, req={}, got={}, prev={:?}", + id, name, req_semver, version, pre, ); true } else { diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 9ae346c60..ceb3344e9 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -41,10 +41,11 @@ impl SystemConfig { } } + // return true if the same pub fn compare(&self, other: &SystemConfig) -> bool { *self == *other } - + pub async fn load_config(&mut self) -> BuckyResult<()> { let config_file = PATHS.system_config.clone(); diff --git a/src/service/ood-daemon/src/config_repo/meta.rs b/src/service/ood-daemon/src/config_repo/meta.rs index 90f3aa98e..e261c358a 100644 --- a/src/service/ood-daemon/src/config_repo/meta.rs +++ b/src/service/ood-daemon/src/config_repo/meta.rs @@ -450,16 +450,33 @@ impl DeviceConfigMetaRepo { // 从mete-chain拉取对应的service_list let service_list = self.load_service_list(¤t_system_config).await?; + let mut service_list_is_the_same = None; + // Only in the default version case, it will use the cache of servicelist if current_system_config.service_version.is_default() { let cache = self.cache.lock().unwrap(); if let Some(cache) = &*cache { - if cache.system_config.compare(¤t_system_config) && Self::compare_service_list(&cache.service_list, &service_list) { + service_list_is_the_same = Some(Self::compare_service_list(&cache.service_list, &service_list)); + if cache.system_config.compare(¤t_system_config) && service_list_is_the_same == Some(true) { return Ok(cache.device_config_str.clone()); } } } + { + if service_list_is_the_same.is_none() { + let cache = self.cache.lock().unwrap(); + if let Some(cache) = &*cache { + service_list_is_the_same = Some(Self::compare_service_list(&cache.service_list, &service_list)); + } + } + + if service_list_is_the_same == Some(false) { + warn!("service list changed! now will clear meta cache"); + self.clear_cache().await; + } + } + let mut device_config = self .gen_service_list_to_device_config(¤t_system_config, &service_list) .await?; From 4ac580f355d032bcbeeb77dbf2f253471c44780d Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 28 Feb 2023 09:33:39 +0800 Subject: [PATCH 344/553] Switch ndn get_data to normal http requestor instead of surf requestor --- src/component/cyfs-lib/src/stack/stack.rs | 55 +++++++++++++++-------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 5de037faa..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -76,7 +76,7 @@ impl Drop for ObjectServices { pub struct SharedCyfsStack { param: SharedCyfsStackParam, - // 所属的dec_id + // The dec_id it belongs to dec_id: SharedObjectStackDecID, services: Arc, @@ -88,7 +88,7 @@ pub struct SharedCyfsStack { // router events router_events: RouterEventManager, - // 当前协议栈的device + // Device of the current protocol stack device_info: Arc>>, // uni_stack @@ -161,10 +161,10 @@ impl CyfsStackRequestorConfig { pub struct SharedCyfsStackParam { pub dec_id: Option, - // 基于http协议的服务地址 + // Service address based on the HTTP protocol pub service_url: Url, - // 基于websocket协议的服务地址 + // Service address based on the WebSocket protocol pub ws_url: Url, pub event_type: CyfsStackEventType, @@ -186,7 +186,7 @@ impl SharedCyfsStackParam { Self::default(dec_id) } - // 默认切换到websocket模式 + // Switch to the websocket mode by default pub fn default(dec_id: Option) -> Self { let (service_url, ws_url) = Self::gen_url(cyfs_base::NON_STACK_HTTP_PORT, cyfs_base::NON_STACK_WS_PORT); @@ -200,7 +200,7 @@ impl SharedCyfsStackParam { } } - // 提供给cyfs-runtime使用的shareobjectstack + // SharedCyfsStack provided to Cyfs-Runtime pub fn default_runtime(dec_id: Option) -> Self { let (service_url, ws_url) = Self::gen_url( cyfs_base::CYFS_RUNTIME_NON_STACK_HTTP_PORT, @@ -216,7 +216,7 @@ impl SharedCyfsStackParam { } } - // 打开指定端口的shareobjectstack + // Open shared stack of the specified port pub fn gen(dec_id: Option, http_port: u16, ws_port: u16) -> Self { let (service_url, ws_url) = Self::gen_url(http_port, ws_port); @@ -263,6 +263,7 @@ struct RequestorHolder { requestor_config: CyfsStackRequestorConfig, http: Option, ws: Option, + data: Option, } impl RequestorHolder { @@ -271,6 +272,7 @@ impl RequestorHolder { requestor_config, http: None, ws: None, + data: None, } } @@ -283,7 +285,7 @@ impl RequestorHolder { CyfsStackRequestorType::Http => { self.http .get_or_insert_with(|| { - // 基于标准http的requestor + // Requestor based on standard http let addr = format!( "{}:{}", param.service_url.host_str().unwrap(), @@ -306,7 +308,7 @@ impl RequestorHolder { CyfsStackRequestorType::WebSocket => { self.ws .get_or_insert_with(|| { - // 基于websocket协议的requestor + // Requestor based on the WebSocket protocol Arc::new(Box::new(WSHttpRequestor::new(param.ws_url.clone()))) }) .clone() @@ -314,6 +316,21 @@ impl RequestorHolder { } } + fn data_requestor(&mut self, param: &SharedCyfsStackParam) -> HttpRequestorRef { + self.data + .get_or_insert_with(|| { + // Requestor based on standard HTTP + let addr = format!( + "{}:{}", + param.service_url.host_str().unwrap(), + param.service_url.port().unwrap() + ); + + Arc::new(Box::new(TcpHttpRequestor::new(&addr))) + }) + .clone() + } + async fn stop(&self) { if let Some(requestor) = &self.http { requestor.stop().await; @@ -383,7 +400,7 @@ impl SharedCyfsStack { let requestor = requestor_holder.select_requestor(¶m, ¶m.requestor_config.ndn_service); let data_requestor = - requestor_holder.select_requestor(¶m, &CyfsStackRequestorType::Http); + requestor_holder.data_requestor(¶m); let ndn_service = NDNRequestor::new(Some(dec_id.clone()), requestor, Some(data_requestor)); // sync @@ -433,7 +450,7 @@ impl SharedCyfsStack { local_cache_meta, }); - // 初始化对应的事件处理器,二选一 + // Initialize the corresponding event processor, choose one in the two choices let router_handlers = match ¶m.event_type { CyfsStackEventType::WebSocket(ws_url) => { RouterHandlerManager::new(Some(dec_id.clone()), ws_url.clone()) @@ -446,7 +463,7 @@ impl SharedCyfsStack { } }; - // 缓存所有processors,用以uni_stack直接返回使用 + // Caches all processors, use UNI_STACK to return to use directly let processors = Arc::new(CyfsStackProcessors { non_service: services.non_service.clone_processor(), ndn_service: services.ndn_service.clone_processor(), @@ -502,7 +519,7 @@ impl SharedCyfsStack { Self::open(param).await } - // 等待协议栈上线 + // Waiting for the protocol stack online pub async fn wait_online(&self, timeout: Option) -> BuckyResult<()> { let this = self.clone(); let ft = async move { @@ -512,7 +529,7 @@ impl SharedCyfsStack { Err(e) => { match e.code() { BuckyErrorCode::ConnectFailed | BuckyErrorCode::Timeout => { - // 需要重试 + // Need to retry } _ => { error!("stack online failed! {}", e); @@ -540,7 +557,7 @@ impl SharedCyfsStack { } pub async fn online(&self) -> BuckyResult<()> { - // 获取当前协议栈的device_id + // Get Device_id of the current protocol stack let req = UtilGetDeviceOutputRequest::new(); let resp = self.services.util_service.get_device(req).await?; @@ -551,7 +568,7 @@ impl SharedCyfsStack { Ok(()) } - // 如果初始化时候没有指定,那么可以延迟绑定一次 + // If it is not specified during initialization, it can be delayed init once pub fn bind_dec(&self, dec_id: ObjectId) { self.dec_id.set(dec_id).unwrap(); } @@ -560,7 +577,7 @@ impl SharedCyfsStack { self.dec_id.get() } - // 下面两个接口必须调用onlien成功一次之后才可以调用 + // The following two interfaces must be called online successfully before you can call them pub fn local_device_id(&self) -> DeviceId { self.device_info.read().unwrap().as_ref().unwrap().0.clone() } @@ -601,7 +618,7 @@ impl SharedCyfsStack { &self.router_events } - // root_state 根状态管理相关接口 + // root_state Root State Management Related Interface pub fn root_state(&self) -> &GlobalStateRequestor { &self.services.root_state } @@ -720,7 +737,7 @@ impl SharedCyfsStack { ) } - // uni_stack相关接口 + // uni_stack related interface fn create_uni_stack(&self) -> UniCyfsStackRef { Arc::new(self.clone()) } From 7594fdbffdc5e1a6d0d8c875d6a4de09590d249c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Tue, 28 Feb 2023 09:46:18 +0800 Subject: [PATCH 345/553] Improve admin and sync test cases --- src/tests/cyfs-stack-test/src/case/admin.rs | 16 +++++- src/tests/cyfs-stack-test/src/case/crypto.rs | 2 +- src/tests/cyfs-stack-test/src/case/mod.rs | 16 +++--- src/tests/cyfs-stack-test/src/case/sync.rs | 56 +++++++++++++++----- 4 files changed, 63 insertions(+), 27 deletions(-) diff --git a/src/tests/cyfs-stack-test/src/case/admin.rs b/src/tests/cyfs-stack-test/src/case/admin.rs index 7daef8807..bd7aa1fb0 100644 --- a/src/tests/cyfs-stack-test/src/case/admin.rs +++ b/src/tests/cyfs-stack-test/src/case/admin.rs @@ -20,7 +20,17 @@ async fn change_access_mode(_dec_id: &ObjectId, access_mode: GlobalStateAccessMo let admin_id = admin_object.desc().calculate_id(); let buf = admin_object.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(Some(target.clone().into()), admin_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(Some(target.clone().into()), admin_id, buf); + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_ADMIN_VIRTUAL_PATH.to_owned()); + + let resp = stack.non_service().post_object(req.clone()).await; + if let Err(e) = resp { + assert_eq!(e.code(), BuckyErrorCode::NotHandled); + } else { + unreachable!(); + } + + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await; if let Err(e) = resp { assert_eq!(e.code(), BuckyErrorCode::InvalidSignature); @@ -41,7 +51,9 @@ async fn change_access_mode(_dec_id: &ObjectId, access_mode: GlobalStateAccessMo let admin_id = admin_object.desc().calculate_id(); let buf = admin_object.to_vec().unwrap(); - let req = NONPostObjectOutputRequest::new_router(Some(target.into()), admin_id, buf); + let mut req = NONPostObjectOutputRequest::new_router(Some(target.into()), admin_id, buf); + req.common.req_path = Some(cyfs_base::CYFS_SYSTEM_ADMIN_VIRTUAL_PATH.to_owned()); + req.common.dec_id = Some(cyfs_core::get_system_dec_app().to_owned()); let resp = stack.non_service().post_object(req).await.unwrap(); assert!(resp.object.is_none()); diff --git a/src/tests/cyfs-stack-test/src/case/crypto.rs b/src/tests/cyfs-stack-test/src/case/crypto.rs index 43ce9724f..f4ae23eb0 100644 --- a/src/tests/cyfs-stack-test/src/case/crypto.rs +++ b/src/tests/cyfs-stack-test/src/case/crypto.rs @@ -52,7 +52,7 @@ fn new_dec(name: &str) -> ObjectId { } pub async fn test() { - return test_codec().await; + test_codec().await; let dec_id = new_dec("crypto"); let stack1 = TestLoader::get_shared_stack(DeviceIndex::User1OOD); diff --git a/src/tests/cyfs-stack-test/src/case/mod.rs b/src/tests/cyfs-stack-test/src/case/mod.rs index 2c4edf860..95ec48a6b 100644 --- a/src/tests/cyfs-stack-test/src/case/mod.rs +++ b/src/tests/cyfs-stack-test/src/case/mod.rs @@ -45,7 +45,6 @@ pub async fn test() { test_restart().await; // role::test().await; - // crypto::test().await; noc::test().await; @@ -67,20 +66,17 @@ pub async fn test() { app_manager::test().await; trans::test().await; - async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; + admin::test().await; + sync::test().await; - return; + async_std::task::sleep(std::time::Duration::from_secs(60 * 30)).await; - // test_drive::test().await; - non_handlers::test().await; - //non_file::test().await; - - router_handlers::test().await; + // non_handlers::test().await; + // non_file::test().await; - admin::test().await; - sync::test().await; + // router_handlers::test().await; info!("test all case success!"); } \ No newline at end of file diff --git a/src/tests/cyfs-stack-test/src/case/sync.rs b/src/tests/cyfs-stack-test/src/case/sync.rs index 4ff8105db..522610cf5 100644 --- a/src/tests/cyfs-stack-test/src/case/sync.rs +++ b/src/tests/cyfs-stack-test/src/case/sync.rs @@ -53,7 +53,31 @@ impl Indexer { } } +async fn test_http_version() { + use std::str::FromStr; + + let stack = TestLoader::get_shared_stack(DeviceIndex::User1StandbyOOD); + let chunk_id = ChunkId::from_str("7EwH3v5RwuzSfu6oGHJvEN69cw2YyfCu72Euo3wmauzy").unwrap(); + let req = NDNGetDataOutputRequest::new_ndc(chunk_id.object_id(), None); + let _resp = stack.ndn_service().get_data(req).await.unwrap(); + + let req = NDNGetDataOutputRequest::new_ndc(chunk_id.object_id(), None); + let _resp = stack.ndn_service().get_data(req).await.unwrap(); +} + pub async fn test() { + async_std::task::spawn(async move { + test_http_version().await; + }); + + async_std::task::spawn(async move { + test_http_version().await; + }); + + async_std::task::spawn(async move { + test_http_version().await; + }); + let index = Indexer::new(); let index1 = index.clone(); @@ -68,6 +92,8 @@ pub async fn test() { let stack = TestLoader::get_shared_stack(DeviceIndex::User1StandbyOOD); test_standby_ood_get(&stack, index).await; }); + + async_std::task::sleep(std::time::Duration::from_secs(60 * 5)).await; } async fn add_chunk(stack: &SharedCyfsStack) -> ChunkId { @@ -385,20 +411,6 @@ async fn test_standby_ood_get(stack: &SharedCyfsStack, indexer: Indexer) { let expect = indexer.get(&root_info.root).unwrap(); assert_eq!(expect, v); - let ret = op_env.get_by_path("/data/object_id1").await.unwrap(); - let v = ret.unwrap(); - assert!(v.is_data()); - - let req = RootStateAccessorGetObjectByPathOutputRequest::new("/data/object_id1"); - let ret = stack.root_state_accessor().get_object_by_path(req).await; - assert!(ret.is_ok()); - let ret = ret.unwrap(); - assert!(ret.object.object.is_empty()); - assert!(ret.object.object.object_id.is_data()); - - let object = stack.root_state_accessor_stub(None, None).get_object_by_path("/data/object_id1").await.unwrap(); - assert!(object.object.is_empty()); - assert!(object.object.object_id.is_data()); info!("device will get text_object: {}", v); let req = NONGetObjectRequest::new_noc(v, None); @@ -414,6 +426,22 @@ async fn test_standby_ood_get(stack: &SharedCyfsStack, indexer: Indexer) { info!("device got target chunk: {}", chunk_id); } + + let ret = op_env.get_by_path("/data/object_id1").await.unwrap(); + let ret = ret.unwrap(); + assert!(ret.is_data()); + + let req = RootStateAccessorGetObjectByPathOutputRequest::new("/data/object_id1"); + let ret = stack.root_state_accessor().get_object_by_path(req).await; + assert!(ret.is_ok()); + let ret = ret.unwrap(); + assert!(ret.object.object.is_empty()); + assert!(ret.object.object.object_id.is_data()); + + let object = stack.root_state_accessor_stub(None, None).get_object_by_path("/data/object_id1").await.unwrap(); + assert!(object.object.is_empty()); + assert!(object.object.object_id.is_data()); + async_std::task::sleep(std::time::Duration::from_secs(15)).await; } } From 68c81c8c4c5090c3c60cbec3e62b0dc32146e1b9 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 17:42:13 +0800 Subject: [PATCH 346/553] Set known sn list when sync built-in app repo --- src/tools/ood-installer/src/app_repo_downloader.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/ood-installer/src/app_repo_downloader.rs b/src/tools/ood-installer/src/app_repo_downloader.rs index b7fa7ca18..dd5c79c08 100644 --- a/src/tools/ood-installer/src/app_repo_downloader.rs +++ b/src/tools/ood-installer/src/app_repo_downloader.rs @@ -39,6 +39,11 @@ impl AppRepoDownloader { return Err(BuckyError::new(e.code(), msg)); } + let known_sn = cyfs_util::get_sn_desc().iter().map(|(_, device)| { + device.clone() + }).collect(); + let _ = self.client.reset_known_sn_list(known_sn); + Ok(()) } From e7ce42893fa34b5fc2edc8a7f63f8d2cccc920a6 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 20:55:05 +0800 Subject: [PATCH 347/553] Fix wrong app local repo path --- src/service/app-manager/src/package.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/service/app-manager/src/package.rs b/src/service/app-manager/src/package.rs index 274ed7d51..4b9d283be 100644 --- a/src/service/app-manager/src/package.rs +++ b/src/service/app-manager/src/package.rs @@ -34,7 +34,7 @@ impl AppPackage { Self::install_from_local(app_id, &tmp_path, true) } RepoMode::Local => { - let repo_path = get_cyfs_root_path().join("app_repo"); + let repo_path = get_cyfs_root_path().join("app_repo").join(dir.to_string()); Self::install_from_local(app_id, &repo_path, false) } } @@ -64,6 +64,7 @@ impl AppPackage { } pub fn install_from_local(app_id: &DecAppId, local_path: &Path, delete_source: bool) -> BuckyResult<()> { + info!("install app {} from local path {}", app_id, local_path.display()); let app_str = app_id.to_string(); let service_path = get_app_dir(&app_str); let acl_path = get_app_acl_dir(&app_str); From 66969e010143a178f1c1989c49701a3cdab812ab Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 20:57:20 +0800 Subject: [PATCH 348/553] App-manager return error when repo path not exist --- src/service/app-manager/src/app_manager_ex.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/service/app-manager/src/app_manager_ex.rs b/src/service/app-manager/src/app_manager_ex.rs index 7da7d0be5..359bcb1fc 100644 --- a/src/service/app-manager/src/app_manager_ex.rs +++ b/src/service/app-manager/src/app_manager_ex.rs @@ -557,8 +557,12 @@ impl AppManager { .await { Ok(is_running) => { - info!("[RUNNING CHECK] running: [{}] app:{}", is_running, app_id); + let running_counter = self.start_couter.write().unwrap().entry(app_id.clone()).or_insert(0); + info!("[RUNNING CHECK] running: [{}] app:{}, start counter: {}", is_running, app_id, *running_counter); if is_running { + if *running_counter > 0 { + *running_counter = 0; + } return; } else { let mut try_start = false; @@ -575,17 +579,15 @@ impl AppManager { return; } //status is running, but not actually - let mut counters = self.start_couter.write().unwrap(); - let cur_count = *counters.get(app_id).unwrap_or(&0); - if cur_count > START_RETRY_LIMIT { + if *running_counter > START_RETRY_LIMIT { let target_status_code = AppLocalStatusCode::RunException; info!("[RUNNING CHECK] app failed count is out of limit! app:{}, change app status from [{}] to [{}]", app_id, cur_status_code, target_status_code); status.set_status(target_status_code); status_clone = Some(status.clone()); } else { - info!("[RUNNING CHECK] app status is running, but not actually. will restart it, app:{}, retry count:{}", app_id, cur_count + 1); - counters.insert(app_id.clone(), cur_count + 1); + *running_counter = *running_counter + 1; + info!("[RUNNING CHECK] app status is running, but not actually. will restart it, app:{}, retry count:{}", app_id, *running_counter); try_start = true; } } From 28d86fa05a1f9ad40e9acc6ffba83bc749423dc5 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 28 Feb 2023 20:59:51 +0800 Subject: [PATCH 349/553] Commit right file --- src/service/app-manager/src/package.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service/app-manager/src/package.rs b/src/service/app-manager/src/package.rs index 4b9d283be..d6537a206 100644 --- a/src/service/app-manager/src/package.rs +++ b/src/service/app-manager/src/package.rs @@ -65,6 +65,9 @@ impl AppPackage { pub fn install_from_local(app_id: &DecAppId, local_path: &Path, delete_source: bool) -> BuckyResult<()> { info!("install app {} from local path {}", app_id, local_path.display()); + if !local_path.exists() { + return Err(BuckyError::new(BuckyErrorCode::NotFound, format!("local path {} not found", local_path.display()))); + } let app_str = app_id.to_string(); let service_path = get_app_dir(&app_str); let acl_path = get_app_acl_dir(&app_str); From 952dbb66a5e745c18b3decc09e21a692e4c626b5 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 1 Mar 2023 15:19:46 +0800 Subject: [PATCH 350/553] App-manager returns an error in the case that the command program does not exist. --- src/service/app-manager/src/app_manager_ex.rs | 8 ++++++-- src/service/app-manager/src/dapp.rs | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/service/app-manager/src/app_manager_ex.rs b/src/service/app-manager/src/app_manager_ex.rs index 359bcb1fc..14969b2a8 100644 --- a/src/service/app-manager/src/app_manager_ex.rs +++ b/src/service/app-manager/src/app_manager_ex.rs @@ -557,10 +557,12 @@ impl AppManager { .await { Ok(is_running) => { - let running_counter = self.start_couter.write().unwrap().entry(app_id.clone()).or_insert(0); - info!("[RUNNING CHECK] running: [{}] app:{}, start counter: {}", is_running, app_id, *running_counter); + info!("[RUNNING CHECK] running: [{}] app:{}", is_running, app_id); if is_running { + let mut writer = self.start_couter.write().unwrap(); + let running_counter = writer.entry(app_id.clone()).or_insert(0); if *running_counter > 0 { + info!("reset app {} restart counter {}", app_id, *running_counter); *running_counter = 0; } return; @@ -579,6 +581,8 @@ impl AppManager { return; } //status is running, but not actually + let mut writer = self.start_couter.write().unwrap(); + let running_counter = writer.entry(app_id.clone()).or_insert(0); if *running_counter > START_RETRY_LIMIT { let target_status_code = AppLocalStatusCode::RunException; info!("[RUNNING CHECK] app failed count is out of limit! app:{}, change app status from [{}] to [{}]", diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index 9f3e52df7..fff62587a 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -188,6 +188,11 @@ impl DApp { } info!("run cmd {} in {}", cmd, dir.display()); let program = which::which(args[0]).unwrap_or_else(|_| dir.join(args[0])); + if !program.exists() { + let err = format!("exec program path {} not exists!", program.display()); + error!("{}", &err); + return Err(BuckyError::new(BuckyErrorCode::NotFound, err)); + } let mut command = Command::new(program); command.args(&args[1..]).current_dir(dir); if let Some(out) = stdout { From 093d774d6522c691d2484aad8d2567ce5909aad2 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 1 Mar 2023 17:43:39 +0800 Subject: [PATCH 351/553] Add perf-service in misc --- src/Cargo.lock | 508 +++++++++++++++++++-- src/Cargo.toml | 1 + src/misc/perf-service/Cargo.toml | 26 ++ src/misc/perf-service/src/config.rs | 174 +++++++ src/misc/perf-service/src/main.rs | 72 +++ src/misc/perf-service/src/service.rs | 124 +++++ src/misc/perf-service/src/storage/mod.rs | 77 ++++ src/misc/perf-service/src/storage/mongo.rs | 493 ++++++++++++++++++++ 8 files changed, 1449 insertions(+), 26 deletions(-) create mode 100644 src/misc/perf-service/Cargo.toml create mode 100644 src/misc/perf-service/src/config.rs create mode 100644 src/misc/perf-service/src/main.rs create mode 100644 src/misc/perf-service/src/service.rs create mode 100644 src/misc/perf-service/src/storage/mod.rs create mode 100644 src/misc/perf-service/src/storage/mongo.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 1d9ae081b..0649e040a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -174,7 +174,7 @@ dependencies = [ "serde_json", "surf", "tar", - "toml", + "toml 0.5.11", "version-compare", "wait-timeout", "walkdir", @@ -193,7 +193,7 @@ dependencies = [ "log 0.4.17", "serde", "serde_json", - "toml", + "toml 0.5.11", ] [[package]] @@ -342,7 +342,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] @@ -472,6 +472,20 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "async-std-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "pin-utils", + "trust-dns-resolver", +] + [[package]] name = "async-task" version = "4.3.0" @@ -844,7 +858,27 @@ dependencies = [ "serde_json", "sqlx", "tide", - "toml", + "toml 0.5.11", +] + +[[package]] +name = "bson" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8746d07211bb12a7c34d995539b4a2acd4e0b0e757de98ce2ab99bcf17443fad" +dependencies = [ + "ahash", + "base64 0.13.1", + "chrono", + "hex", + "indexmap", + "lazy_static", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "time 0.3.19", + "uuid 1.3.0", ] [[package]] @@ -1387,6 +1421,16 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.6", + "subtle 2.4.1", +] + [[package]] name = "csv" version = "1.2.0" @@ -1571,7 +1615,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "socket2", + "socket2 0.4.7", "winapi", ] @@ -1705,7 +1749,7 @@ dependencies = [ "hmac 0.12.1", "log 0.4.17", "memzero", - "pbkdf2", + "pbkdf2 0.11.0", "rand 0.7.3", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -1813,7 +1857,7 @@ dependencies = [ "surf", "tide", "timer", - "toml", + "toml 0.5.11", "url 2.3.0", "winapi", ] @@ -2087,7 +2131,7 @@ dependencies = [ "serde", "serde_json", "surf", - "toml", + "toml 0.5.11", "url 2.3.0", ] @@ -2209,7 +2253,7 @@ dependencies = [ "serde", "serde_json", "tide", - "toml", + "toml 0.5.11", "url 2.3.0", ] @@ -2272,7 +2316,7 @@ dependencies = [ "sha2 0.8.2", "sqlx", "tide", - "toml", + "toml 0.5.11", "zip 0.6.4", ] @@ -2296,7 +2340,7 @@ dependencies = [ "log 0.4.17", "rand 0.8.5", "serde", - "toml", + "toml 0.5.11", ] [[package]] @@ -2318,7 +2362,7 @@ dependencies = [ "log 0.4.17", "regex", "serde", - "toml", + "toml 0.5.11", "toml_edit 0.15.0", ] @@ -2413,7 +2457,7 @@ dependencies = [ "simple_logger 2.3.0", "sysinfo 0.27.7", "thread_local", - "toml", + "toml 0.5.11", "url 2.3.0", "walkdir", "winapi", @@ -2468,6 +2512,12 @@ dependencies = [ "parking_lot_core 0.9.7", ] +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + [[package]] name = "deadpool" version = "0.7.0" @@ -2493,6 +2543,17 @@ dependencies = [ "pem-rfc7468", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -2700,6 +2761,18 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +[[package]] +name = "enum-as-inner" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -3197,7 +3270,7 @@ dependencies = [ "serde", "serde_json", "tide", - "toml", + "toml 0.5.11", "url 2.3.0", "wildmatch", "winapi", @@ -3519,6 +3592,16 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -3667,7 +3750,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite 0.2.9", - "socket2", + "socket2 0.4.7", "tokio", "tower-service", "tracing", @@ -3919,6 +4002,24 @@ dependencies = [ "libc", ] +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2 0.3.19", + "widestring 0.4.3", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + [[package]] name = "itertools" version = "0.10.5" @@ -4044,7 +4145,7 @@ dependencies = [ "nom 7.1.3", "once_cell", "quoted_printable", - "socket2", + "socket2 0.4.7", ] [[package]] @@ -4108,6 +4209,12 @@ dependencies = [ "cc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "local-ip-address" version = "0.5.1" @@ -4160,6 +4267,15 @@ dependencies = [ "log 0.4.17", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "lru_time_cache" version = "0.11.11" @@ -4194,6 +4310,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "md5" version = "0.7.0" @@ -4343,6 +4470,55 @@ dependencies = [ "serde", ] +[[package]] +name = "mongodb" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bacb6f8cee6bf010d7bc57550d859f6a4ffe255eb8c9a7014637fe988eaece64" +dependencies = [ + "async-std", + "async-std-resolver", + "async-trait", + "base64 0.13.1", + "bitflags", + "bson", + "chrono", + "derivative", + "futures-core", + "futures-executor", + "futures-io", + "futures-util", + "hex", + "hmac 0.11.0", + "lazy_static", + "md-5", + "os_info", + "pbkdf2 0.8.0", + "percent-encoding 2.2.0", + "rand 0.8.5", + "rustls 0.19.1", + "rustls-pemfile", + "serde", + "serde_with", + "sha-1 0.9.8", + "sha2 0.9.9", + "socket2 0.4.7", + "stringprep", + "strsim 0.10.0", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util 0.6.10", + "trust-dns-proto", + "trust-dns-resolver", + "typed-builder", + "uuid 0.8.2", + "version_check 0.9.4", + "webpki", + "webpki-roots 0.21.1", +] + [[package]] name = "multimap" version = "0.8.3" @@ -4359,7 +4535,7 @@ dependencies = [ "once_cell", "parking_lot 0.12.1", "thiserror", - "widestring", + "widestring 0.5.1", "winapi", ] @@ -4665,7 +4841,7 @@ dependencies = [ "serde", "serde_json", "tide", - "toml", + "toml 0.5.11", "zip 0.6.4", ] @@ -4759,6 +4935,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_info" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c424bc68d15e0778838ac013b5b3449544d8133633d8016319e7e05a820b8c0" +dependencies = [ + "log 0.4.17", + "winapi", +] + [[package]] name = "os_type" version = "2.6.0" @@ -4897,6 +5083,15 @@ dependencies = [ "proc-macro-hack 0.5.20+deprecated", ] +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -4941,6 +5136,27 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "perf-service" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-perf-base", + "cyfs-util", + "log 0.4.17", + "mongodb", + "serde", + "serde_json", + "toml 0.7.2", +] + [[package]] name = "petgraph" version = "0.6.3" @@ -5170,7 +5386,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] @@ -5770,6 +5986,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.16.20" @@ -5985,6 +6211,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "rustversion" version = "1.0.11" @@ -6129,6 +6364,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.2" @@ -6165,6 +6409,7 @@ version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ + "indexmap", "itoa", "ryu", "serde", @@ -6181,6 +6426,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -6215,6 +6469,19 @@ dependencies = [ "syn", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -6479,6 +6746,17 @@ dependencies = [ "simple_logger 4.0.0", ] +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -6574,7 +6852,7 @@ dependencies = [ "rand 0.8.5", "rsa 0.6.1", "rustls 0.19.1", - "sha-1", + "sha-1 0.10.1", "sha2 0.10.6", "smallvec 1.10.0", "sqlformat", @@ -6799,6 +7077,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tap" version = "1.0.1" @@ -7047,6 +7331,21 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.25.0" @@ -7060,10 +7359,33 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite 0.2.9", - "socket2", + "socket2 0.4.7", + "tokio-macros", "windows-sys 0.42.0", ] +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki", +] + [[package]] name = "tokio-util" version = "0.6.10" @@ -7072,6 +7394,7 @@ checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes 1.4.0", "futures-core", + "futures-io", "futures-sink", "log 0.4.17", "pin-project-lite 0.2.9", @@ -7102,12 +7425,33 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "toml_edit 0.19.4", +] + [[package]] name = "toml_datetime" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + [[package]] name = "toml_edit" version = "0.15.0" @@ -7117,7 +7461,7 @@ dependencies = [ "combine", "indexmap", "itertools", - "toml_datetime", + "toml_datetime 0.5.1", ] [[package]] @@ -7128,7 +7472,20 @@ checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ "indexmap", "nom8", - "toml_datetime", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "winnow", ] [[package]] @@ -7173,6 +7530,51 @@ dependencies = [ "rlp", ] +[[package]] +name = "trust-dns-proto" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.1", + "ipnet", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "smallvec 1.10.0", + "thiserror", + "tinyvec", + "tokio", + "url 2.3.0", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" +dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lazy_static", + "log 0.4.17", + "lru-cache", + "parking_lot 0.11.2", + "resolv-conf", + "smallvec 1.10.0", + "thiserror", + "tokio", + "trust-dns-proto", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -7192,7 +7594,7 @@ dependencies = [ "httparse", "log 0.4.17", "rand 0.8.5", - "sha-1", + "sha-1 0.10.1", "thiserror", "url 2.3.0", "utf-8", @@ -7204,6 +7606,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +[[package]] +name = "typed-builder" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46ee5bd706ff79131be9c94e7edcb82b703c487766a114434e5790361cf08c5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.16.0" @@ -7336,6 +7749,25 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "uuid" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +dependencies = [ + "getrandom 0.2.8", + "serde", +] + [[package]] name = "value-bag" version = "1.0.0-alpha.9" @@ -7560,6 +7992,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "widestring" version = "0.5.1" @@ -7736,6 +8174,24 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "winnow" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + [[package]] name = "wyz" version = "0.2.0" @@ -7800,7 +8256,7 @@ dependencies = [ "crossbeam-utils", "flate2", "hmac 0.12.1", - "pbkdf2", + "pbkdf2 0.11.0", "sha1 0.10.5", "time 0.3.19", "zstd", @@ -7863,7 +8319,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "toml", + "toml 0.5.11", "zone-simulator", ] diff --git a/src/Cargo.toml b/src/Cargo.toml index 3e7e6cdea..28684a8d6 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -65,6 +65,7 @@ members = [ "./misc/cyfs-monitor", "./misc/misc-util", "./misc/sn-online-test", + "./misc/perf-service", "./tests/cyfs-stack-test", "./tests/cyfs-bench-mark", diff --git a/src/misc/perf-service/Cargo.toml b/src/misc/perf-service/Cargo.toml new file mode 100644 index 000000000..24e526e3f --- /dev/null +++ b/src/misc/perf-service/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "perf-service" +version = "0.5.0" +authors = ["wangzhi "] +edition = "2018" +license = "BSD-2-Clause" +description = "Rust perf-service package" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cyfs-perf-base = {path="../../component/cyfs-perf/cyfs-perf-base"} +cyfs-base = {path="../../component/cyfs-base"} +cyfs-debug = {path="../../component/cyfs-debug"} +cyfs-core = {path="../../component/cyfs-core"} +cyfs-util = {path="../../component/cyfs-util"} +async-std = { version = "1.11", features = ["unstable", "attributes"] } +cyfs-lib = {path="../../component/cyfs-lib"} +log = "0.4" +async-trait = "0.1.53" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +mongodb = { version = "2", default-features = false, features = ["async-std-runtime", "bson-chrono-0_4"]} +toml = "0.7" +clap = "2" +chrono = "0.4" \ No newline at end of file diff --git a/src/misc/perf-service/src/config.rs b/src/misc/perf-service/src/config.rs new file mode 100644 index 000000000..4e4cac21e --- /dev/null +++ b/src/misc/perf-service/src/config.rs @@ -0,0 +1,174 @@ +use std::fmt::{Display, Formatter}; +use std::str::FromStr; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, TStringVisitor}; +use cyfs_lib::SharedCyfsStack; +use crate::storage::StorageConfig; +use cyfs_perf_base::PERF_DEC_ID; + +#[derive(PartialEq)] +pub enum StackType { + OOD, + Runtime, + Other(u16, u16) +} + +impl Default for StackType { + fn default() -> Self { + StackType::OOD + } +} + +impl Display for StackType { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + StackType::OOD => write!(f, "ood"), + StackType::Runtime => write!(f, "runtime"), + StackType::Other(http_port, ws_port) => write!(f, "{}:{}", http_port, ws_port) + } + } +} + +impl FromStr for StackType { + type Err = BuckyError; + + fn from_str(s: &str) -> BuckyResult { + match s { + "ood" => Ok(StackType::OOD), + "runtime" => Ok(StackType::Runtime), + v @ _ => { + let ports: Vec<&str> = v.split(":").collect(); + if ports.len() != 2 { + let msg = format!("stack type str {} invalid. Must have two port numbers separated by a colon", v); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + let http_port; + let ws_port; + match ports[0].parse::() { + Ok(port) => {http_port = port}, + Err(_) => { + let msg = format!("stack http port {} invalid. Must u16 port number", ports[0]); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + + match ports[1].parse::() { + Ok(port) => {ws_port = port}, + Err(_) => { + let msg = format!("stack ws port {} invalid. Must u16 port number", ports[1]); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + + Ok(StackType::Other(http_port, ws_port)) + } + } + } +} + +impl<'de> Deserialize<'de> for StackType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(TStringVisitor::::new()) + } +} + +impl Serialize for StackType { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_string()) + } +} + +#[derive(Serialize, Deserialize)] +pub(crate) struct PerfConfig { + pub stack_type: StackType, + pub storage: StorageConfig +} + +impl Default for PerfConfig { + fn default() -> Self { + Self { + stack_type: StackType::default(), + storage: StorageConfig::default(), + } + } +} + +pub(crate) async fn get_stack(config: StackType) -> BuckyResult { + let dec_id = Some(PERF_DEC_ID.clone()); + let stack = match config { + StackType::OOD => { + SharedCyfsStack::open_default(dec_id).await + }, + StackType::Runtime => { + SharedCyfsStack::open_runtime(dec_id).await + }, + StackType::Other(http_port, ws_port) => { + SharedCyfsStack::open_with_port(dec_id, http_port, ws_port).await + } + }?; + + stack.online().await?; + + Ok(stack) +} + +#[cfg(test)] +mod test { + use std::str::FromStr; + use crate::config::{PerfConfig, StackType}; + use crate::storage::mongo::MongoConfig; + use crate::storage::{DatabaseConfig, StorageConfig}; + + #[test] + fn print_config() { + let stack_type = StackType::from_str("2547:9885").unwrap(); + if let StackType::Other(http_port, ws_port) = stack_type { + assert_eq!(http_port, 2547); + assert_eq!(ws_port, 9885); + } else { + assert!(false); + } + + println!("normal config: \n{}", toml::to_string(&PerfConfig { + stack_type: StackType::OOD, + storage: StorageConfig { + isolate: Some("isolate".to_owned()), + database: DatabaseConfig::MongoDB(MongoConfig { mongo_url: "mongodb://localhost:21731".to_string() }) + } + }).unwrap()); + + println!("runtime config: \n{}", toml::to_string(&PerfConfig { + stack_type: StackType::Runtime, + storage: StorageConfig { + isolate: Some("isolate2".to_owned()), + database: DatabaseConfig::MongoDB(MongoConfig { mongo_url: "mongodb://localhost:21731".to_string() }) + } + }).unwrap()); + + println!("normal config: \n{}", toml::to_string(&PerfConfig { + stack_type: StackType::Other(21001, 21002), + storage: StorageConfig { + isolate: None, + database: DatabaseConfig::MongoDB(MongoConfig { mongo_url: "mongodb://localhost:21731".to_string() }) + } + }).unwrap()); + + let config_str = r#" +stack_type = "2132:8876" + +[storage.database.mongodb] +mongo_url = "mongodb://localhost:21731" +"#; + let config: PerfConfig = toml::from_str(config_str).unwrap(); + assert!(config.stack_type == StackType::Other(2132, 8876)); + assert!(config.storage.isolate.is_none()); + if let DatabaseConfig::MongoDB(config) = config.storage.database { + assert_eq!(config.mongo_url.as_str(), "mongodb://localhost:21731"); + } else { + assert!(false); + } + } +} diff --git a/src/misc/perf-service/src/main.rs b/src/misc/perf-service/src/main.rs new file mode 100644 index 000000000..7778c8093 --- /dev/null +++ b/src/misc/perf-service/src/main.rs @@ -0,0 +1,72 @@ + +mod service; +mod storage; +mod config; + +use std::path::Path; +use std::str::FromStr; +use service::*; +use async_std::sync::Arc; +use clap::{App, Arg}; +use log::{error, info, warn}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult}; +use crate::config::{PerfConfig, StackType}; + +fn parse_config(config_path: &Path) -> BuckyResult { + if !config_path.exists() { + warn!("config path {} not exists.", config_path.display()); + return Err(BuckyError::from(BuckyErrorCode::NotFound)); + } + + toml::from_str(std::fs::read_to_string(config_path)?.as_str()).map_err(|e| { + BuckyError::new(BuckyErrorCode::InvalidFormat, e.to_string()) + })? +} + +#[async_std::main] +async fn main() { + let matches = App::new("perf-service").version(cyfs_base::get_version()) + .arg(Arg::with_name("stack").short("s").long("stack").help("set stack mode, replace the config file one")) + .arg(Arg::with_name("config").short("c").long("config").takes_value(true).default_value("perf-service.toml")) + .get_matches(); + + cyfs_debug::CyfsLoggerBuilder::new_service("perf-service") + .level("info") + .console("info") + .enable_bdt(Some("info"), Some("info")) + .build() + .unwrap() + .start(); + + cyfs_debug::PanicBuilder::new("ood-service", "perf-service").build().start(); + + let config_path = Path::new(matches.value_of("config").unwrap()); + let mut config = match parse_config(config_path) { + Ok(config) => config, + Err(e) => { + warn!("parse config path {} err {}, use default", config_path.display(), e); + PerfConfig::default() + } + }; + + if let Some(stack_str) = matches.value_of("stack") { + info!("get stack param {}", stack_str); + match StackType::from_str(stack_str) { + Ok(stack) => { + config.stack_type = stack; + } + Err(e) => { + error!("parse stack param {} err {}", stack_str, e); + std::process::exit(1); + } + } + } + + info!("use final config: \n{}", toml::to_string_pretty(&config).unwrap()); + + let service = PerfService::create(config).await.unwrap(); + + PerfService::start(Arc::new(service)); + + async_std::task::block_on(async_std::future::pending::<()>()); +} \ No newline at end of file diff --git a/src/misc/perf-service/src/service.rs b/src/misc/perf-service/src/service.rs new file mode 100644 index 000000000..e53ee1314 --- /dev/null +++ b/src/misc/perf-service/src/service.rs @@ -0,0 +1,124 @@ +use cyfs_base::*; +use cyfs_perf_base::*; +use log::*; +use cyfs_lib::*; +use async_trait::async_trait; +use std::sync::{Arc}; +use cyfs_util::EventListenerAsyncRoutine; +use crate::config::{get_stack, PerfConfig}; + +use crate::storage::{create_storage, StorageRef}; + +struct OnPerfReport { + owner: Arc, +} + +#[async_trait] +impl EventListenerAsyncRoutine for OnPerfReport { + async fn call(&self, param: &RouterHandlerPostObjectRequest) -> BuckyResult { + let mut result = RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: None, + }; + + let owner = self.owner.clone(); + let from = param.request.common.source.zone.device.as_ref() + .map(|o|o.to_string()) + .unwrap_or_else(|| { + "self".to_owned() + }); + + // 验证对象签名,决定是否保存 + // 解出Perf对象 + match Perf::clone_from_slice(¶m.request.object.object_raw) { + Ok(perf) => { + let id= perf.desc().calculate_id(); + if self.owner.verify_object(&perf).await { + // 这里是实际处理流程,不占用路由时间 + async_std::task::spawn(async move { + info!("process perf object {} from {}", &id, from); + let _ = owner.on_perf(&perf).await; + }); + result.response = Some(Ok(NONPostObjectInputResponse { object: None })) + } else { + let msg = format!("perf object {} verify failed", &id); + warn!("{}", &msg); + result.response = Some(Err(BuckyError::new(BuckyErrorCode::Reject, msg))); + }; + } + Err(e) => { + let msg = format!("decode perf object {} err {}", ¶m.request.object.object_id, e); + result.response = Some(Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg))); + } + } + + Ok(result) + } +} + +pub(crate) struct PerfService { + cyfs_stack: SharedCyfsStack, + perf_storage: StorageRef +} + +impl PerfService { + pub async fn create(config: PerfConfig) -> BuckyResult { + let storage = create_storage(&config.storage).await?; + Ok(Self { + cyfs_stack: get_stack(config.stack_type).await?, + perf_storage: storage + }) + } + + pub fn start(service: Arc) { + // 注册on_post_put_router事件 + let listener = OnPerfReport { + owner: service.clone(), + }; + + // 只监听应用自己的DecObject + service.cyfs_stack + .router_handlers() + .add_handler( + RouterHandlerChain::Handler, + "cyfs_perf_on_perf_report", + 0, + None, + Some(PERF_REPORT_PATH.to_owned()), + RouterHandlerAction::Default, + Some(Box::new(listener))) + .unwrap(); + } + + // 这里验证对象签名是否正确,验证正确的对象才会被保存 + pub async fn verify_object(&self, _pref: &Perf) -> bool { + // 这里用业务逻辑检查 + true + } + + async fn on_perf(&self, perf: &Perf) -> BuckyResult<()> { + let id = perf.desc().calculate_id(); + + info!( + "###### recv msg {}, people:{}, device:{}, dec_id: {}, id: {}", + &id, + perf.people(), + perf.device(), + perf.dec_id(), + perf.get_id() + ); + + let all = perf.get_entity_list(); + info!("perf entity list len: {}", all.len()); + + let _ = self.perf_storage.insert_entity_list(perf.people(), + perf.device(), + perf.dec_id().to_string(), + perf.get_id().to_string(), + perf.get_version().to_owned(), + &all).await; + + Ok(()) + } +} diff --git a/src/misc/perf-service/src/storage/mod.rs b/src/misc/perf-service/src/storage/mod.rs new file mode 100644 index 000000000..9120ee1bd --- /dev/null +++ b/src/misc/perf-service/src/storage/mod.rs @@ -0,0 +1,77 @@ +pub mod mongo; + +use async_trait::async_trait; + +use cyfs_base::{BuckyResult}; + +use cyfs_perf_base::*; +use std::collections::HashMap; +use std::sync::Arc; +use serde::{Deserialize, Serialize, Serializer}; +use serde::ser::SerializeStruct; +use crate::storage::mongo::{MangodbStorage, MongoConfig}; + +#[derive(Serialize, Deserialize)] +pub(crate) struct StorageConfig { + pub(crate) isolate: Option, + pub(crate) database: DatabaseConfig +} + +impl Default for StorageConfig { + fn default() -> Self { + Self { + isolate: Some("perf-service".to_owned()), + database: DatabaseConfig::default(), + } + } +} + +#[derive(Deserialize)] +#[serde(rename_all="lowercase")] +pub(crate) enum DatabaseConfig { + MongoDB(MongoConfig) +} + +impl Default for DatabaseConfig { + fn default() -> Self { + DatabaseConfig::MongoDB(MongoConfig::default()) + } +} + +impl Serialize for DatabaseConfig { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + let mut state = serializer.serialize_struct("database", 1)?; + match self { + DatabaseConfig::MongoDB(config) => { + state.serialize_field("mongodb", config)?; + } + } + state.end() + } +} + +#[async_trait] +pub(crate) trait Storage: Sync + Send { + async fn insert_entity_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()>; +} + +pub(crate) type StorageRef = Arc; + +pub(crate) async fn create_storage(config: &StorageConfig) -> BuckyResult { + match &config.database { + DatabaseConfig::MongoDB(mongo_config) => { + let storage = MangodbStorage::new(config.isolate.as_deref(), mongo_config).await?; + Ok(Arc::new(storage)) + } + } +} + + + + + + + + + + diff --git a/src/misc/perf-service/src/storage/mongo.rs b/src/misc/perf-service/src/storage/mongo.rs new file mode 100644 index 000000000..4d5db067e --- /dev/null +++ b/src/misc/perf-service/src/storage/mongo.rs @@ -0,0 +1,493 @@ +use cyfs_base::{BuckyResult, BuckyError, BuckyErrorCode, bucky_time_to_system_time}; +use async_std::task; +use mongodb::{options::ClientOptions, Client, Collection, Database}; +use mongodb::error::{Error, ErrorKind, WriteFailure}; +use log::*; + +use async_trait::async_trait; +use crate::storage::*; +use cyfs_perf_base::*; +use std::collections::HashMap; +use chrono::Utc; +use mongodb::bson::{doc, Document}; +use serde::{Deserialize, Serialize}; + +const MONGO_DB_DEFAULT_NAME: &str = "perf-db"; + +const MONGO_COLL_NAME_REQUEST: &str = "request"; +const MONGO_COLL_NAME_ACTION: &str = "action"; +const MONGO_COLL_NAME_ACC: &str = "accumulation"; +const MONGO_COLL_NAME_RECORD: &str = "record"; + +pub const OBJECT_SELECT_MAX_PAGE_SIZE: u16 = 256; + +#[derive(Serialize, Deserialize)] +pub(crate) struct MongoConfig { + pub mongo_url: String +} + +impl Default for MongoConfig { + fn default() -> Self { + Self { + mongo_url: "mongodb://localhost".to_owned(), + } + } +} + +pub(crate) struct MangodbStorage{ + client: Client, + db: Database, + request_coll: Collection, + action_coll: Collection, + acc_coll: Collection, + record_coll: Collection, +} + +fn bucky_time_to_chrono_time(bucky_time: u64) -> chrono::DateTime { + let sys_time = bucky_time_to_system_time(bucky_time); + sys_time.into() +} + +impl MangodbStorage { + pub async fn new(isolate: Option<&str>, config: &MongoConfig) ->BuckyResult { + let mut client_options = ClientOptions::parse(&config.mongo_url).await.unwrap(); + client_options.direct_connection = Some(true); + client_options.app_name = Some("perf-service".to_string()); + + let client = Client::with_options(client_options).map_err(|e| { + let msg = format!("init mangodb client error: {}", e); + error!("{}", msg); + + BuckyError::from(msg) + })?; + + let db_name = if let Some(isolate) = isolate { + format!("{}-{}", isolate, MONGO_DB_DEFAULT_NAME) + } else { + MONGO_DB_DEFAULT_NAME.to_owned() + }; + + info!("use mongo db: {}", db_name); + + let db = client.database(&db_name); + let _ = Self::ping(&db).await; + + Self::dump_db(&db); + + // init request coll + let request_coll = db.collection(MONGO_COLL_NAME_REQUEST); + Self::dump_coll(&request_coll, MONGO_COLL_NAME_REQUEST.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_REQUEST.to_string()).await?; + + // init action coll + let action_coll = db.collection(MONGO_COLL_NAME_ACTION); + Self::dump_coll(&action_coll, MONGO_COLL_NAME_ACTION.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_ACTION.to_string()).await?; + + // init record coll + let record_coll = db.collection(MONGO_COLL_NAME_RECORD); + Self::dump_coll(&record_coll, MONGO_COLL_NAME_RECORD.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_RECORD.to_string()).await?; + + + // init acc coll + let acc_coll = db.collection(MONGO_COLL_NAME_ACC); + Self::dump_coll(&acc_coll, MONGO_COLL_NAME_ACC.to_string()); + + Self::init_coll(&db, MONGO_COLL_NAME_ACC.to_string()).await?; + + + let ret = Self { client, db, request_coll, action_coll, acc_coll, record_coll}; + Ok(ret) + } + + + pub async fn query_index(db: &Database, coll_name: String) -> BuckyResult<()>{ + // 查询索引 + let doc = doc! { + "listIndexes": coll_name, + }; + + let _ret = db.run_command(doc, None).await.map_err(|e| { + let msg = format!("list index on coll error: {}", e); + error!("{}", msg); + + BuckyError::from(msg) + })?; + + Ok(()) + } + + pub async fn init_coll(db: &Database, coll_name: String) -> BuckyResult<()> { + const INDEX_NAME: &str = "people_id"; + + // 建立索引 + // https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/ + let doc = doc! { + "createIndexes": coll_name, + "indexes": [ + { + "key": { + "people_id": 1, + }, + "name": INDEX_NAME, + "unique": false, + }, + ], + }; + + let ret = db.run_command(doc, None).await.map_err(|e| { + let msg = format!("create index on coll error: {}", e); + error!("{}", msg); + BuckyError::from(msg) + + })?; + + trace!("{}", ret); + + let ok = ret.get_f64("ok").unwrap(); + + if ok == 1.0 { + if let Ok(note) = ret.get_str("note") { + info!("index already exists: {} {}", INDEX_NAME, note); + } else { + info!("create index success: {}", INDEX_NAME); + } + } else { + if let Ok(note) = ret.get_str("note") { + info!("index already exists: {} {}", INDEX_NAME, note); + } else { + let err = ret.get("errmsg"); + let code = ret.get("code"); + + let msg = format!("create index error: {} {:?} {:?}", INDEX_NAME, err, code); + error!("{}", msg); + + } + } + + Ok(()) + + } + + fn dump_db(db: &Database) { + let db = db.clone(); + task::spawn(async move { + match db.list_collection_names(None).await { + Ok(list) => { + info!("collections in {} as follows: {:?}", db.name(), list); + } + Err(e) => { + error!("list_collection_names error: {}", e); + } + } + }); + } + + fn dump_coll(coll: &Collection, coll_name: String) { + let coll = coll.clone(); + let coll_name = coll_name.clone(); + task::spawn(async move { + match coll.count_documents(None, None).await { + Ok(list) => { + info!("collection {} has doc count: {}", coll_name, list); + } + Err(e) => { + error!("count_documents error: {}", e); + } + } + }); + } + + pub async fn ping(db: &Database) -> BuckyResult<()>{ + let doc = doc! { + "ping": 1, + }; + + let _doc = db.run_command(doc, None).await.map_err(|e| { + let _msg = format!("ping error: {}", e); + error!("{}", e); + }).map_err(|_e|{ + error!{"async fn ping db_run_command() failed!"}; + }); + + Ok(()) + } + + + // 判断是不是相同object_id的项目已经存在 + fn is_exists_error(e: &Error) -> bool { + if let ErrorKind::Write(WriteFailure::WriteError(e)) = e.kind.as_ref() { + if e.code == 11000 { + return true; + } + } + + false + } + + + async fn insert_reqs_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.to_owned(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let reqs = v.reqs.clone(); + + let mut reqs_vec = Vec::new(); + for (_k1, v1) in reqs { + doc.insert("item_id", v1.id); + doc.insert("time", bucky_time_to_chrono_time(v1.time_range.begin)); + doc.insert("time_begin", bucky_time_to_chrono_time(v1.time_range.begin)); + doc.insert("time_end", bucky_time_to_chrono_time(v1.time_range.end)); + doc.insert("total", v1.total); + doc.insert("success", v1.success); + doc.insert("total_time", v1.total_time as i64); + if let Some(total_size) = v1.total_size { + doc.insert("total_size", total_size as i64); + } else { + doc.insert("total_size", 0); + } + + reqs_vec.push(doc.clone()); + } + + if !reqs_vec.is_empty() { + let _ = self.request_coll.insert_many(reqs_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to req coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to req coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_request success: obj={:?}", all); + + reqs_vec.clear(); + } + } + + Ok(()) + } + + async fn insert_action_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.clone(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let actions = v.actions.clone(); + + let mut actions_vec = Vec::new(); + for action in actions { + doc.insert("item_id", action.id); + doc.insert("time", bucky_time_to_chrono_time(action.time)); + doc.insert("err", action.err); + doc.insert("name", action.name); + doc.insert("value", action.value); + + actions_vec.push(doc.clone()); + } + + if !actions_vec.is_empty() { + let _ = self.action_coll.insert_many(actions_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to action coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to action coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_action success: obj={:?}", all); + + actions_vec.clear(); + } + + } + + Ok(()) + } + + + async fn insert_acc_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.to_owned(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let accs = v.accumulations.clone(); + + let mut acc_vec = Vec::new(); + for (_k1, v1) in accs { + doc.insert("item_id", v1.id); + doc.insert("time", bucky_time_to_chrono_time(v1.time_range.begin.clone())); + doc.insert("time_begin", bucky_time_to_chrono_time(v1.time_range.begin)); + doc.insert("time_end", bucky_time_to_chrono_time(v1.time_range.end)); + doc.insert("total", v1.total); + doc.insert("success", v1.success); + if let Some(total_size) = v1.total_size { + doc.insert("total_size", total_size as i64); + } else { + doc.insert("total_size", 0); + } + + acc_vec.push(doc.clone()); + } + + if !acc_vec.is_empty() { + let _ = self.acc_coll.insert_many(acc_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to acc coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to acc coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_accumulation success: obj={:?}", all); + acc_vec.clear(); + } + } + + Ok(()) + } + + + async fn insert_record_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + let mut doc = Document::new(); + doc.insert("device_id", device_id.to_owned()); + doc.insert("people_id", people_id.to_owned()); + doc.insert("dec_id", dec_id.to_owned()); + doc.insert("dec_name", dec_name.to_owned()); + doc.insert("version", version.to_owned()); + + for (_k, v) in all { + // device_id+dec_id+version +isolate+item_id+time + doc.insert("isolate", v.id.clone()); + + // let time_range = v.time_range.to_owned(); + // doc.insert("time_begin", time_range.begin); + // doc.insert("time_end", time_range.end); + + let records = v.records.clone(); + + let mut record_vec = Vec::new(); + for (_k1, v1) in records { + doc.insert("item_id", v1.id); + doc.insert("time", bucky_time_to_chrono_time(v1.time)); + doc.insert("total", v1.total as i64); + if let Some(total_size) = v1.total_size { + doc.insert("total_size", total_size as i64); + } else { + doc.insert("total_size", 0); + } + + record_vec.push(doc.clone()); + } + + if !record_vec.is_empty() { + let _ = self.record_coll.insert_many(record_vec.clone(), None).await.map_err(|e| { + let msg; + let code = if Self::is_exists_error(&e) { + msg = format!( + "insert object to record coll but already exists: {:?}, error: {}", + all, e + ); + BuckyErrorCode::AlreadyExists + } else { + msg = format!("insert object to record coll error: {:?} {}", all, e); + BuckyErrorCode::MongoDBError + }; + + warn!("{}", msg); + BuckyError::new(code, msg) + })?; + + info!("insert new to perf_record success: obj={:?}", all); + + record_vec.clear(); + } + } + + Ok(()) + } + + + pub async fn insert_entity_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + + let _ = self.insert_reqs_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + let _ = self.insert_action_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + let _ = self.insert_acc_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + let _ = self.insert_record_list(people_id.clone(), device_id.clone(), dec_id.clone(), dec_name.clone(), version.clone(), all).await; + + Ok(()) + } + +} + +#[async_trait] +impl Storage for MangodbStorage { + async fn insert_entity_list(&self, people_id: String, device_id: String, dec_id: String, dec_name: String, version: String, all: &HashMap) -> BuckyResult<()> { + self.insert_entity_list(people_id, device_id, dec_id, dec_name, version, all).await + } +} \ No newline at end of file From ac0ed1507895e38c1ad72f51f20389dadfd2a520 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 13:51:50 +0800 Subject: [PATCH 352/553] Do not cache chunk if already exists in data request --- src/component/cyfs-bdt-ext/src/cache/reader/cache.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs index 07991125d..6ca443db5 100644 --- a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs +++ b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs @@ -62,6 +62,7 @@ impl ChunkListCacheReader { let ret = chunk_manager.exist(cache.chunk()).await; if ret { debug!("cache chunk to chunk manager but already exists! chunk={}", cache.chunk()); + return; } let cache_wrapper = ChunkCacheWrapper::new(cache.clone()); From fdc1239daf0e60bc54927138ed264a6b5d8b9a07 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 13:56:49 +0800 Subject: [PATCH 353/553] Fix body length error when mime sniffing in cyfs-runtime --- src/service/cyfs-runtime/src/mime.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/service/cyfs-runtime/src/mime.rs b/src/service/cyfs-runtime/src/mime.rs index 405b385af..d6e7a5653 100644 --- a/src/service/cyfs-runtime/src/mime.rs +++ b/src/service/cyfs-runtime/src/mime.rs @@ -78,8 +78,12 @@ impl MimeHelper { // 根据内容猜测 // read some content and try sniff the mime use async_std::io::ReadExt; - let mut body = resp.take_body().into_reader(); let body_len = resp.len(); + if body_len == Some(0) { + return; + } + + let mut body = resp.take_body().into_reader(); let mut content: Vec = vec![0; 512]; let read_content_len; match body.read(&mut content).await { From 36351c8799d9b9bc4959d1037272df388bc1aeb1 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 16:15:21 +0800 Subject: [PATCH 354/553] Optimize some logs level --- .../cyfs-chunk-cache/src/local_chunk_cache.rs | 2 +- .../cyfs-stack/src/interface/browser_server.rs | 2 +- .../src/non_api/inner_path/objectmap_loader.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs index 5fb4bed09..9bd4887c3 100644 --- a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs +++ b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs @@ -630,7 +630,7 @@ impl TSingleDiskChunkCache for SingleDiskChunkCache { #[async_trait::async_trait] impl ChunkCache for SingleDiskChunkCache { async fn get_chunk(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult> { - log::info!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); + log::debug!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); let file_path = self.get_file_path(chunk_id, false); if !file_path.exists() { #[cfg(target_os = "windows")] diff --git a/src/component/cyfs-stack/src/interface/browser_server.rs b/src/component/cyfs-stack/src/interface/browser_server.rs index ae27a7433..c7e63153d 100644 --- a/src/component/cyfs-stack/src/interface/browser_server.rs +++ b/src/component/cyfs-stack/src/interface/browser_server.rs @@ -376,7 +376,7 @@ impl BrowserSanboxHttpServer { } } None => { - warn!("browser dec request but dec_id header or query pairs missing! req={}, origin={:?}", req.url(), origin); + debug!("browser dec request but dec_id header or query pairs missing! req={}, origin={:?}", req.url(), origin); drop(origin); // insert the origin dec_id diff --git a/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs b/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs index 5964b236e..e2e20b01b 100644 --- a/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs +++ b/src/component/cyfs-stack/src/non_api/inner_path/objectmap_loader.rs @@ -27,11 +27,6 @@ impl NONObjectMapLoader { pub async fn load(&self, req: NONGetObjectInputRequest) -> BuckyResult { let inner_path = req.inner_path.unwrap(); - info!( - "will get objectmap with inner path: {}, {}", - req.object_id, inner_path - ); - assert_eq!(req.object_id.obj_type_code(), ObjectTypeCode::ObjectMap); // first check access at object level @@ -97,6 +92,11 @@ impl NONObjectMapLoader { let (object, object_raw) = ret.unwrap(); + info!( + "get object from objectmap with inner path: {}, {}, got={}", + req.object_id, inner_path, object_id, + ); + let info = NONObjectInfo { object_id: object_id.to_owned(), object_raw, From 991f817cedeba988061ff7f6fa1bc7f8c783da72 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 19:33:18 +0800 Subject: [PATCH 355/553] Fix the bug that build file object access cannot take effect --- src/component/cyfs-stack/src/util_api/local/build_dir_task.rs | 4 ++-- .../cyfs-stack/src/util_api/local/build_file_task.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs b/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs index 119789132..3379abf79 100644 --- a/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs +++ b/src/component/cyfs-stack/src/util_api/local/build_dir_task.rs @@ -512,7 +512,7 @@ impl BuildDirTask { start_pos: usize, ) -> BuckyResult { let path_str = path.to_string_lossy().to_string(); - log::info!("build_dir {}", path_str.as_str()); + log::info!("build_dir {}, start_pos={}", path_str, start_pos); { let mut task_state = self.task_state.lock().unwrap(); if !task_state @@ -583,7 +583,7 @@ impl BuildDirTask { let file_id = file.desc().calculate_id(); Ok((task_id, file_name, file_id)) } else { - let msg = format!("build_file_object unexpect status"); + let msg = format!("build_file_object unexpect status, task={}", task_id); log::error!("{}", msg.as_str()); Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)) } diff --git a/src/component/cyfs-stack/src/util_api/local/build_file_task.rs b/src/component/cyfs-stack/src/util_api/local/build_file_task.rs index bdc387b58..c4f226056 100644 --- a/src/component/cyfs-stack/src/util_api/local/build_file_task.rs +++ b/src/component/cyfs-stack/src/util_api/local/build_file_task.rs @@ -347,7 +347,7 @@ impl BuildFileTask { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: self.access, }; match self.noc.put_object(&req).await { @@ -633,6 +633,7 @@ mod build_file_task_test { chunk_size: 4 * 1024 * 1024, dec_id: dec_id.to_owned(), access: None, + chunk_method: TransPublishChunkMethod::default(), }; let task = task_manager .create_task( @@ -673,6 +674,7 @@ mod build_file_task_test { chunk_size: 4 * 1024 * 1024, dec_id: dec_id.to_owned(), access: None, + chunk_method: TransPublishChunkMethod::default(), }; let task = task_manager .create_task( From 5477443dac5f8547055a59f23d27c84850c4fb80 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 2 Mar 2023 19:39:19 +0800 Subject: [PATCH 356/553] Add chunk length verify to poll_read method in cache reader --- .../cyfs-bdt-ext/src/cache/reader/cache.rs | 63 ++++++++++++++----- .../src/data/target_data_manager.rs | 2 + 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs index 6ca443db5..8a12ebc68 100644 --- a/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs +++ b/src/component/cyfs-bdt-ext/src/cache/reader/cache.rs @@ -1,14 +1,13 @@ +use cyfs_base::*; use cyfs_bdt::{chunk::ChunkCache, DownloadTaskSplitRead}; use cyfs_chunk_cache::ChunkManagerRef; use cyfs_chunk_lib::*; -use cyfs_base::*; use async_std::io::{Read, Result}; use std::io::{Seek, SeekFrom}; use std::pin::Pin; use std::task::{Context, Poll}; - pub trait ChunkSplitReader: DownloadTaskSplitRead + Seek {} impl ChunkSplitReader for T {} @@ -19,15 +18,25 @@ pub struct ChunkListCacheReader { chunk_manager: ChunkManagerRef, last_cache_chunk: Option, + full_len: u64, + read_len: u64, } impl ChunkListCacheReader { pub fn new( chunk_manager: ChunkManagerRef, task_id: String, + full_len: u64, reader: Box, ) -> Self { - Self { task_id, reader, chunk_manager, last_cache_chunk: None, } + Self { + task_id, + reader, + chunk_manager, + last_cache_chunk: None, + full_len, + read_len: 0, + } } fn try_cache_chunk(&mut self, cache: &ChunkCache) { @@ -61,17 +70,30 @@ impl ChunkListCacheReader { async_std::task::spawn(async move { let ret = chunk_manager.exist(cache.chunk()).await; if ret { - debug!("cache chunk to chunk manager but already exists! chunk={}", cache.chunk()); + debug!( + "cache chunk to chunk manager but already exists! chunk={}", + cache.chunk() + ); return; } let cache_wrapper = ChunkCacheWrapper::new(cache.clone()); - match chunk_manager.put_chunk(cache.chunk(), Box::new(cache_wrapper)).await { + match chunk_manager + .put_chunk(cache.chunk(), Box::new(cache_wrapper)) + .await + { Ok(()) => { - info!("cache chunk to chunk manager success! chunk={}", cache.chunk()); + info!( + "cache chunk to chunk manager success! chunk={}", + cache.chunk() + ); } Err(e) => { - info!("cache chunk to chunk manager failed! chunk={}, {}", cache.chunk(), e); + info!( + "cache chunk to chunk manager failed! chunk={}, {}", + cache.chunk(), + e + ); } } }); @@ -87,11 +109,26 @@ impl Read for ChunkListCacheReader { match Pin::new(self.reader.as_mut()).poll_split_read(cx, buf) { Poll::Ready(ret) => match ret { Ok(Some((cache, range))) => { + self.read_len += range.len() as u64; self.try_cache_chunk(&cache); Poll::Ready(Ok(range.len())) } - Ok(None) => Poll::Ready(Ok(0)), - Err(e) => Poll::Ready(Err(e)), + Ok(None) => { + if self.full_len != self.read_len { + error!( + "unmatch data size got from bdt: data={}, len={}, got={}", + self.task_id, self.full_len, self.read_len + ); + } + Poll::Ready(Ok(0)) + } + Err(e) => { + warn!( + "read data from bdt got error! data={}, len={}, {}", + self.task_id, self.full_len, e + ); + Poll::Ready(Err(e)) + } }, Poll::Pending => Poll::Pending, } @@ -99,10 +136,7 @@ impl Read for ChunkListCacheReader { } impl Seek for ChunkListCacheReader { - fn seek( - self: &mut Self, - pos: SeekFrom, - ) -> std::io::Result { + fn seek(self: &mut Self, pos: SeekFrom) -> std::io::Result { Pin::new(self.reader.as_mut()).seek(pos) } } @@ -149,7 +183,8 @@ impl Chunk for ChunkCacheWrapper { } async fn read(&mut self, buf: &mut [u8]) -> BuckyResult { - let len = self.cache + let len = self + .cache .read(self.offset, buf, || std::future::pending()) .await?; self.offset += len; diff --git a/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs b/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs index 662b2b892..80bf56b8b 100644 --- a/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs +++ b/src/component/cyfs-bdt-ext/src/data/target_data_manager.rs @@ -85,6 +85,7 @@ impl TargetDataManager { let reader = ChunkListCacheReader::new( self.chunk_manager.clone(), file_id.to_string(), + total_size, Box::new(reader), ); @@ -154,6 +155,7 @@ impl TargetDataManager { let reader = ChunkListCacheReader::new( self.chunk_manager.clone(), chunk_id.to_string(), + total_size as u64, Box::new(reader), ); From 684ef7afe27256c0597c9caedf599f4e2107d226 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 3 Mar 2023 00:32:33 +0800 Subject: [PATCH 357/553] Add chunk length and hash verify when write to local cache --- .../cyfs-chunk-cache/src/local_chunk_cache.rs | 597 +++++++++++++----- .../src/trans_api/local/publish_manager.rs | 4 +- 2 files changed, 428 insertions(+), 173 deletions(-) diff --git a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs index 9bd4887c3..368554f41 100644 --- a/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs +++ b/src/component/cyfs-chunk-cache/src/local_chunk_cache.rs @@ -1,17 +1,17 @@ -use std::fs::{create_dir_all}; +use crate::{Chunk, ChunkCache, ChunkMut, ChunkType, MMapChunk, MMapChunkMut, MemChunk}; +use cyfs_base::*; +use cyfs_chunk_lib::{ChunkMeta}; +use cyfs_debug::Mutex; +use futures_lite::AsyncWriteExt; +use num_traits::abs; +use num_traits::float::Float; +use scan_dir::ScanDir; +use std::fs::create_dir_all; use std::hash::Hasher; use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock}; use std::u64; -use cyfs_base::*; use sysinfo::{DiskExt, RefreshKind, SystemExt}; -use crate::{Chunk, ChunkCache, ChunkMut, MMapChunk, MMapChunkMut, MemChunk, ChunkType}; -use num_traits::float::Float; -use futures_lite::AsyncWriteExt; -use num_traits::abs; -use scan_dir::ScanDir; -use cyfs_chunk_lib::{ChunkMeta, ChunkRead}; -use cyfs_debug::Mutex; #[derive(Clone, RawEncode, RawDecode)] pub(crate) struct LocalChunkCacheMetaRecord { @@ -52,7 +52,7 @@ impl LocalChunkCacheMetaRecord { pub fn get_weight(&self, path: &str) -> Option { for (item, weight) in self.list.iter() { if path == item.as_str() { - return Some(*weight) + return Some(*weight); } } None @@ -71,40 +71,30 @@ impl LocalChunkCacheMeta { pub fn add_update_record(&mut self, disk_cache_list: Vec<(String, u32)>) { let record = match self.list.last() { - Some(last) => { - LocalChunkCacheMetaRecord::new(Some(last.hash()), disk_cache_list) - }, - None => { - LocalChunkCacheMetaRecord::new(None, disk_cache_list) - } + Some(last) => LocalChunkCacheMetaRecord::new(Some(last.hash()), disk_cache_list), + None => LocalChunkCacheMetaRecord::new(None, disk_cache_list), }; self.list.push(record); } pub fn last_hash(&self) -> Option { match self.list.last() { - Some(last) => { - last.prev_hash.clone() - }, - None => None + Some(last) => last.prev_hash.clone(), + None => None, } } pub fn is_latest(&self, disk_cache_list: &Vec<(String, u32)>) -> bool { match self.list.last() { - Some(last) => { - last.is_same(disk_cache_list) - }, - None => false + Some(last) => last.is_same(disk_cache_list), + None => false, } } pub fn get_latest_weight(&self, path: &str) -> Option { match self.list.last() { - Some(last) => { - last.get_weight(path) - }, - None => None + Some(last) => last.get_weight(path), + None => None, } } @@ -114,10 +104,8 @@ impl LocalChunkCacheMeta { pub fn get_latest_record(&self) -> Option { match self.list.last() { - Some(last) => { - Some(last.clone()) - }, - None => None + Some(last) => Some(last.clone()), + None => None, } } @@ -141,7 +129,7 @@ pub(crate) fn get_cache_path_list() -> Vec<(PathBuf, u64)> { cache_list } -pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64){ +pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64) { let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_disks_list()); let dist_list = system.disks(); let mut total = 0; @@ -149,7 +137,10 @@ pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64){ let mut max_match_path = PathBuf::new(); for disk in dist_list { let disk_mount = disk.mount_point().to_path_buf(); - if path.starts_with(disk_mount.as_path()) && max_match_path.to_string_lossy().to_string().len() < disk_mount.to_string_lossy().to_string().len() { + if path.starts_with(disk_mount.as_path()) + && max_match_path.to_string_lossy().to_string().len() + < disk_mount.to_string_lossy().to_string().len() + { max_match_path = disk_mount; total = disk.total_space(); available = disk.available_space(); @@ -160,21 +151,25 @@ pub(crate) fn get_disk_info_of_path(path: &Path) -> (u64, u64){ pub(crate) async fn get_path_size(path: PathBuf) -> BuckyResult { async_std::task::spawn_blocking(move || { - ScanDir::files().skip_dirs(true).walk(path.as_path(), |it| { - let mut sum = 0; - for (entry, _) in it { - match entry.metadata() { - Ok(meta) => sum += meta.len(), - Err(_) => {} + ScanDir::files() + .skip_dirs(true) + .walk(path.as_path(), |it| { + let mut sum = 0; + for (entry, _) in it { + match entry.metadata() { + Ok(meta) => sum += meta.len(), + Err(_) => {} + } } - } - sum - }).map_err(|_e| { - let msg = format!("scan path {} err", path.to_string_lossy().to_string()); - log::error!("{}", msg.as_str()); - BuckyError::new(BuckyErrorCode::Failed, msg) - }) - }).await + sum + }) + .map_err(|_e| { + let msg = format!("scan path {} err", path.to_string_lossy().to_string()); + log::error!("{}", msg.as_str()); + BuckyError::new(BuckyErrorCode::Failed, msg) + }) + }) + .await } pub(crate) trait DiskScanner: Send + Sync { @@ -196,13 +191,19 @@ pub(crate) struct LocalChunkCache LocalChunkCache { +impl + LocalChunkCache +{ pub async fn new(isolate: &str, scanner: SCANNER) -> BuckyResult { let obj = Self { disk_cache_list: RwLock::new(Vec::new()), cache_meta: Mutex::new(LocalChunkCacheMeta::new()), scanner, - isolate: if isolate.is_empty() { "default".to_string() } else { isolate.to_string() } + isolate: if isolate.is_empty() { + "default".to_string() + } else { + isolate.to_string() + }, }; obj.refresh_cache().await?; Ok(obj) @@ -225,21 +226,21 @@ impl LocalChun // 遍历磁盘列表 let cache_list = self.scanner.get_cache_path_list(); for (path, space) in cache_list.iter() { - log::info!("read cache path {} {}", path.to_string_lossy().to_string(), *space); + log::info!( + "read cache path {} {}", + path.to_string_lossy().to_string(), + *space + ); let path = path.as_path().join(self.isolate.as_str()); if !path.exists() { let _ = create_dir_all(path.as_path()); } let cache = match self.get_cache(path.as_path()) { - Some(cache) => { - cache - }, - None => { - Arc::new(CACHE::new(path.to_path_buf())) - } + Some(cache) => cache, + None => Arc::new(CACHE::new(path.to_path_buf())), }; let cache_meta = cache.get_local_cache_meta()?; - let weight = (space/1024/1024/1024) as u32; + let weight = (space / 1024 / 1024 / 1024) as u32; // 获取最新的cache元数据列表 if cache_meta.record_count() as i32 > max_record_count { @@ -255,12 +256,20 @@ impl LocalChun let mut meta_list = Vec::new(); for (cache, weight) in disk_cache_list.iter_mut() { let path_str = cache.get_cache_path().to_string_lossy().to_string(); - if let Some(latest_weight) = global_last_record.get_latest_weight(path_str.as_str()) { + if let Some(latest_weight) = global_last_record.get_latest_weight(path_str.as_str()) + { //如果当前空间大于上次记录空间,表示该区域已经扩容 if *weight > latest_weight { - let path_size = (get_path_size(cache.get_cache_path().to_path_buf()).await?/1024/1024/1024) as u32; + let path_size = (get_path_size(cache.get_cache_path().to_path_buf()) + .await? + / 1024 + / 1024 + / 1024) as u32; //如果新扩容区域小于上次记录空间的20%或扩容空间小于50G,则保持全新不变 - if ((*weight + path_size - latest_weight) as f32 / (latest_weight as f32) < 0.2 ) || (*weight + path_size - latest_weight < 50) { + if ((*weight + path_size - latest_weight) as f32 / (latest_weight as f32) + < 0.2) + || (*weight + path_size - latest_weight < 50) + { *weight = latest_weight; } else { *weight = *weight + path_size; @@ -269,10 +278,16 @@ impl LocalChun } else if *weight > 10 || *weight as f32 / (latest_weight as f32) > 0.1 { *weight = latest_weight; } else { - let path_size = (get_path_size(cache.get_cache_path().to_path_buf()).await?/1024/1024/1024) as u32; + let path_size = (get_path_size(cache.get_cache_path().to_path_buf()) + .await? + / 1024 + / 1024 + / 1024) as u32; //如果理论剩余空间和真实剩余空间的比例小于15%或理论剩余空间和真实剩余空间的差值小于5G,则保持权重不变 - if abs(1f32 - (latest_weight - path_size) as f32 / (*weight as f32)) < 0.15 || abs(latest_weight as i64 - path_size as i64 - *weight as i64) < 5 { + if abs(1f32 - (latest_weight - path_size) as f32 / (*weight as f32)) < 0.15 + || abs(latest_weight as i64 - path_size as i64 - *weight as i64) < 5 + { *weight = latest_weight; } else { *weight = path_size + *weight; @@ -286,7 +301,10 @@ impl LocalChun if !global_last_record.is_latest(&meta_list) { global_last_record.add_update_record(meta_list); - log::info!("chunk cache change.item count {}", global_last_record.record_count()); + log::info!( + "chunk cache change.item count {}", + global_last_record.record_count() + ); for (cache, _) in disk_cache_list.iter_mut() { cache.set_local_cache_meta(&global_last_record)?; @@ -317,7 +335,7 @@ impl LocalChun } for (disk_cache, weight) in disk_cache_list.iter() { let hash = Self::hash(chunk_id, disk_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; cache = Some(disk_cache); @@ -341,7 +359,7 @@ impl LocalChun } for (disk_cache, weight) in disk_cache_list.iter() { let hash = Self::hash(chunk_id, disk_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; cache = Some(disk_cache); @@ -357,7 +375,11 @@ impl LocalChun } } - async fn find_chunk_from_prev_async(&self, chunk_id: &ChunkId, cache: &Arc) -> BuckyResult<()> { + async fn find_chunk_from_prev_async( + &self, + chunk_id: &ChunkId, + cache: &Arc, + ) -> BuckyResult<()> { let cache_meta = self.cache_meta.lock().unwrap().clone(); let mut index = cache_meta.record_count() as i64 - 2; while index >= 0 { @@ -367,7 +389,7 @@ impl LocalChun for (cache_path, weight) in record.list.iter() { let tmp_cache = Arc::new(CACHE::new(PathBuf::from(cache_path.to_string()))); let hash = Self::hash(chunk_id, tmp_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; max_cache = Some(tmp_cache); @@ -378,7 +400,7 @@ impl LocalChun if let Ok(chunk) = tmp_cache.get_chunk(chunk_id, ChunkType::MMapChunk).await { cache.put_chunk(chunk_id, chunk).await?; tmp_cache.delete_chunk(chunk_id).await?; - return Ok(()) + return Ok(()); } } index -= 1; @@ -396,7 +418,7 @@ impl LocalChun for (cache_path, weight) in record.list.iter() { let tmp_cache = Arc::new(CACHE::new(PathBuf::from(cache_path.to_string()))); let hash = Self::hash(chunk_id, tmp_cache.get_cache_id()); - let v = (hash as f64/u64::MAX as f64).ln() / (*weight as f64); + let v = (hash as f64 / u64::MAX as f64).ln() / (*weight as f64); if v > max { max = v; max_cache = Some(tmp_cache); @@ -405,7 +427,7 @@ impl LocalChun if max_cache.is_some() { let tmp_cache = max_cache.unwrap(); if tmp_cache.is_exist(chunk_id).await { - return Ok(tmp_cache) + return Ok(tmp_cache); } } index -= 1; @@ -415,13 +437,17 @@ impl LocalChun } #[async_trait::async_trait] -impl ChunkCache for LocalChunkCache { - async fn get_chunk(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult> { +impl ChunkCache + for LocalChunkCache +{ + async fn get_chunk( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult> { let cache = self.get_disk_cache(chunk_id)?; match cache.get_chunk(chunk_id, chunk_type).await { - Ok(chunk) => { - Ok(chunk) - }, + Ok(chunk) => Ok(chunk), Err(e) => { if e.code() == BuckyErrorCode::NotFound { self.find_chunk_from_prev_async(chunk_id, &cache).await?; @@ -459,24 +485,26 @@ impl ChunkCach async fn is_exist(&self, chunk_id: &ChunkId) -> bool { let cache = match self.get_disk_cache(chunk_id) { Ok(cache) => cache, - Err(_) => return false + Err(_) => return false, }; if !cache.is_exist(chunk_id).await { match self.find_chunk_from_prev_async(chunk_id, &cache).await { Ok(()) => true, - Err(_) => false + Err(_) => false, } } else { true } } - async fn get_chunk_meta(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult { + async fn get_chunk_meta( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult { let cache = self.get_disk_cache(chunk_id)?; match cache.get_chunk_meta(chunk_id, chunk_type).await { - Ok(chunk) => { - Ok(chunk) - }, + Ok(chunk) => Ok(chunk), Err(e) => { if e.code() == BuckyErrorCode::NotFound { self.find_chunk_from_prev_async(chunk_id, &cache).await?; @@ -518,24 +546,20 @@ impl SingleDiskChunkCache { let hash_str = file_id.to_base36(); let (tmp, last) = hash_str.split_at(hash_str.len() - 3); let (mut first, mut mid) = tmp.split_at(tmp.len() - 3); - + /* Do not use the following reserved names as filenames: CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、 LPT6、LPT7、LPT8、 LPT9 */ match mid { "con" | "aux" | "nul" | "prn" => { (first, mid) = tmp.split_at(tmp.len() - 4); } - _ => {}, + _ => {} } let last = match last { - "con" | "aux" | "nul" | "prn" => { - Cow::Owned(format!("{}_", last)) - } - _ => { - Cow::Borrowed(last) - }, + "con" | "aux" | "nul" | "prn" => Cow::Owned(format!("{}_", last)), + _ => Cow::Borrowed(last), }; - + let path = self.path.join(last.as_ref()).join(mid); if is_create && !path.exists() { if let Err(e) = create_dir_all(path.as_path()) { @@ -561,10 +585,16 @@ impl SingleDiskChunkCache { pub async fn remove_file(&self, file_id: &ChunkId) -> BuckyResult<()> { let file_path = self.get_file_path(file_id, false); - let _ = async_std::fs::remove_file(file_path.as_path()).await.map_err(|e| { - log::error!("remove file {} failed.err={}", file_path.to_string_lossy().to_string(), &e); - BuckyError::from(e) - }); + let _ = async_std::fs::remove_file(file_path.as_path()) + .await + .map_err(|e| { + log::error!( + "remove file {} failed.err={}", + file_path.to_string_lossy().to_string(), + &e + ); + BuckyError::from(e) + }); Ok(()) } @@ -577,7 +607,11 @@ impl SingleDiskChunkCache { let file_meta = match std::fs::metadata(file_path.as_path()) { Ok(meta) => meta, Err(e) => { - let msg = format!("read file {} meta err.{}", file_path.to_string_lossy().to_string(), e); + let msg = format!( + "read file {} meta err.{}", + file_path.to_string_lossy().to_string(), + e + ); log::error!("{}", msg); return false; } @@ -589,6 +623,67 @@ impl SingleDiskChunkCache { true } } + + async fn write_with_verify( + chunk_id: ChunkId, + mut chunk: Box, + mut file: async_std::fs::File, + file_path: &Path, + ) -> BuckyResult<()> { + use sha2::Digest; + + let mut sha256 = sha2::Sha256::new(); + let mut buf = Vec::with_capacity(1024 * 256); + unsafe { + buf.set_len(1024 * 256); + } + + let mut file_len = 0; + loop { + match chunk.read(&mut buf).await { + Ok(bytes) => { + if bytes == 0 { + break Ok(()); + } + + sha256.input(&buf[0..bytes]); + file_len += bytes; + + file.write_all(&buf[0..bytes]).await.map_err(|e| { + let msg = format!( + "write chunk slice to file failed! chunk={}, slice bytes={}, file={}, {}", + chunk_id, + bytes, + file_path.display(), + e + ); + log::error!("{}", msg); + let e: BuckyError = e.into(); + e.with_msg(msg) + })?; + } + Err(e) => { + break Err(e); + } + } + }?; + + if file_len != chunk_id.len() { + let msg = format!("mismatched chunk length! chunk={}, len={}, got={}", chunk_id, chunk_id.len(), file_len); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + } + + let hash: HashValue = sha256.result().into(); + let actual_id = ChunkId::new(&hash, file_len as u32); + if actual_id != chunk_id { + let msg = format!("mismatched chunk hash value! chunk={}, len={}, got={}", chunk_id, chunk_id.len(), actual_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + } + + Ok(()) + } } impl TSingleDiskChunkCache for SingleDiskChunkCache { @@ -616,7 +711,8 @@ impl TSingleDiskChunkCache for SingleDiskChunkCache { if !meta_path.exists() { return Ok(LocalChunkCacheMeta::new()); } - let (meta, _) = LocalChunkCacheMeta::decode_from_file(meta_path.as_path(), &mut Vec::new())?; + let (meta, _) = + LocalChunkCacheMeta::decode_from_file(meta_path.as_path(), &mut Vec::new())?; Ok(meta) } @@ -629,21 +725,33 @@ impl TSingleDiskChunkCache for SingleDiskChunkCache { #[async_trait::async_trait] impl ChunkCache for SingleDiskChunkCache { - async fn get_chunk(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult> { + async fn get_chunk( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult> { log::debug!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); let file_path = self.get_file_path(chunk_id, false); if !file_path.exists() { #[cfg(target_os = "windows")] { if !self.upgrade.try_update(&file_path, chunk_id) { - let msg = format!("get chunk's file but not exist! chunk={}, file={}", chunk_id, file_path.display()); + let msg = format!( + "get chunk's file but not exist! chunk={}, file={}", + chunk_id, + file_path.display() + ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } } #[cfg(not(target_os = "windows"))] { - let msg = format!("get chunk's file but not exist! chunk={}, file={}", chunk_id, file_path.display()); + let msg = format!( + "get chunk's file but not exist! chunk={}, file={}", + chunk_id, + file_path.display() + ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } @@ -653,13 +761,20 @@ impl ChunkCache for SingleDiskChunkCache { ChunkType::MMapChunk => { let chunk: Box = Box::new(MMapChunk::open(file_path, None).await?); Ok(chunk) - }, + } ChunkType::MemChunk => { - let buf = async_std::fs::read(file_path.as_path()).await.map_err(|e| { - let msg = format!("open chunk's file error! chunk={}, file={}, {}", chunk_id, file_path.display(), e); - log::error!("{}", msg); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let buf = async_std::fs::read(file_path.as_path()) + .await + .map_err(|e| { + let msg = format!( + "open chunk's file error! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; let chunk: Box = Box::new(MemChunk::from(buf)); Ok(chunk) } @@ -670,7 +785,12 @@ impl ChunkCache for SingleDiskChunkCache { let file_path = self.get_file_path(chunk_id, true); log::info!("new chunk {}", file_path.to_string_lossy().to_string()); if file_path.exists() { - let msg = format!("[{}:{}] file {} exist", file!(), line!(), file_path.to_string_lossy().to_string()); + let msg = format!( + "[{}:{}] file {} exist", + file!(), + line!(), + file_path.to_string_lossy().to_string() + ); log::error!("{}", msg.as_str()); return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, msg)); } @@ -694,40 +814,92 @@ impl ChunkCache for SingleDiskChunkCache { // log::info!("will put chunk, chunk={}, len={}, local file={}", chunk_id, chunk_id.len(), file_path.display()); if file_path.exists() { - let msg = format!("put chunk but local file already exist! chunk={}, file={},", chunk_id, file_path.display()); + let msg = format!( + "put chunk but local file already exist! chunk={}, file={},", + chunk_id, + file_path.display() + ); log::info!("{}", msg.as_str()); return Ok(()); } - let mut file = async_std::fs::OpenOptions::new().read(true).write(true).create(true).open(file_path.as_path()).await.map_err(|e| { - let msg = format!("put chunk but open local file failed! chunk={}, file={}, {}", chunk_id, file_path.display(), e); - log::error!("{}", msg); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let mut file = async_std::fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(file_path.as_path()) + .await + .map_err(|e| { + let msg = format!( + "put chunk but open local file failed! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; chunk.as_mut().seek(std::io::SeekFrom::Start(0)).await?; + if let Err(e) = Self::write_with_verify(chunk_id.to_owned(), chunk, file.clone(), &file_path).await { + if let Err(e) = async_std::fs::remove_file(&file_path).await { + log::error!("remove chunk local cache file failed! chunk={}, {}", chunk_id, e); + } + + return Err(e); + } + + /* let reader = ChunkRead::new(chunk); - let len = async_std::io::copy(reader, file.clone()).await.map_err(|e| { - let msg = format!("write chunk to file failed! chunk={}, len={}, file={}, {}", chunk_id, chunk_id.len(), file_path.display(), e); - log::error!("{}", msg); - let e: BuckyError = e.into(); - e.with_msg(msg) - })?; + let len = async_std::io::copy(reader, file.clone()) + .await + .map_err(|e| { + let msg = format!( + "write chunk to file failed! chunk={}, len={}, file={}, {}", + chunk_id, + chunk_id.len(), + file_path.display(), + e + ); + log::error!("{}", msg); + let e: BuckyError = e.into(); + e.with_msg(msg) + })?; if len != chunk_id.len() as u64 { - let msg = format!("write chunk to file but got unmatch len! chunk={}, len={}, read={}, file={}", chunk_id, chunk_id.len(), len, file_path.display()); + let msg = format!( + "write chunk to file but got unmatch len! chunk={}, len={}, read={}, file={}", + chunk_id, + chunk_id.len(), + len, + file_path.display() + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::IoError, msg)); } + */ + + if let Err(e) = file.flush().await { + if let Err(e) = async_std::fs::remove_file(&file_path).await { + log::error!("remove chunk local cache file failed! chunk={}, {}", chunk_id, e); + } - file.flush().await.map_err(|e| { - let msg = format!("put chunk to local file but flush failed! chunk={}, file={}, {}", chunk_id, file_path.display(), e); + let msg = format!( + "put chunk to local file but flush failed! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); log::error!("{}", msg); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + return Err(BuckyError::new(BuckyErrorCode::IoError, msg)); + } - log::info!("put chunk to local file complete! chunk={}, file={}", chunk_id, file_path.display()); + log::info!( + "put chunk to local file complete! chunk={}, file={}", + chunk_id, + file_path.display() + ); Ok(()) } @@ -735,25 +907,41 @@ impl ChunkCache for SingleDiskChunkCache { self.chunk_exist(chunk_id) } - async fn get_chunk_meta(&self, chunk_id: &ChunkId, chunk_type: ChunkType) -> BuckyResult { + async fn get_chunk_meta( + &self, + chunk_id: &ChunkId, + chunk_type: ChunkType, + ) -> BuckyResult { log::debug!("SingleDiskChunkCache get_chunk {}", chunk_id.to_string()); let file_path = self.get_file_path(chunk_id, false); if !file_path.exists() { - let msg = format!("local chunk file not exists! chunk={}, file={}", file_path.display(), chunk_id); + let msg = format!( + "local chunk file not exists! chunk={}, file={}", + file_path.display(), + chunk_id + ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::NotFound, msg)); } match chunk_type { - ChunkType::MMapChunk => { - Ok(ChunkMeta::MMapChunk(file_path.to_string_lossy().to_string(), None)) - }, + ChunkType::MMapChunk => Ok(ChunkMeta::MMapChunk( + file_path.to_string_lossy().to_string(), + None, + )), ChunkType::MemChunk => { - let buf = async_std::fs::read(file_path.as_path()).await.map_err(|e| { - let msg = format!("open local chunk file failed! chunk={}, file={}, {}", chunk_id, file_path.display(), e); - log::error!("{}", msg.as_str()); - BuckyError::new(BuckyErrorCode::IoError, msg) - })?; + let buf = async_std::fs::read(file_path.as_path()) + .await + .map_err(|e| { + let msg = format!( + "open local chunk file failed! chunk={}, file={}, {}", + chunk_id, + file_path.display(), + e + ); + log::error!("{}", msg.as_str()); + BuckyError::new(BuckyErrorCode::IoError, msg) + })?; Ok(ChunkMeta::MemChunk(buf)) } } @@ -762,15 +950,18 @@ impl ChunkCache for SingleDiskChunkCache { #[cfg(test)] mod test_local_chunk_cache { + use crate::{ + Chunk, ChunkCache, ChunkMut, ChunkRead, ChunkType, ChunkWrite, DiskScanner, + LocalChunkCache, LocalChunkCacheMeta, TSingleDiskChunkCache, + }; + use cyfs_base::{hash_data, BuckyError, BuckyErrorCode, BuckyResult, ChunkId, HashValue}; + use cyfs_chunk_lib::ChunkMeta; + use futures_lite::{AsyncReadExt, AsyncWriteExt}; use std::collections::HashMap; use std::io::{SeekFrom, Write}; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::sync::Mutex; - use futures_lite::{AsyncReadExt, AsyncWriteExt}; - use cyfs_chunk_lib::ChunkMeta; - use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ChunkId, hash_data, HashValue}; - use crate::{ChunkCache, Chunk, ChunkMut, ChunkType, DiskScanner, LocalChunkCache, LocalChunkCacheMeta, TSingleDiskChunkCache, ChunkRead, ChunkWrite}; pub type RandomId = HashValue; @@ -797,20 +988,44 @@ mod test_local_chunk_cache { unsafe { if HAS_RUN { let mut list = Vec::new(); - list.push((PathBuf::from("/test1".to_string()), 1024*1024*1024*50)); - list.push((PathBuf::from("/test2".to_string()), 1024*1024*1024*100)); - list.push((PathBuf::from("/test3".to_string()), 1024*1024*1024*150)); - list.push((PathBuf::from("/test4".to_string()), 1024*1024*1024*200)); - list.push((PathBuf::from("/test5".to_string()), 1024*1024*1024*200)); + list.push((PathBuf::from("/test1".to_string()), 1024 * 1024 * 1024 * 50)); + list.push(( + PathBuf::from("/test2".to_string()), + 1024 * 1024 * 1024 * 100, + )); + list.push(( + PathBuf::from("/test3".to_string()), + 1024 * 1024 * 1024 * 150, + )); + list.push(( + PathBuf::from("/test4".to_string()), + 1024 * 1024 * 1024 * 200, + )); + list.push(( + PathBuf::from("/test5".to_string()), + 1024 * 1024 * 1024 * 200, + )); list } else { HAS_RUN = true; let mut list = Vec::new(); - list.push((PathBuf::from("/test1".to_string()), 1024*1024*1024*50)); - list.push((PathBuf::from("/test2".to_string()), 1024*1024*1024*100)); - list.push((PathBuf::from("/test3".to_string()), 1024*1024*1024*150)); - list.push((PathBuf::from("/test4".to_string()), 1024*1024*1024*200)); - list.push((PathBuf::from("/test5".to_string()), 1024*1024*1024*200)); + list.push((PathBuf::from("/test1".to_string()), 1024 * 1024 * 1024 * 50)); + list.push(( + PathBuf::from("/test2".to_string()), + 1024 * 1024 * 1024 * 100, + )); + list.push(( + PathBuf::from("/test3".to_string()), + 1024 * 1024 * 1024 * 150, + )); + list.push(( + PathBuf::from("/test4".to_string()), + 1024 * 1024 * 1024 * 200, + )); + list.push(( + PathBuf::from("/test5".to_string()), + 1024 * 1024 * 1024 * 200, + )); list } } @@ -830,7 +1045,7 @@ mod test_local_chunk_cache { path, cache_id, chunk_map: Mutex::new(Default::default()), - meta: Mutex::new(LocalChunkCacheMeta::new()) + meta: Mutex::new(LocalChunkCacheMeta::new()), } } @@ -855,15 +1070,17 @@ mod test_local_chunk_cache { #[async_trait::async_trait] impl ChunkCache for SingleDiskChunkCacheMock { - async fn get_chunk(&self, chunk_id: &ChunkId, _chunk_type: ChunkType) -> BuckyResult> { + async fn get_chunk( + &self, + chunk_id: &ChunkId, + _chunk_type: ChunkType, + ) -> BuckyResult> { return match self.chunk_map.lock().unwrap().get(chunk_id) { - Some(chunk) => { - Ok(Box::new(ChunkMock {buf: Vec::from(chunk.as_ref().deref())})) - }, - None => { - Err(BuckyError::new(BuckyErrorCode::NotFound, "")) - } - } + Some(chunk) => Ok(Box::new(ChunkMock { + buf: Vec::from(chunk.as_ref().deref()), + })), + None => Err(BuckyError::new(BuckyErrorCode::NotFound, "")), + }; } async fn new_chunk(&self, _chunk_id: &ChunkId) -> BuckyResult> { @@ -874,7 +1091,11 @@ mod test_local_chunk_cache { todo!() } - async fn put_chunk(&self, chunk_id: &ChunkId, mut chunk: Box) -> BuckyResult<()> { + async fn put_chunk( + &self, + chunk_id: &ChunkId, + mut chunk: Box, + ) -> BuckyResult<()> { log::info!("will put chunk, chunk={}, file={}", chunk_id); chunk.as_mut().seek(std::io::SeekFrom::Start(0)).await?; @@ -883,18 +1104,31 @@ mod test_local_chunk_cache { let mut buf = Vec::with_capacity(chunk_id.len()); let len = reader.read_to_end(&mut buf).await.map_err(|e| { - let msg = format!("read chunk to buffer failed! chunk={}, len={}, {}", chunk_id, chunk_id.len(), e); + let msg = format!( + "read chunk to buffer failed! chunk={}, len={}, {}", + chunk_id, + chunk_id.len(), + e + ); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::IoError, msg) })?; if len != chunk_id.len() { - let msg = format!("read chunk to buffer but got unmatch len! chunk={}, len={}, read={}", chunk_id, chunk_id.len(), len); + let msg = format!( + "read chunk to buffer but got unmatch len! chunk={}, len={}, read={}", + chunk_id, + chunk_id.len(), + len + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::IoError, msg)); } - self.chunk_map.lock().unwrap().insert(chunk_id.clone(), Box::new(ChunkMock{buf})); + self.chunk_map + .lock() + .unwrap() + .insert(chunk_id.clone(), Box::new(ChunkMock { buf })); Ok(()) } @@ -902,12 +1136,16 @@ mod test_local_chunk_cache { todo!() } - async fn get_chunk_meta(&self, _chunk_id: &ChunkId, _chunk_type: ChunkType) -> BuckyResult { + async fn get_chunk_meta( + &self, + _chunk_id: &ChunkId, + _chunk_type: ChunkType, + ) -> BuckyResult { todo!() } } pub struct ChunkMock { - buf: Vec + buf: Vec, } #[async_trait::async_trait] @@ -970,22 +1208,35 @@ mod test_local_chunk_cache { #[test] fn test_alloc() { async_std::task::block_on(async move { - let cache = LocalChunkCache::::new("", TestDiskScanner).await.unwrap(); + let cache = LocalChunkCache::::new("", TestDiskScanner) + .await + .unwrap(); let mut chunk_list = Vec::new(); for i in 0..1000000u32 { let random_id = RandomId::new_id(); - let chunk_id = ChunkId::new(&random_id, 8192*1024); + let chunk_id = ChunkId::new(&random_id, 8192 * 1024); chunk_list.push(chunk_id.clone()); - cache.put_chunk(&chunk_id, &mut ChunkMock{buf: i.to_be_bytes().to_vec()}).await.unwrap(); - let chunk = cache.get_chunk(&chunk_id, ChunkType::MemChunk).await.unwrap(); + cache + .put_chunk( + &chunk_id, + &mut ChunkMock { + buf: i.to_be_bytes().to_vec(), + }, + ) + .await + .unwrap(); + let chunk = cache + .get_chunk(&chunk_id, ChunkType::MemChunk) + .await + .unwrap(); let mut reader = ChunkRead::new(chunk); - let mut buf = [0u8;4]; + let mut buf = [0u8; 4]; let len = reader.read(&mut buf).await.unwrap(); assert_eq!(len, 4); let tmp = u32::from_be_bytes(buf); assert_eq!(u32::from_be_bytes(buf), i); - let chunk = Box::new(ChunkMock{buf: Vec::new()}); + let chunk = Box::new(ChunkMock { buf: Vec::new() }); let mut write = ChunkWrite::new(chunk); let len = write.write(&buf).await.unwrap(); assert_eq!(len, 4); @@ -993,7 +1244,11 @@ mod test_local_chunk_cache { { let list = cache.disk_cache_list.read().unwrap(); for (item, weight) in list.iter() { - println!("weight {} count {}", *weight, item.chunk_map.lock().unwrap().len()); + println!( + "weight {} count {}", + *weight, + item.chunk_map.lock().unwrap().len() + ); } } diff --git a/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs b/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs index 377315077..015083804 100644 --- a/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs +++ b/src/component/cyfs-stack/src/trans_api/local/publish_manager.rs @@ -350,8 +350,8 @@ impl PublishLocalDirTask { .join(sub_path.strip_prefix("/").unwrap()) .join(file_name); log::info!( - "publish file {}", - file_path.to_string_lossy().to_string() + "publish file {}, {}", + file_path.to_string_lossy().to_string(), object_id, ); file_recorder .record_file_chunk_list(file_path.as_path(), &file, self.chunk_method) From 0030621b937de2b536276a17cd18c01c4aef5c8c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Fri, 3 Mar 2023 15:15:58 +0800 Subject: [PATCH 358/553] Improve congtent-based mime sniffing mechanism in cyfs-runtime --- src/service/cyfs-runtime/src/mime.rs | 48 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/service/cyfs-runtime/src/mime.rs b/src/service/cyfs-runtime/src/mime.rs index d6e7a5653..35af7139c 100644 --- a/src/service/cyfs-runtime/src/mime.rs +++ b/src/service/cyfs-runtime/src/mime.rs @@ -4,6 +4,8 @@ use http_types::{mime, Mime, Url}; use mime_sniffer::{HttpRequest, MimeTypeSniffer}; use std::borrow::Cow; use std::str::FromStr; +use async_std::io::BufRead as AsyncBufRead; +use async_std::prelude::*; pub(crate) struct MimeHelper; @@ -77,29 +79,20 @@ impl MimeHelper { // 根据内容猜测 // read some content and try sniff the mime - use async_std::io::ReadExt; let body_len = resp.len(); if body_len == Some(0) { return; } - let mut body = resp.take_body().into_reader(); - let mut content: Vec = vec![0; 512]; - let read_content_len; - match body.read(&mut content).await { - Ok(bytes) => { - if bytes == 0 { - warn!("sniff mime read resp body but got empty! url={}", url); - return; - } + let body = resp.take_body().into_reader(); + let mut body = body.take(512); - read_content_len = bytes; - } - Err(e) => { - error!("sniff read resp body but error! url={}, {}", url, e); - resp.set_body(http_types::Body::from_reader(body, body_len)); - return; - } + let mut content: Vec = Vec::with_capacity(512); + if let Err(e) = body.read_to_end(&mut content).await { + error!("sniff read resp body but error! url={}, {}", url, e); + let new_body = Self::merge_body(body_len, content, body.into_inner()); + resp.set_body(new_body); + return; } let str_url = url.to_string(); @@ -155,7 +148,21 @@ impl MimeHelper { } } - let new_body = http_types::Body::from_bytes(content[..read_content_len].to_vec()); + let new_body = Self::merge_body(body_len, content, body.into_inner()); + resp.set_body(new_body); + } + + fn merge_body( + body_len: Option, + content: Vec, + body_reader: Box, + ) -> http_types::Body { + if content.len() == 0 { + return http_types::Body::from_reader(body_reader, body_len); + } + + let read_content_len = content.len(); + let new_body = http_types::Body::from_bytes(content); let tail_len = match body_len { Some(len) => { @@ -172,8 +179,7 @@ impl MimeHelper { None => None, }; - let tail_body = http_types::Body::from_reader(body, tail_len); - let new_body = new_body.chain(tail_body); - resp.set_body(new_body); + let tail_body = http_types::Body::from_reader(body_reader, tail_len); + new_body.chain(tail_body) } } From 2fd47a8b770b1bdf1cfe388d51b2130e4dce4136 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Fri, 3 Mar 2023 20:06:22 +0800 Subject: [PATCH 359/553] Fix: sn client stop ping after second try --- src/component/cyfs-bdt/src/sn/client/ping/client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-bdt/src/sn/client/ping/client.rs b/src/component/cyfs-bdt/src/sn/client/ping/client.rs index 06dc15952..a23a14249 100644 --- a/src/component/cyfs-bdt/src/sn/client/ping/client.rs +++ b/src/component/cyfs-bdt/src/sn/client/ping/client.rs @@ -502,7 +502,8 @@ impl PingClient { stack.keystore().reset_peer(&self.sn()); let session = session.reset(None, None); info!("{} start second try", self); - *active = ActiveState::SecondTry(session); + *active = ActiveState::SecondTry(session.clone_as_ping_session()); + next.to_start = Some(session); }, ActiveState::SecondTry(_) => { next.waiter = Some(waiter.transfer()); From bbc51ca4a70ed36b5a0ea731e858d6aa9735e533 Mon Sep 17 00:00:00 2001 From: tsukasa Date: Fri, 3 Mar 2023 20:17:21 +0800 Subject: [PATCH 360/553] Fix: sn client stop ping after second try --- src/component/cyfs-bdt/src/sn/client/ping/client.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/component/cyfs-bdt/src/sn/client/ping/client.rs b/src/component/cyfs-bdt/src/sn/client/ping/client.rs index a23a14249..d13e770b0 100644 --- a/src/component/cyfs-bdt/src/sn/client/ping/client.rs +++ b/src/component/cyfs-bdt/src/sn/client/ping/client.rs @@ -415,6 +415,7 @@ impl PingClient { struct NextStep { waiter: Option, update: Option<(Endpoint, Endpoint)>, + to_start: Option>, ping_once: bool, update_cache: Option> } @@ -424,6 +425,7 @@ impl PingClient { Self { waiter: None, update: None, + to_start: None, ping_once: false, update_cache: None } @@ -531,6 +533,13 @@ impl PingClient { } } + if let Some(session) = next.to_start { + let client = self.clone(); + task::spawn(async move { + client.sync_session_resp(session.as_ref(), session.wait().await); + }); + } + if let Some(waiter) = next.waiter { waiter.wake(); } From 8a06c03dfbd8a4a0581803b3872f7a6e4b1aeddf Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 15:38:38 +0800 Subject: [PATCH 361/553] Add continuous service publish --- scripts/pack.js | 76 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index d59ef46d2..c5f54d0dc 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -3,10 +3,9 @@ const child_process = require('child_process'); const targets = process.argv[2].split(";") const type = process.argv[3].split(";") const { apps, services } = require('./build_config') -const path = require('path') +const path = require('path'); +const assert = require('assert'); -const onlyput = process.argv[4] || "put" -const action = process.argv[5] || "put" const buildnumber = process.argv[6] || "0" const channel = process.argv[7] || "nightly" @@ -14,6 +13,41 @@ if (!fs.existsSync('Cargo.toml')) { console.error('cannot find Cargo.toml in cwd! check working dir') } +const PublishStep = { + Pack: 1, + Upload: 2, + SetVersion: 3, + Finish: 4 +} + +const step_file_name = "curstep" + +let processing = {}; +if (fs.existsSync(step_file_name)) { + processing = JSON.parse(fs.readFileSync(processing_name)) +} + +function set_step(service_name, step, arg) { + processing[service_name] = {step: step, arg: arg}; + fs.writeFileSync(step_file_name, JSON.stringify(processing)) +} + +function get_step_arg(service_name, step) { + if (processing[service_name].step === step) { + return processing[service_name].arg; + } + + return undefined; +} + +function need_step(service_name, step) { + let old_info = processing[service_name]; + if (!old_info) { + return true + } + + return old_info.step < step +} const protocols = { 'http:': require('http'), @@ -138,10 +172,12 @@ async function run() { console.error(`service ${service.name} has no id!`); process.exit(1); } + if (!service.pub) { continue } - if (onlyput !== "onlyput") { + + if (need_step(service.name, PublishStep.Pack)) { for (const target of targets) { if (service.exclude && service.exclude.includes(target)) { continue @@ -149,31 +185,40 @@ async function run() { if (service.include && !service.include.includes(target)) { continue } - + let config_path = service.config_file[target] || service.config_file.default fs.copyFileSync(`service/${service.name}/${config_path}`, `dist/services/${service.name}/${target}/package.cfg`) - + if (service.assets && service.assets[target]) { for (const asset of service.assets[target]) { fs.copyFileSync(asset.from, `dist/services/${service.name}/${target}/${asset.to}`) } } - + child_process.execSync(`bash -c "./pack-tools -d services/${service.name}/${target}"`, { cwd: 'dist', stdio: 'inherit' }) fs.rmSync(`dist/services/${service.name}/${target}`, {recursive: true, force: true}); } + set_step(service.name, PublishStep.Pack) } - child_process.execSync(`cyfs-client ${action} services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) - - let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) + if (need_step(service.name, PublishStep.Upload)) { + child_process.execSync(`cyfs-client put services/${service.name} -f fid -o ${file_repo_path} --tcp`, { cwd: 'dist', stdio: 'inherit' }) + let fid = fs.readFileSync('dist/fid', {encoding: 'utf-8'}) + set_step(service.name, PublishStep.Upload, fid) + } - // 运行app-tool,添加版本和fid - let app_version = version + "-preview"; - let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; - console.log("will run app tool cmd:", cmd) - child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) + if (need_step(service.name, PublishStep.SetVersion)) { + // 运行app-tool,添加版本和fid + let fid = get_step_arg(service.name, PublishStep.Upload); + let app_version = version + "-preview"; + let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; + console.log("will run app tool cmd:", cmd) + child_process.execSync(cmd, { cwd: 'dist', stdio: 'inherit' }) + set_step(service.name, PublishStep.SetVersion, version) + } + let version = get_step_arg(service.name, PublishStep.SetVersion) + assert(!!version) device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) } @@ -184,6 +229,7 @@ async function run() { } run().then(() => { + try {fs.removeSync(step_file_name)} catch(e) {} process.exit(0) }) From 4eb4f60e7f7ddc9c99bcbbae9bfb0b634601984c Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 15:40:02 +0800 Subject: [PATCH 362/553] Remove unused publish script params --- scripts/pack.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index c5f54d0dc..3729ffd82 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -6,8 +6,8 @@ const { apps, services } = require('./build_config') const path = require('path'); const assert = require('assert'); -const buildnumber = process.argv[6] || "0" -const channel = process.argv[7] || "nightly" +const buildnumber = process.argv[4] || "0" +const channel = process.argv[5] || "nightly" if (!fs.existsSync('Cargo.toml')) { console.error('cannot find Cargo.toml in cwd! check working dir') @@ -209,7 +209,7 @@ async function run() { if (need_step(service.name, PublishStep.SetVersion)) { // 运行app-tool,添加版本和fid - let fid = get_step_arg(service.name, PublishStep.Upload); + let fid = get_step_arg(service.name, PublishStep.Upload) let app_version = version + "-preview"; let cmd = `app-tool app set -v ${app_version} -s ${fid} ${service.id} -o ${repo_path}`; console.log("will run app tool cmd:", cmd) From c37266bdabeaa5833ba8e8304b64aea0b565f435 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 16:55:52 +0800 Subject: [PATCH 363/553] Remove curstep file when publish finish --- scripts/pack.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/pack.js b/scripts/pack.js index 3729ffd82..eb9f8d32a 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -217,9 +217,9 @@ async function run() { set_step(service.name, PublishStep.SetVersion, version) } - let version = get_step_arg(service.name, PublishStep.SetVersion) - assert(!!version) - device_config.push({ "id": service.id, "ver": `${version}`, "status": 1 }) + let service_version = get_step_arg(service.name, PublishStep.SetVersion) + assert(!!service_version) + device_config.push({ "id": service.id, "ver": `${service_version}`, "status": 1 }) } fs.writeFileSync('dist/device-config.cfg', JSON.stringify(device_config)) @@ -229,7 +229,7 @@ async function run() { } run().then(() => { - try {fs.removeSync(step_file_name)} catch(e) {} + fs.rmSync(step_file_name, {force: true, maxRetries: 3}) process.exit(0) }) From 5e41097b0e4a73dd5398569feb16efc7adf00ead Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Mon, 6 Mar 2023 17:14:47 +0800 Subject: [PATCH 364/553] Bump and publish cargo packages --- cargo_pub_rev | 2 +- src/component/cyfs-base/Cargo.toml | 2 +- src/component/cyfs-bdt/Cargo.toml | 4 ++-- src/component/cyfs-core/Cargo.toml | 6 ++---- src/component/cyfs-debug/Cargo.toml | 2 +- src/component/cyfs-lib/Cargo.toml | 2 +- src/component/cyfs-meta-lib/Cargo.toml | 4 ++-- src/component/cyfs-perf/cyfs-perf-base/Cargo.toml | 4 ++-- src/component/cyfs-perf/cyfs-perf-client/Cargo.toml | 6 +++--- src/component/cyfs-task-manager/Cargo.toml | 2 +- src/component/cyfs-util/Cargo.toml | 2 +- 11 files changed, 17 insertions(+), 19 deletions(-) diff --git a/cargo_pub_rev b/cargo_pub_rev index f4faa68c7..e724f4d9f 100644 --- a/cargo_pub_rev +++ b/cargo_pub_rev @@ -1 +1 @@ -95a5c99d \ No newline at end of file +27b2f448 \ No newline at end of file diff --git a/src/component/cyfs-base/Cargo.toml b/src/component/cyfs-base/Cargo.toml index 9ce32803e..9c0dc81fe 100644 --- a/src/component/cyfs-base/Cargo.toml +++ b/src/component/cyfs-base/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-base' -version = '0.6.9' +version = '0.6.10' authors = ['liuzhicong '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-bdt/Cargo.toml b/src/component/cyfs-bdt/Cargo.toml index dcf843d0a..4c2ef1679 100644 --- a/src/component/cyfs-bdt/Cargo.toml +++ b/src/component/cyfs-bdt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-bdt' -version = '0.7.0' +version = '0.7.1' authors = ['liuzhicong '] edition = '2021' license = 'BSD-2-Clause' @@ -40,4 +40,4 @@ serde = { version = '1.0', features = ['derive'] } nix = '0.24' [dev-dependencies] -local-ip-address = '0.5.1' \ No newline at end of file +local-ip-address = '0.5.1' diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index d478a8d58..e075f74dd 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-core' -version = '0.6.5' +version = '0.6.6' authors = ['weiqiushi '] edition = '2021' license = 'BSD-2-Clause' @@ -29,6 +29,4 @@ once_cell = '1.12' hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } -sha2 = { version = '0.8' } -generic-array = { version = '0.12', default-features = false, features = ['serde'] } -semver = "1.0" +semver = '1.0' diff --git a/src/component/cyfs-debug/Cargo.toml b/src/component/cyfs-debug/Cargo.toml index 50e071920..f64231710 100644 --- a/src/component/cyfs-debug/Cargo.toml +++ b/src/component/cyfs-debug/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-debug' -version = '0.6.3' +version = '0.6.4' authors = ['liyaxing '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-lib/Cargo.toml b/src/component/cyfs-lib/Cargo.toml index c64a19e1b..6784d2a15 100644 --- a/src/component/cyfs-lib/Cargo.toml +++ b/src/component/cyfs-lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-lib' -version = '0.8.0' +version = '0.8.1' authors = ['liyaxing '] edition = '2021' license = 'BSD-2-Clause' diff --git a/src/component/cyfs-meta-lib/Cargo.toml b/src/component/cyfs-meta-lib/Cargo.toml index d19e44fbe..32a83ac3e 100644 --- a/src/component/cyfs-meta-lib/Cargo.toml +++ b/src/component/cyfs-meta-lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-meta-lib' -version = '0.6.2' +version = '0.6.3' authors = ['weiqiushi '] edition = '2021' license = 'BSD-2-Clause' @@ -18,4 +18,4 @@ log = '0.4' serde_json = '1.0' rand = '0.7.3' primitive-types = { version = '0.9' } -lru_time_cache = "0.11" +lru_time_cache = '0.11' diff --git a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml index 9ff1ed0a6..a555d2e70 100644 --- a/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-base/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-perf-base' -version = '0.6.2' +version = '0.6.3' authors = ['wangzhi '] edition = '2021' license = 'BSD-2-Clause' @@ -21,7 +21,7 @@ int-enum = '0.4' protobuf = { version = '2', features = ['with-bytes'] } serde = { version = '1.0', features = ['derive'] } serde_json = '1.0' -lazy_static = "1.4" +lazy_static = '1.4' [dev-dependencies] async-std = { version = '1.11', features = ['attributes'] } diff --git a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml index f9c167319..c85719330 100644 --- a/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml +++ b/src/component/cyfs-perf/cyfs-perf-client/Cargo.toml @@ -1,14 +1,14 @@ [package] name = 'cyfs-perf-client' -version = '0.6.1' +version = '0.6.2' authors = ['wangzhi '] edition = '2021' license = 'BSD-2-Clause' description = 'Rust cyfs-perf-client package' [dependencies] -log = { version = '0.4'} +log = { version = '0.4' } serde_json = '1.0' int-enum = '0.4' cyfs-perf-base = { path = '../cyfs-perf-base', version = '0.6' } @@ -22,7 +22,7 @@ async-std = { version = '1.11', features = ['unstable', 'attributes'] } rand = '0.7' sha2 = '0.8' async-trait = '0.1.53' -chrono = "0.4" +chrono = '0.4' [target.'cfg(target_os = "android")'.dependencies] jni = '0.19' diff --git a/src/component/cyfs-task-manager/Cargo.toml b/src/component/cyfs-task-manager/Cargo.toml index c79bcb320..0b9f005d1 100644 --- a/src/component/cyfs-task-manager/Cargo.toml +++ b/src/component/cyfs-task-manager/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-task-manager' -version = '0.6.2' +version = '0.6.3' edition = '2021' license = 'BSD-2-Clause' description = 'Rust cyfs-task-manager package' diff --git a/src/component/cyfs-util/Cargo.toml b/src/component/cyfs-util/Cargo.toml index 313201623..3b2cf72a8 100644 --- a/src/component/cyfs-util/Cargo.toml +++ b/src/component/cyfs-util/Cargo.toml @@ -1,7 +1,7 @@ [package] name = 'cyfs-util' -version = '0.6.5' +version = '0.6.6' authors = ['weiqiushi '] edition = '2021' license = 'BSD-2-Clause' From ac7a6ae228ce007bd0508c027f14f33e0e9dea5d Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 17:29:59 +0800 Subject: [PATCH 365/553] AppManager support install web-packed DecApp --- src/service/app-manager/src/package.rs | 42 ++++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/service/app-manager/src/package.rs b/src/service/app-manager/src/package.rs index d6537a206..4e4028294 100644 --- a/src/service/app-manager/src/package.rs +++ b/src/service/app-manager/src/package.rs @@ -51,8 +51,8 @@ impl AppPackage { let service_path = target_path.join("service"); // 下载service文件,/cyfs/tmp/app/{appid}/service.dl let service_pkg_path = target_path.join("service").with_extension("dl"); - let service_file_num = Self::download_service(dir, owner, client, &service_pkg_path).await?; - if service_file_num > 0 { + let service_exists = Self::download_service(dir, owner, client, &service_pkg_path).await?; + if service_exists { // 解压service zip文件到tmp目录,/cyfs/tmp/app/{appid}/service info!("extract app service {} to {}", service_pkg_path.display(), service_path.display()); Self::extract(&service_pkg_path, &service_path)?; @@ -89,24 +89,34 @@ impl AppPackage { Ok(()) } - pub async fn download_acl(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { - Self::download_files(dir, owner, client, "acl", target_path).await + pub async fn download_acl(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + Self::download_files(dir, owner, client, "acl", target_path).await.map(|size|size > 0) } - pub async fn download_service(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + pub async fn download_service(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { let system_config = get_system_config(); let target = system_config.target.clone(); //拼app service的inner_path,当前为"service/{target}.zip" let service_inner_path = format!("service/{}.zip", &target); - Self::download_files(dir, owner, client, &service_inner_path, target_path).await + Self::download_files(dir, owner, client, &service_inner_path, target_path).await.map(|size|size > 0) } - pub async fn download_web(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { - Self::download_files(dir, owner, client, "web", target_path).await + pub async fn download_web(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + // 先尝试下载web.zip文件 + let web_zip_tmp_path = get_temp_path().join(format!("{}-web.zip", dir)); + if Self::download_files(dir, owner, client, "web.zip", &web_zip_tmp_path).await? == 1 { + // 如果有,这里解压 + info!("extract app web {} to {}", web_zip_tmp_path.display(), target_path.display()); + Self::extract(&web_zip_tmp_path, &target_path)?; + Ok(true) + } else { + Self::download_files(dir, owner, client, "web", target_path).await.map(|size|size > 0) + } + } - pub async fn download_dep(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { - Self::download_files(dir, owner, client, "dependent", target_path).await + pub async fn download_dep(dir: &ObjectId, owner: &ObjectId, client: &NamedCacheClient, target_path: &Path) -> BuckyResult { + Self::download_files(dir, owner, client, "dependent", target_path).await.map(|size|size > 0) } // 下载一个文件夹 @@ -128,22 +138,14 @@ impl AppPackage { pub fn extract(pkg_path: &Path, target_folder: &Path) -> BuckyResult<()> { if target_folder.is_dir() { fs::remove_dir_all(target_folder).map_err(|e| { - error!( - "remove target_folder failed! path={}, err={}", - target_folder.display(), - e - ); + error!("remove target_folder failed! path={}, err={}", target_folder.display(), e); e })?; info!("remove exists target_folder success! dir={}", target_folder.display()); } fs::create_dir_all(target_folder).map_err(|e| { - error!( - "create target_folder failed! path={}, err={}", - target_folder.display(), - e - ); + error!("create target_folder failed! path={}, err={}", target_folder.display(), e); e })?; From 960bea151f528fdfd4614743270a4f45d0c1a82b Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 18:28:02 +0800 Subject: [PATCH 366/553] Update Cargo.lock --- src/Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 0649e040a..aa257e2fa 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1517,7 +1517,7 @@ dependencies = [ [[package]] name = "cyfs-base" -version = "0.6.9" +version = "0.6.10" dependencies = [ "aes 0.7.5", "async-recursion", @@ -1588,7 +1588,7 @@ dependencies = [ [[package]] name = "cyfs-bdt" -version = "0.7.0" +version = "0.7.1" dependencies = [ "async-std", "async-trait", @@ -1802,7 +1802,7 @@ dependencies = [ [[package]] name = "cyfs-core" -version = "0.6.5" +version = "0.6.6" dependencies = [ "async-std", "async-trait", @@ -1829,7 +1829,7 @@ dependencies = [ [[package]] name = "cyfs-debug" -version = "0.6.3" +version = "0.6.4" dependencies = [ "async-h1", "async-std", @@ -1935,7 +1935,7 @@ dependencies = [ [[package]] name = "cyfs-lib" -version = "0.8.0" +version = "0.8.1" dependencies = [ "async-h1", "async-std", @@ -2036,7 +2036,7 @@ dependencies = [ [[package]] name = "cyfs-meta-lib" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -2171,7 +2171,7 @@ dependencies = [ [[package]] name = "cyfs-perf-base" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -2190,7 +2190,7 @@ dependencies = [ [[package]] name = "cyfs-perf-client" -version = "0.6.1" +version = "0.6.2" dependencies = [ "android_logger", "async-std", @@ -2397,7 +2397,7 @@ dependencies = [ [[package]] name = "cyfs-task-manager" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "async-trait", @@ -2426,7 +2426,7 @@ dependencies = [ [[package]] name = "cyfs-util" -version = "0.6.5" +version = "0.6.6" dependencies = [ "async-h1", "async-std", From 35a3debaced04245d7705909126fe1b418db8947 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 19:53:36 +0800 Subject: [PATCH 367/553] Fix service pub script --- scripts/pack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pack.js b/scripts/pack.js index eb9f8d32a..ab45fa21a 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -24,7 +24,7 @@ const step_file_name = "curstep" let processing = {}; if (fs.existsSync(step_file_name)) { - processing = JSON.parse(fs.readFileSync(processing_name)) + processing = JSON.parse(fs.readFileSync(step_file_name)) } function set_step(service_name, step, arg) { From 59f2366a50fefabef6d67c1b881a70523dbecb11 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 7 Mar 2023 20:06:36 +0800 Subject: [PATCH 368/553] Fix continuous script error --- scripts/build.js | 17 ++--------------- scripts/build_config.js | 3 ++- scripts/pack.js | 12 +++++------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index d2947a592..77205e6b5 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,7 +1,6 @@ const fs = require('fs') const build_util = require('./build_util') const build_config = require('./build_config') -const child_process = require('child_process'); // build_util.reflesh_cargo(); @@ -18,25 +17,13 @@ if (!fs.existsSync('Cargo.toml')) { console.error('cannot find Cargo.toml in cwd! check working dir') } -function prepare_bash(base_path, dirs) { - child_process.execSync(`bash -c "rm -rf ${base_path}"`); - child_process.execSync(`bash -c "mkdir ${base_path} -p"`); - for (const dir of dirs) { - child_process.execSync(`bash -c "cp -r -f ${dir} ${base_path}/"`); - } -} - function build(catalogy, need_pack, need_bin) { - try{fs.rmSync(`dist/${catalogy}`, {recursive: true, force: true})}catch(error){} + fs.rmSync(build_config.step_file, {force: true, maxRetries: 3}) + fs.rmSync(`dist/${catalogy}`, {recursive: true, force: true}) if (build_config[catalogy] === undefined) { console.error(`build catalogy ${catalogy} not exists in config`) return } - /* - if (process.argv[2].includes("unknown-linux")) { - // 这里拷贝rust_src下的必要文件到bash的文件夹下 - prepare_bash("~/workspace/ffs", ["3rd", "component", "service", "tests", "tools", "Cargo.toml", "Cargo.lock"]) - }*/ for (const prog of build_config[catalogy]) { for (const target of targets) { diff --git a/scripts/build_config.js b/scripts/build_config.js index 0dbe25639..a2f38c228 100644 --- a/scripts/build_config.js +++ b/scripts/build_config.js @@ -146,5 +146,6 @@ module.exports = { sdk, installer, metas, - misc + misc, + step_file: "curstep" } \ No newline at end of file diff --git a/scripts/pack.js b/scripts/pack.js index ab45fa21a..3e797e7b8 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -2,7 +2,7 @@ const fs = require('fs') const child_process = require('child_process'); const targets = process.argv[2].split(";") const type = process.argv[3].split(";") -const { apps, services } = require('./build_config') +const { apps, services, step_file } = require('./build_config') const path = require('path'); const assert = require('assert'); @@ -20,16 +20,14 @@ const PublishStep = { Finish: 4 } -const step_file_name = "curstep" - let processing = {}; -if (fs.existsSync(step_file_name)) { - processing = JSON.parse(fs.readFileSync(step_file_name)) +if (fs.existsSync(step_file)) { + processing = JSON.parse(fs.readFileSync(step_file)) } function set_step(service_name, step, arg) { processing[service_name] = {step: step, arg: arg}; - fs.writeFileSync(step_file_name, JSON.stringify(processing)) + fs.writeFileSync(step_file, JSON.stringify(processing)) } function get_step_arg(service_name, step) { @@ -229,7 +227,7 @@ async function run() { } run().then(() => { - fs.rmSync(step_file_name, {force: true, maxRetries: 3}) + fs.rmSync(step_file, {force: true, maxRetries: 3}) process.exit(0) }) From 65124c751c8e5d2a049e095f5b5bf6e121a6c3fe Mon Sep 17 00:00:00 2001 From: liqirun Date: Tue, 7 Mar 2023 20:46:35 +0800 Subject: [PATCH 369/553] bdt debuger tool support new SN/NDN api and multi streams test --- src/Cargo.lock | 1 + src/component/cyfs-bdt/src/debug/command.rs | 21 +- src/component/cyfs-bdt/src/debug/stub.rs | 392 +++++++++++++------- src/component/cyfs-bdt/src/stack.rs | 2 +- src/tools/bdt-debuger-deamon/Cargo.toml | 1 + src/tools/bdt-debuger-deamon/src/main.rs | 143 +++++-- 6 files changed, 376 insertions(+), 184 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index aa257e2fa..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -645,6 +645,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-debug", + "cyfs-util", "log 0.4.17", "md5", ] diff --git a/src/component/cyfs-bdt/src/debug/command.rs b/src/component/cyfs-bdt/src/debug/command.rs index 3594fb662..8efecd612 100644 --- a/src/component/cyfs-bdt/src/debug/command.rs +++ b/src/component/cyfs-bdt/src/debug/command.rs @@ -31,12 +31,14 @@ pub fn debug_command_line() -> clap::App<'static, 'static> { .subcommand(SubCommand::with_name("nc") .arg(Arg::with_name("remote").required(true)) .arg(Arg::with_name("port").required(true)) + .arg(Arg::with_name("bench").required(false)) + .arg(Arg::with_name("task").required(false)) ) .subcommand(SubCommand::with_name("get_chunk") .arg(Arg::with_name("remotes").required(true)) .arg(Arg::with_name("timeout").required(true)) .arg(Arg::with_name("chunk_id").required(true)) - .arg(Arg::with_name("local_path").required(true)) + .arg(Arg::with_name("local_path").required(false)) ) .subcommand(SubCommand::with_name("get_file") .arg(Arg::with_name("remotes").required(true)) @@ -100,10 +102,14 @@ impl DebugCommand { let remote = remote_device(stack, subcommand.value_of("remote").unwrap()).await .map_err(|err| format!("load remote desc {} failed for {}\r\n", subcommand.value_of("remote").unwrap(), err))?; let port = u16::from_str(subcommand.value_of("port").unwrap()).unwrap(); + let bench = u32::from_str(subcommand.value_of("bench").unwrap_or("0")).unwrap(); + let task_num = u32::from_str(subcommand.value_of("task").unwrap_or("1")).unwrap(); Ok(Self::Nc(DebugCommandNc { remote, port, - timeout: Duration::from_secs(8) + timeout: Duration::from_secs(8), + bench, + task_num, })) }, "get_chunk" => { @@ -114,12 +120,12 @@ impl DebugCommand { for remote_file in remotes_split { let remote = remote_device(stack, remote_file).await .map_err(|err| format!("load remote desc {} failed for {}\r\n", subcommand.value_of("remote").unwrap(), err))?; - remotes.push(remote.desc().device_id()); + remotes.push(remote.desc().clone()); } let chunk_id_str = String::from_str(subcommand.value_of("chunk_id").unwrap()).unwrap(); let chunk_id = ChunkId::from_str(&chunk_id_str.as_str()).map_err(|err| format!("load chunk_id {} fail: {}\r\n", chunk_id_str, err))?; - let local_path_str = String::from_str(subcommand.value_of("local_path").unwrap()).unwrap(); + let local_path_str = String::from_str(subcommand.value_of("local_path").unwrap_or("default")).unwrap(); let local_path = PathBuf::from_str(&local_path_str.as_str()).unwrap(); let timeout = u32::from_str(subcommand.value_of("timeout").unwrap()).unwrap(); @@ -214,14 +220,17 @@ pub struct DebugCommandPing { pub timeout: Duration } +#[derive(Clone, Debug)] pub struct DebugCommandNc { pub remote: Device, pub port: u16, - pub timeout: Duration + pub timeout: Duration, + pub bench: u32, + pub task_num: u32, } pub struct DebugCommandGetChunk { - pub remotes: Vec, + pub remotes: Vec, pub timeout: u32, pub chunk_id: ChunkId, pub local_path: PathBuf, diff --git a/src/component/cyfs-bdt/src/debug/stub.rs b/src/component/cyfs-bdt/src/debug/stub.rs index 8c7289566..0f4aa5c07 100644 --- a/src/component/cyfs-bdt/src/debug/stub.rs +++ b/src/component/cyfs-bdt/src/debug/stub.rs @@ -21,36 +21,39 @@ use crate::{ datagram::{self, DatagramOptions}, types::*, ndn::*, - utils::* + utils::*, }; use super::command::*; -// use super::super::sn::client::SnStatus; +use super::super::sn::client::SnStatus; struct DebugStubImpl { stack: WeakStack, listener: TcpListener, + chunk_store: MemChunkStore, } #[derive(Clone)] pub struct Config { pub local: String, - pub port: u16 + pub port: u16, + pub chunk_store: MemChunkStore, } #[derive(Clone)] pub struct DebugStub(Arc); impl DebugStub { - pub async fn open(weak_stack: WeakStack) -> BuckyResult { + pub async fn open(weak_stack: WeakStack, chunk_store: MemChunkStore) -> BuckyResult { let stack = Stack::from(&weak_stack); let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::from_str(stack.config().debug.as_ref().unwrap().local.as_str()).unwrap()), stack.config().debug.as_ref().unwrap().port); let listener = TcpListener::bind(addr).await?; Ok(Self(Arc::new(DebugStubImpl { stack: weak_stack, - listener + listener, + chunk_store, }))) - } + } pub fn listen(&self) { const READ_CMD_TIMEOUT: u64 = 30; @@ -138,38 +141,40 @@ impl DebugStub { Ok(()) } - async fn sn_conn_status(&self, _tunnel: TcpStream, _command: DebugCommandSnConnStatus) -> Result<(), String> { - // let mut tunnel = tunnel; + async fn sn_conn_status(&self, tunnel: TcpStream, command: DebugCommandSnConnStatus) -> Result<(), String> { + let mut tunnel = tunnel; - // let stack = Stack::from(&self.0.stack); - // let timeout = { - // if command.timeout_sec == 0 { - // 6 - // } else { - // command.timeout_sec - // } - // }; + let stack = Stack::from(&self.0.stack); + let timeout = { + if command.timeout_sec == 0 { + 6 + } else { + command.timeout_sec + } + }; - // let sleep_ms = 200; - // let mut counter = timeout*(1000/sleep_ms); - // loop { - // let sn_status = stack.sn_client().ping().status(); + let sleep_ms = 200; + let mut counter = timeout*(1000/sleep_ms); + loop { + let sn_status = stack.sn_client().ping().status(); - // if let SnStatus::Online = sn_status { - // let _ = tunnel.write_all("Ok: sn connected\r\n".as_ref()).await; + if let Some(sn_status) = sn_status { + if let SnStatus::Online = sn_status { + let _ = tunnel.write_all("Ok: sn connected\r\n".as_ref()).await; - // return Ok(()) - // } + return Ok(()) + } + } - // counter -= 1; - // if counter == 0 { - // break ; - // } + counter -= 1; + if counter == 0 { + break ; + } - // task::sleep(Duration::from_millis(sleep_ms)).await; - // } + task::sleep(Duration::from_millis(sleep_ms)).await; + } - // let _ = tunnel.write_all("Err: sn connect timeout\r\n".as_ref()).await; + let _ = tunnel.write_all("Err: sn connect timeout\r\n".as_ref()).await; Ok(()) } @@ -283,93 +288,85 @@ impl DebugStub { } async fn nc(&self, tunnel: TcpStream, command: DebugCommandNc) -> Result<(), String> { - let mut tunnel = tunnel; let stack = Stack::from(&self.0.stack); - let _ = tunnel.write_all("connecting stream\r\n".as_ref()).await; - - let question = b"question?"; - let mut conn = stack.stream_manager().connect( - command.port, - question.to_vec(), - BuildTunnelParams { - remote_const: command.remote.desc().clone(), - remote_sn: None, - remote_desc: Some(command.remote.clone()) - }).await.map_err(|err| format!("Err: {}\r\n", err.msg().to_string()))?; - - let _ = tunnel.write_all("Connect success, read answer\r\n".as_ref()).await; - - let mut answer = [0; 128]; - match conn.read(&mut answer).await { - Ok(len) => { - let s = format!("Read answer success, len={} content={:?}\r\n", - len, String::from_utf8(answer[..len].to_vec()).expect("")); - let _ = tunnel.write_all(s.as_bytes()).await; - }, - Err(e) => { - let s = format!("Read answer fail, err={}\r\n", e); - let _ = tunnel.write_all(s.as_bytes()).await; - return Ok(()); - } + let task_num = if command.task_num == 0 { + 1 + } else { + command.task_num + }; + let mut tasks = vec![]; + + for task_id in 0..task_num { + let mut t = tunnel.clone(); + let c = command.clone(); + let s = stack.clone(); + tasks.push(task::spawn(async move { + match nc_task(t.clone(), c, s, task_id).await { + Err(e) => { + let _ = t.write_all(format!("nc_task err={}\r\n", e).as_ref()).await; + }, + Ok(_) => { + } + } + })); } - let _ = conn.write_all(b"hello world.").await; - - let mut buf = [0u8; 128]; - match conn.read(&mut buf).await { - Ok(len) => { - let s = format!("Read data success, len={} content={:?}\r\n", - len, String::from_utf8(buf[..len].to_vec()).expect("")); - let _ = tunnel.write_all(s.as_bytes()).await; - }, - Err(e) => { - let s = format!("Read data fail, err={}\r\n", e); - let _ = tunnel.write_all(s.as_bytes()).await; - return Ok(()); - } + for t in tasks { + let _ = t.await; } - let _ = tunnel.write_all("Ok: stream connected\r\n".as_ref()).await; - - let _ = conn.shutdown(Shutdown::Both); - Ok(()) } async fn get_chunk(&self, tunnel: TcpStream, command: DebugCommandGetChunk) -> Result<(), String> { let mut tunnel = tunnel; - + let chunk_id = command.chunk_id; let remotes = command.remotes; - let timeout = command.timeout; - let local_path = command.local_path; + //let local_path = command.local_path; - let _ = tunnel.write_all("start downloading chunk..\r\n".as_ref()).await; let stack = Stack::from(&self.0.stack); - let context = SampleDownloadContext::id_streams(&stack, "".to_owned(), &remotes).await - .map_err(|e| format!("download err: {}\r\n", e))?; - let (_, reader) = download_chunk(&stack, - chunk_id.clone(), - None, - context).await - .map_err(|e| format!("download err: {}\r\n", e))?; - let _ = future::timeout(Duration::from_secs(timeout as u64), LocalChunkWriter::new(local_path.clone(), None, &chunk_id).write(reader)).await - .map_err(|e| { - format!("download err: {}\r\n", e) - })?; + let chunk_store = self.0.chunk_store.clone(); + let context = SampleDownloadContext::desc_streams("".to_string(), remotes); + let begin = Instant::now(); + match download_chunk(&stack, chunk_id.clone(),None, context).await { + Ok((_, reader)) => { + chunk_store.write_chunk(&chunk_id, reader).await.unwrap(); + match future::timeout(Duration::from_secs(600), get_chunk_wait_finish(stack.clone(), chunk_id.clone())).await { + Err(e) => { + let _ = tunnel.write_all(format!("get_chunk_wait_finish err={}\r\n", e).as_ref()).await; + }, + Ok(r) => { + match r { + Ok(n) => { + let cost_secs = begin.elapsed().as_secs_f64(); + let _ = tunnel.write_all(format!("get success\r\n").as_ref()).await; + if chunk_id.len() != n { + let _ = tunnel.write_all(format!("data wrong, recv_len={} want={}\r\n", n, chunk_id.len()).as_ref()).await; + } else { + let len = n as f64; + let speed = if cost_secs > 0.0 { + len / cost_secs / 1024.0 + } else { + 999999.9 + }; + let _ = tunnel.write_all(format!("cost={:.3}s len={:.1}KB speed={:.1}KB/s\r\n", + cost_secs, len/1024.0, speed).as_ref()).await; + } + }, + Err(e) => { + let _ = tunnel.write_all(format!("get_chunk_wait_finish err={}\r\n", e).as_ref()).await; + } + } + } + } + }, + Err(e) => { + let _ = tunnel.write_all(format!("download_chunk err={}\r\n", e).as_ref()).await; + } + } - let _ = tunnel.write_all("waiting..\r\n".as_ref()).await; - let task_start_time = Instant::now(); - // let ret = watchdog_download_finished(path, timeout).await; - // if ret.is_ok() { - let size = get_filesize(&local_path); - let cost = Instant::now() - task_start_time; - let cost_sec = (cost.as_millis() as f64) / 1000.0; - let speed = (size as f64) * 8.0 / cost_sec / 1000000.0; - let _ = tunnel.write_all(format!("download chunk finish.\r\nsize: {:.1} MB\r\ncost: {:.1} s\r\nspeed: {:.1} Mbps\r\n", - size/1024/1024, cost_sec, speed).as_bytes()).await; - // } Ok(()) } @@ -407,53 +404,47 @@ impl DebugStub { format!("download err: {}\r\n", e) })?; - - // let ret = watchdog_download_finished(task.clone_as_task(), timeout).await; let _ = tunnel.write_all("download file finish.\r\n".as_ref()).await; Ok(()) } - async fn put_chunk(&self, _tunnel: TcpStream, _command: DebugCommandPutChunk) -> Result<(), String> { - // FIXME: impl put chunk debug command with - // let mut tunnel = tunnel; - // let stack = Stack::from(&self.0.stack); - // let local_path = command.local_path; + async fn put_chunk(&self, tunnel: TcpStream, command: DebugCommandPutChunk) -> Result<(), String> { + let mut tunnel = tunnel; + let local_path = command.local_path; - // if local_path.as_path().exists() { - // let mut file = async_std::fs::File::open(local_path.as_path()).await.map_err(|e| { - // format!("open file err: {}\r\n", e) - // })?; - // let mut content = Vec::::new(); - // let _ = file.read_to_end(&mut content).await.map_err(|e| { - // format!("read file err: {}\r\n", e) - // })?; + if local_path.as_path().exists() { + let mut file = async_std::fs::File::open(local_path.as_path()).await.map_err(|e| { + format!("open file err: {}\r\n", e) + })?; + let mut content = Vec::::new(); + let _ = file.read_to_end(&mut content).await.map_err(|e| { + format!("read file err: {}\r\n", e) + })?; - // if content.len() == 0 { - // return Err(format!("file size is zero\r\n")); - // } + if content.len() == 0 { + return Err(format!("file size is zero\r\n")); + } - // match ChunkId::calculate(content.as_slice()).await { - // Ok(chunk_id) => { - // LocalChunkWriter::new(&chunk_id, local_path, None).await - // .map_err(|e| { - // format!("download err: {}\r\n", e) - // })? - // .track_path().await - // .map_err(|e| { - // format!("download err: {}\r\n", e) - // })?; - // let _ = tunnel.write_all(format!("put chunk success. chunk_id: {}\r\n", - // chunk_id.to_string()).as_bytes()).await; - // Ok(()) - // }, - // Err(e) => { - // Err(format!("calculate chunk id err: {}\r\n", e)) - // } - // } - // } else { - // Err(format!("file not exists: {}\r\n", local_path.to_str().unwrap())) - // } - Err("not supported now".to_owned()) + let chunk_store = self.0.chunk_store.clone(); + match ChunkId::calculate(content.as_slice()).await { + Ok(chunk_id) => { + match chunk_store.add(chunk_id.clone(), Arc::new(content)).await { + Ok(_) => { + let _ = tunnel.write_all(format!("put chunk success, chunk_id={}\r\n", chunk_id).as_ref()).await; + }, + Err(e) => { + let _ = tunnel.write_all(format!("put chunk fail, err={}\r\n", e).as_ref()).await; + } + } + Ok(()) + }, + Err(e) => { + Err(format!("calculate chunk id err: {}\r\n", e)) + } + } + } else { + Err(format!("file not exists: {}\r\n", local_path.to_str().unwrap())) + } } async fn put_file(&self, _tunnel: TcpStream, _command: DebugCommandPutFile) -> Result<(), String> { @@ -600,4 +591,121 @@ fn rand_data_gen_buf(len: usize) -> Vec { } buf +} + +fn rand_char(len: usize) -> Vec { + let mut buf = Vec::new(); + buf.resize(len, 0u8); + + for i in 0..len { + buf[i] = 97 + rand::random::() % 26; + } + + buf +} + +async fn get_chunk_wait_finish(stack: Stack, chunk_id: ChunkId) -> BuckyResult { + let mut len = 0; + loop { + let ret = stack.ndn().chunk_manager().store().get(&chunk_id).await; + if let Ok(mut reader) = ret { + let mut content = vec![0u8; 2048]; + + loop { + let n = reader.read(content.as_mut_slice()).await?; + if n == 0 { + break ; + } + len += n; + } + + return Ok(len); + } else { + task::sleep(Duration::from_millis(200)).await; + } + } +} + +async fn nc_task(tunnel: TcpStream, command: DebugCommandNc, stack: Stack, task_id: u32) -> Result<(), String> { + let mut tunnel = tunnel; + let _ = tunnel.write_all(format!("[{}] connecting stream\r\n", task_id).as_ref()).await; + + let question = b"question?"; + let mut conn = stack.stream_manager().connect( + command.port, + question.to_vec(), + BuildTunnelParams { + remote_const: command.remote.desc().clone(), + remote_sn: None, + remote_desc: Some(command.remote.clone()) + }).await.map_err(|err| format!("Err: {}\r\n", err.msg().to_string()))?; + + let _ = tunnel.write_all(format!("[{}] Connect success, read answer\r\n", task_id).as_ref()).await; + + let mut answer = [0; 128]; + match conn.read(&mut answer).await { + Ok(len) => { + let s = format!("[{}] Read answer success, len={} content={:?}\r\n", + task_id, len, String::from_utf8(answer[..len].to_vec()).expect("")); + let _ = tunnel.write_all(s.as_bytes()).await; + }, + Err(e) => { + let s = format!("[{}] Read answer fail, err={}\r\n", task_id, e); + let _ = tunnel.write_all(s.as_bytes()).await; + return Ok(()); + } + } + + let _ = conn.write_all(b"hello world").await; + + let mut buf = [0u8; 128]; + match conn.read(&mut buf).await { + Ok(len) => { + let s = format!("[{}] Read data success, len={} content={:?}\r\n", + task_id, len, String::from_utf8(buf[..len].to_vec()).expect("")); + let _ = tunnel.write_all(s.as_bytes()).await; + }, + Err(e) => { + let s = format!("[{}] Read data fail, err={}\r\n", task_id, e); + let _ = tunnel.write_all(s.as_bytes()).await; + return Ok(()); + } + } + + let _ = tunnel.write_all(format!("[{}] Ok: stream connected\r\n", task_id).as_ref()).await; + + if command.bench > 0 { + let _ = tunnel.write_all(format!("[{}] start bench size={}MB\r\n", task_id, command.bench).as_ref()).await; + + let buf = rand_char(1024); + let mut i: u32 = 0; + let max = command.bench * 1024; + let begin = Instant::now(); + loop { + match conn.write_all(&buf).await { + Ok(_) => { + i += 1; + }, + Err(e) => { + let _ = tunnel.write_all(format!("[{}] write err={}\r\n", task_id, e).as_ref()).await; + break; + } + } + if i >= max { + break; + } + } + let cost = begin.elapsed().as_secs_f64(); + let speed = if cost > 0.0 { + i as f64 / cost + } else { + 999999.9 + }; + let _ = tunnel.write_all(format!("[{}] bench over. cost={:.3}s len={}KB speed={:.1}KB/s\r\n", + task_id, cost, i, speed).as_ref()).await; + } + + let _ = conn.shutdown(Shutdown::Both); + + Ok(()) } \ No newline at end of file diff --git a/src/component/cyfs-bdt/src/stack.rs b/src/component/cyfs-bdt/src/stack.rs index c7f556e85..3a45b6a98 100644 --- a/src/component/cyfs-bdt/src/stack.rs +++ b/src/component/cyfs-bdt/src/stack.rs @@ -330,7 +330,7 @@ impl Stack { } let debug_stub = if stack.config().debug.is_some() { - Some(DebugStub::open(stack.to_weak()).await?) + Some(DebugStub::open(stack.to_weak(), stack.config().debug.as_ref().unwrap().chunk_store.clone()).await?) } else { None }; diff --git a/src/tools/bdt-debuger-deamon/Cargo.toml b/src/tools/bdt-debuger-deamon/Cargo.toml index 2fc55d5d4..94f25a2ef 100644 --- a/src/tools/bdt-debuger-deamon/Cargo.toml +++ b/src/tools/bdt-debuger-deamon/Cargo.toml @@ -12,6 +12,7 @@ description = "Rust bdt-debuger-deamon package" cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-bdt = { path = "../../component/cyfs-bdt" } +cyfs-util = { path = '../../component/cyfs-util', version = '0.6' } async-std = { version = "1.11", features = ["unstable", "attributes"] } clap = "2.34.0" log = "0.4" diff --git a/src/tools/bdt-debuger-deamon/src/main.rs b/src/tools/bdt-debuger-deamon/src/main.rs index a59b4c7cc..8b8ee4aa9 100644 --- a/src/tools/bdt-debuger-deamon/src/main.rs +++ b/src/tools/bdt-debuger-deamon/src/main.rs @@ -1,12 +1,14 @@ -use std::{io::Read, path::Path, str::FromStr, net::Shutdown}; +use std::{io::Read, path::Path, str::FromStr, net::Shutdown, time::Duration}; use async_std::{ task, stream::StreamExt, - io::prelude::{ReadExt}, + io::{prelude::{ReadExt}, WriteExt}, + future, }; use clap::{App, Arg}; use cyfs_base::*; -use cyfs_bdt::{self, Stack, StackOpenParams}; +use cyfs_bdt::*; +use log::*; fn load_dev_by_path(path: &str) -> Option { let desc_path = Path::new(path); @@ -52,8 +54,9 @@ async fn main() { .arg(Arg::with_name("active_pn").long("active_pn").takes_value(true).default_value("").help("active pn")) .arg(Arg::with_name("passive_pn").long("passive_pn").takes_value(true).default_value("").help("passive pn")) .arg(Arg::with_name("device_cache").long("device_cache").takes_value(true).default_value("").help("device cache")) + .arg(Arg::with_name("quiet").long("quiet").takes_value(false).default_value("0").help("quiet mode")) .get_matches(); - + let mut endpoints = vec![]; for ep in matches.values_of("ep").unwrap() { if let Ok(ep) = Endpoint::from_str(ep) { @@ -64,6 +67,8 @@ async fn main() { } } + let quiet = u16::from_str(matches.value_of("quiet").unwrap()).unwrap(); + let sns = load_sn(); let default_desc_path = Path::new("deamon.desc"); @@ -72,12 +77,24 @@ async fn main() { println!("deamon.desc not exists, generate new one"); let private_key = PrivateKey::generate_rsa(1024).unwrap(); let public_key = private_key.public(); - + + let sn_list = match sns.as_ref() { + Some(sns) => { + let mut sn_list = Vec::new(); + for sn in sns.iter() { + println!("sn_list push={}", sn.desc().device_id()); + sn_list.push(sn.desc().device_id()); + } + sn_list + }, + None => vec![], + }; + let device = Device::new( None, UniqueId::default(), endpoints.clone(), - vec![], + sn_list, vec![], public_key, Area::default(), @@ -109,7 +126,7 @@ async fn main() { return; } let mut device = device.unwrap(); - + info!("device={:?}", device); let private_key = { let mut buf = vec![]; @@ -124,23 +141,23 @@ async fn main() { let deamon_id = device.desc().device_id(); let deamon_name = format!("bdt-debuger-deamon-{}", deamon_id); - cyfs_debug::CyfsLoggerBuilder::new_app(deamon_name.as_str()) - .level("info") - .console("info") - .build() - .unwrap() - .start(); - + if quiet == 0 { + cyfs_debug::CyfsLoggerBuilder::new_app(deamon_name.as_str()) + .level("info") + .console("info") + .build() + .unwrap() + .start(); + } cyfs_debug::PanicBuilder::new(deamon_name.as_str(), deamon_name.as_str()) .exit_on_panic(true) .build() .start(); - let device_endpoints = device.mut_connect_info().mut_endpoints(); - device_endpoints.clear(); - for ep in endpoints { - device_endpoints.push(ep); + device_endpoints.clear(); + for ep in endpoints { + device_endpoints.push(ep); } let local = matches.value_of("local").unwrap(); @@ -151,12 +168,16 @@ async fn main() { } let port = port.unwrap(); + let chunk_store = MemChunkStore::new(); let mut params = StackOpenParams::new(deamon_name.as_str()); params.config.debug = Some(cyfs_bdt::debug::Config { local: local.to_string(), - port + port, + chunk_store: chunk_store.clone(), }); + let sns2 = sns.clone(); params.known_sn = sns; + params.config.interface.udp.sn_only = false; if let Some(active_pn) = matches.value_of("active_pn") { params.active_pn = load_dev_vec(active_pn); @@ -164,6 +185,7 @@ async fn main() { if let Some(passive_pn) = matches.value_of("passive_pn") { params.passive_pn = load_dev_vec(passive_pn); } + params.chunk_store = Some(Box::new(chunk_store.clone())); let stack = Stack::open( device, @@ -172,11 +194,40 @@ async fn main() { if let Err(err) = stack { println!("open stack failed for {}", err); - return; + return ; } let stack = stack.unwrap(); + if sns2.is_some() { + stack.reset_sn_list(sns2.unwrap()); + } + + match future::timeout( + Duration::from_secs(5), + stack.sn_client().ping().wait_online(), + ).await { + Ok(res) => { + match res { + Ok(res) => { + match res { + SnStatus::Online => {}, + _ => { + println!("sn offline"); + } + } + }, + Err(e) => { + println!("connect sn err={}", e); + } + } + }, + Err(e) => { + println!("wait_online err={}", e); + } + } + + if let Some(device_cache) = matches.value_of("device_cache") { if device_cache.len() > 0 { let dev = load_dev_by_path(device_cache).unwrap(); @@ -204,24 +255,46 @@ async fn main() { loop { if let Some(stream) = incoming.next().await { if let Ok(mut stream) = stream { - println!("question len={} content={:?}", - stream.question.len(), String::from_utf8(stream.question).expect("")); + task::spawn(async move { + println!("question len={} content={:?}", + stream.question.len(), String::from_utf8(stream.question).expect("")); - let _ = stream.stream.confirm(&vec![]).await; + let answer = b"answer!"; + let _ = stream.stream.confirm(&answer.to_vec()).await; - task::spawn(async move { - let mut buf = vec![]; - match stream.stream.read_to_end(&mut buf).await { - Ok(len) => { - println!("read data success. len={} data={}", - len, String::from_utf8(buf[..len].to_vec()).expect("")); - }, - Err(e) => { - println!("read data err: {}", e); - } + let mut read_buf = [0; 128]; + if let Ok(n) = stream.stream.read(&mut read_buf).await { + println!("read len={} data={}", n, String::from_utf8(read_buf[..n].to_vec()).expect("")); + } + + let write_buf = b"abcdefg"; + if let Ok(n) = stream.stream.write(write_buf).await { + println!("write len={}", n); } - let _ = stream.stream.shutdown(Shutdown::Both); + task::spawn(async move { + let mut buf = vec![0u8; 2048]; + let mut total = 0; + loop { + match stream.stream.read(&mut buf).await { + Ok(n) => { + total += n; + if n == 0 { + break; + } + }, + Err(e) => { + println!("read err={}", e); + break; + } + } + } + task::sleep(std::time::Duration::from_millis(200)).await; + match stream.stream.shutdown(Shutdown::Both) { + Ok(_) => println!("shutdown ok, total={}", total), + Err(e) => println!("shutdown err: {:?}", e), + } + }); }); } } @@ -232,4 +305,4 @@ async fn main() { println!("stack debug deamon running..."); async_std::future::pending::<()>().await; -} \ No newline at end of file +} From 925411b8ce9bbb2c8008fc14905ec2979514c658 Mon Sep 17 00:00:00 2001 From: jing-git Date: Thu, 9 Mar 2023 16:40:32 +0800 Subject: [PATCH 370/553] Support peer to build tunnel without SN in LAN --- .../cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs | 5 +++++ .../cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs b/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs index c1a522ff5..51dc8a24a 100644 --- a/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs +++ b/src/component/cyfs-bdt/src/tunnel/builder/connect_stream/builder.rs @@ -185,6 +185,11 @@ impl ConnectStreamBuilder { } } } + } else if let Some(remote) = known_remote { + info!("{} explore_endpoint_pair with known remote {:?} again", self, remote.connect_info().endpoints()); + let _ = self.explore_endpoint_pair(remote, first_box.clone(), |_| true); + } else { + warn!("{} no sn and unkown remote", self); } } diff --git a/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs b/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs index 4901a8195..0e67a1eb5 100644 --- a/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs +++ b/src/component/cyfs-bdt/src/tunnel/builder/connect_tunnel/builder.rs @@ -144,6 +144,11 @@ impl ConnectTunnelBuilder { } } } + } else if let Some(remote) = known_remote { + info!("{} explore_endpoint_pair with known remote {:?} again", self, remote.connect_info().endpoints()); + let _ = self.explore_endpoint_pair(remote, first_box.clone(), |_| true); + } else { + warn!("{} no sn and unkown remote", self); } } From 37adbd3a1f6df1f8b225986aaf598e56d9fea06c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 371/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/component/cyfs-core/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/component/cyfs-core/Cargo.toml b/src/component/cyfs-core/Cargo.toml index e075f74dd..e32db7eb9 100644 --- a/src/component/cyfs-core/Cargo.toml +++ b/src/component/cyfs-core/Cargo.toml @@ -30,3 +30,4 @@ hex = '0.4' chrono = '0.4' protobuf = { version = '2', features = ['with-bytes'] } semver = '1.0' +sha2 = { version = '0.8' } \ No newline at end of file diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From 951c199db0f3e65be222893c573ef58c08f6c748 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 14:48:12 +0800 Subject: [PATCH 372/553] Adapte to the buckyos --- .../engine/storage_engine_group_state.rs | 44 ++++++++++++++++--- .../cyfs-group/src/storage/group_storage.rs | 9 +++- src/meta/cyfs-meta/src/executor/view.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 029b09e78..cf04e93ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -19,6 +19,8 @@ const ACCESS: Option = None; #[derive(Clone)] pub struct StorageEngineGroupState { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, state_path: Arc, } @@ -183,18 +185,28 @@ impl StorageEngineGroupState { Ok(cache) } - pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + pub fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: GroupStatePath, + group_id: ObjectId, + dec_id: ObjectId, + ) -> Self { Self { state_mgr, state_path: Arc::new(state_path), + group_id, + dec_id, } } pub async fn create_writer(&self) -> BuckyResult { - Ok( - StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) - .await?, + Ok(StorageEngineGroupStateWriter::new( + self.state_mgr.clone(), + self.state_path.clone(), + self.group_id, + self.dec_id, ) + .await?) } pub fn root_cache(&self) -> &ObjectMapRootCacheRef { @@ -218,6 +230,8 @@ impl StorageEngine for StorageEngineGroupState { #[derive(Clone)] pub struct StorageEngineGroupStateWriter { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, op_env: ObjectMapPathOpEnvRef, prepare_op_env: ObjectMapSingleOpEnvRef, @@ -230,6 +244,8 @@ impl StorageEngineGroupStateWriter { async fn new( state_mgr: ObjectMapRootManagerRef, state_path: Arc, + group_id: ObjectId, + dec_id: ObjectId, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; @@ -237,7 +253,11 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(group_id), + Some(dec_id), + ) .await?; None } else { @@ -254,6 +274,8 @@ impl StorageEngineGroupStateWriter { state_mgr, prepare_map_id, write_result: Ok(()), + group_id, + dec_id, }) } @@ -264,7 +286,11 @@ impl StorageEngineGroupStateWriter { ) -> BuckyResult { let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; single_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(self.group_id), + Some(self.dec_id), + ) .await?; single_op_env .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) @@ -463,7 +489,11 @@ impl StorageEngineGroupStateWriter { } add_single_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new( + ObjectMapSimpleContentType::Set, + Some(self.group_id), + Some(self.dec_id), + ) .await?; } else { add_single_op_env diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a762c1b6..78af14c4b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -81,6 +81,8 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), + group_id.clone(), + dec_id.clone(), ), local_device_id, cache: StorageCacheInfo::new(None), @@ -138,7 +140,12 @@ impl GroupStorage { rpath: rpath.to_string(), non_driver, group_chunk_id: group_chunk_id.object_id(), - storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + state_path, + group_id.clone(), + dec_id.clone(), + ), local_device_id, cache, object_map_processor, diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 7d76e9fcc..47e3c8a7d 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -5,7 +5,7 @@ use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; use crate::stat::Stat; use crate::state_storage::{StateRef, StateWeakRef}; -use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base::{BuckyResult, RawConvertTo, ObjectId}; use cyfs_base_meta::*; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; From 6b21be6bc7bfd79cd4707b60a1df944e1e422b77 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:13:38 +0800 Subject: [PATCH 373/553] merge from buckyos --- src/component/cyfs-group/Cargo.toml | 2 +- src/component/cyfs-noc/src/blob/file.rs | 1 - src/component/cyfs-stack/Cargo.toml | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 599e13b51..aaab4ed76 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -28,7 +28,7 @@ async-recursion = '1.0' rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } -cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index 13838c174..9417d1377 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -4,7 +4,6 @@ use cyfs_lib::*; use std::borrow::Cow; use std::path::{Path, PathBuf}; -use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 1e9264e88..76148a72e 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -15,6 +15,7 @@ cyfs-bdt = { path = "../../component/cyfs-bdt" } cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } +cyfs-group = { path = "../../component/cyfs-group" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } From e391823db02ebd201bb3b5a3709ce1d32c8ec043 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:22:30 +0800 Subject: [PATCH 374/553] rename GroupRPathMgr to GroupManager --- .../src/dec/{rpath_mgr.rs => group_manager.rs} | 4 ++-- src/component/cyfs-group/src/dec/mod.rs | 4 ++-- src/component/cyfs-group/src/network/listener.rs | 6 +++--- src/component/cyfs-stack/src/stack/cyfs_stack.rs | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_mgr.rs => group_manager.rs} (99%) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/group_manager.rs similarity index 99% rename from src/component/cyfs-group/src/dec/rpath_mgr.rs rename to src/component/cyfs-group/src/dec/group_manager.rs index 644fc2fcf..56ef5e7d9 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -34,9 +34,9 @@ struct LocalInfo { } #[derive(Clone)] -pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); +pub struct GroupManager(Arc<(LocalInfo, RwLock)>); -impl GroupRPathMgr { +impl GroupManager { pub fn new( signer: RsaCPUObjectSigner, non_driver: Box, diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index a1f964e95..b4e753a27 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod delegate_factory; mod rpath_client; mod rpath_control; -mod rpath_mgr; +mod group_manager; pub use delegate_factory::*; pub use rpath_client::*; pub use rpath_control::*; -pub use rpath_mgr::*; +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6a6d7b549..e66ef8a43 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; -use crate::{GroupRPathMgr, HotstuffPackage}; +use crate::{GroupManager, HotstuffPackage}; pub struct Listener; impl Listener { pub fn spawn( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { async_std::task::spawn(async move { @@ -20,7 +20,7 @@ impl Listener { async fn run( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { loop { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 96eaad5cf..d208f57cf 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,9 +35,9 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; -use cyfs_group::GroupRPathMgr; +use cyfs_bdt::{DeviceCache, SnStatus, StackGuard}; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; +use cyfs_group::GroupManager; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -105,7 +105,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupRPathMgr, + group_manager: GroupManager, } impl CyfsStackImpl { @@ -431,7 +431,7 @@ impl CyfsStackImpl { config.clone(), ); - let group_manager = GroupRPathMgr::new( + let group_manager = GroupManager::new( signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), @@ -1162,7 +1162,7 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupRPathMgr { + pub fn group_mgr(&self) -> &GroupManager { &self.stack.group_manager } From 12a5b3b8fc16939ce394f98ae640ffd34cf870e0 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 21:19:34 +0800 Subject: [PATCH 375/553] integrate GroupState, not finish --- .../cyfs-base/src/objects/object_map/mod.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 4 + .../cyfs-group/src/statepath/design.md | 26 +-- .../src/storage/engine/group_state_path.rs | 178 +++++++++++++++ .../cyfs-group/src/storage/engine/mod.rs | 9 + .../src/storage/engine/storage_engine.rs | 23 ++ .../engine/storage_engine_group_state.rs | 207 ++++++++++++++++++ .../storage_engine_mock.rs} | 53 ++--- .../cyfs-group/src/storage/group_storage.rs | 71 +++++- src/component/cyfs-group/src/storage/mod.rs | 4 +- 12 files changed, 524 insertions(+), 70 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs create mode 100644 src/component/cyfs-group/src/storage/engine/mod.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs rename src/component/cyfs-group/src/storage/{storage_engine.rs => engine/storage_engine_mock.rs} (76%) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index be52c2ea5..3bbc5f131 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -2,6 +2,7 @@ mod access; mod cache; mod check; mod diff; +mod isolate_path_env; mod iterator; mod lock; mod object_map; @@ -13,7 +14,6 @@ mod path_iterator; mod root; mod single_env; mod visitor; -mod isolate_path_env; pub use access::*; pub use cache::*; @@ -25,4 +25,5 @@ pub use path::*; pub use path_env::*; pub use path_iterator::*; pub use root::*; +pub use single_env::*; pub use visitor::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ff4e06380..e89498b83 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -18,7 +18,7 @@ use crate::{ consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** @@ -1461,12 +1461,13 @@ impl HotstuffRunner { continue; } - if let Some(ending) = proposal.effective_ending() { - if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.desc().object_id()); - timeout_proposals.push(proposal); - continue; - } + let ending = proposal.effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), + |ending| bucky_time_to_system_time(ending)); + if now >= ending { + remove_proposals.push(proposal.desc().object_id()); + timeout_proposals.push(proposal); + continue; } match self.delegate.on_execute(&proposal, result_state_id).await { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index aa7babc44..1170176b2 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,6 +14,7 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 56ef5e7d9..95c931720 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,6 +6,7 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, @@ -31,6 +32,7 @@ struct LocalInfo { non_driver: Arc>, datagram: DatagramTunnelGuard, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl GroupManager { signer: RsaCPUObjectSigner, non_driver: Box, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); @@ -50,6 +53,7 @@ impl GroupManager { non_driver: Arc::new(non_driver), datagram: datagram.clone(), bdt_stack, + global_state_mgr, }; let raw = GroupRPathMgrRaw { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index b73a46939..7ec71d4d5 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -7,22 +7,18 @@ | |--list-->Set | |--option-->GroupOption | -|--.dec-state // for dec;各Group的dec状态放这里 -| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 -| |--${dec-id} | .group // 一个dec管理的${r-path}状态 -| | | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | -| -|--.link // 区块链结构,记录状态变更链条 -| |--${group-id} -| |--${dec-id} | .group // .group表示group本身的演变共识 +|--${group-id} +| |--${dec-id} +| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 +| | // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-chunk-->Chunk(Group) +| |--group-blob-->BLOB(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs new file mode 100644 index 000000000..4e67d6e1f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/group_state_path.rs @@ -0,0 +1,178 @@ +use cyfs_base::ObjectId; + +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; + +pub struct GroupStatePath { + rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, +} + +impl GroupStatePath { + pub fn new(rpath: String) -> Self { + Self { + rpath, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.rpath.as_str() + } + + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() + } + + pub fn link(&self) -> &str { + self.link.as_str() + } + + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() + } + + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() + } + + pub fn range(&self) -> &str { + self.range.as_str() + } + + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) + } + + pub fn commit_block(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn commit_proposals(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_PROPOSALS, + ]) + } + + pub fn prepares(&self) -> &str { + self.prepares.as_str() + } + + pub fn prepare_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() + } + + pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.pre_commits.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() + } + + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() + } + + pub fn recycle(&self) -> &str { + self.recycle.as_str() + } + + pub fn adding(&self) -> &str { + self.adding.as_str() + } +} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs new file mode 100644 index 000000000..71d5cc49f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -0,0 +1,9 @@ +mod group_state_path; +mod storage_engine; +mod storage_engine_group_state; +mod storage_engine_mock; + +pub(super) use group_state_path::*; +pub(super) use storage_engine::*; +pub(super) use storage_engine_group_state::*; +pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs new file mode 100644 index 000000000..e48e607bc --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -0,0 +1,23 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Send + Sync + Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs new file mode 100644 index 000000000..3aba73e31 --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -0,0 +1,207 @@ +use std::{collections::HashSet, sync::Arc}; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, +}; + +use crate::StatePath; + +use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; + +const ACCESS: Option = None; + +#[derive(Clone)] +pub struct StorageEngineGroupState { + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, +} + +impl StorageEngineGroupState { + pub async fn load( + dec_group_state: ObjectMapRootManagerRef, + state_path: GroupStatePath, + ) -> BuckyResult { + Ok(Self { + state_mgr: todo!(), + state_path: Arc::new(state_path), + }) + } + + pub async fn create_writer(&self) -> BuckyResult { + Ok( + StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) + .await?, + ) + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineGroupState { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + let op_env = self.state_mgr.create_op_env(ACCESS)?; + let block_id = op_env + .get_by_path(self.state_path.commit_block(height).as_str()) + .await?; + block_id.map_or( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), + |block_id| Ok(block_id), + ) + } +} + +#[derive(Clone)] +pub struct StorageEngineGroupStateWriter { + state_mgr: ObjectMapRootManagerRef, + op_env: ObjectMapPathOpEnvRef, + prepare_op_env: ObjectMapSingleOpEnvRef, + prepare_map_id: Option, + state_path: Arc, +} + +impl StorageEngineGroupStateWriter { + async fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; + let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; + match prepare_map_id.as_ref() { + Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, + None => { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await? + } + }; + + Ok(Self { + op_env, + prepare_op_env, + state_path, + state_mgr, + prepare_map_id, + }) + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; + new_prepare + .create_new(ObjectMapSimpleContentType::Map) + .await?; + new_prepare + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + let new_prepare_block = new_prepare.commit().await?; + + self.prepare_op_env + .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .await + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str()) + .await? + .is_some() + { + assert!(false); + } + + // TODO + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineGroupStateWriter<'a> { + fn drop(&mut self) {} +} diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs similarity index 76% rename from src/component/cyfs-group/src/storage/storage_engine.rs rename to src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b9376618b..6208b0680 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -2,28 +2,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -#[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; - async fn push_proposals( - &mut self, - proposal_ids: &[ObjectId], - timestamp: u64, - ) -> BuckyResult<()>; - - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; -} - -#[async_trait::async_trait] -pub trait StorageEngine { - async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult; - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; -} +use super::{StorageEngine, StorageWriter}; struct StorageEngineMockFinishProposalMgr { flip_timestamp: u64, @@ -58,6 +37,10 @@ impl StorageEngineMock { }, } } + + pub async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) + } } #[async_trait::async_trait] @@ -69,19 +52,15 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult { - Ok(StorageEngineMockWriter { engine: self }) - } - - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { - let is_finished = self - .finish_proposals - .adding - .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) - .is_some(); - Ok(is_finished) - } + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + // let is_finished = self + // .finish_proposals + // .adding + // .get(proposal_id) + // .or(self.finish_proposals.over.get(proposal_id)) + // .is_some(); + // Ok(is_finished) + // } } pub struct StorageEngineMockWriter<'a> { @@ -164,9 +143,9 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: u64, + timestamp: Option, ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + if let Some(timestamp) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 440613f51..bc9fc6009 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, time::SystemTime}; +use std::{ + collections::{HashMap, HashSet}, + time::SystemTime, +}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, @@ -6,10 +9,13 @@ use cyfs_base::{ }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; + +use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; +use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; -use super::{storage_engine::StorageEngineMock, StorageEngine}; +const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; pub enum BlockLinkState { Expired, @@ -23,6 +29,12 @@ pub enum BlockLinkState { InvalidBranch, } +struct FinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -39,6 +51,8 @@ pub struct GroupStorage { prepares: HashMap, pre_commits: HashMap, + finish_proposals: FinishProposalMgr, + storage_engine: StorageEngineMock, } @@ -50,11 +64,19 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + // let group_state = root_state_mgr + // .load_root_state(group_id, Some(group_id.clone()), true) + // .await? + // .expect("create group state failed."); + + // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + Ok(Self { group, group_id: group_id.clone(), @@ -70,6 +92,11 @@ impl GroupStorage { pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), local_device_id, + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, }) } @@ -78,6 +105,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -240,10 +268,17 @@ impl GroupStorage { .iter() .map(|p| p.proposal.clone()) .collect(); - writer.push_proposals( - finish_proposals.as_slice(), - new_header.named_object().desc().create_time(), - ); + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + writer + .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } // update memory @@ -276,6 +311,20 @@ impl GroupStorage { if self.first_block.is_none() { self.first_block = self.header_block.clone(); } + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.finish_proposals.over); + self.finish_proposals.flip_timestamp = timestamp; + } + + for proposal in new_header.proposals() { + let is_new = self.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -551,7 +600,13 @@ impl GroupStorage { // find in storage - self.storage_engine.is_proposal_finished(proposal_id).await + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d95cf7ddd..d4440419e 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,7 @@ mod dec_storage; +mod engine; mod group_storage; -mod storage_engine; pub use dec_storage::*; +use engine::*; pub use group_storage::*; -pub(crate) use storage_engine::*; From bce7f2fb11bc41a9bdbd6b2f1e666dc947db0c01 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 17:28:17 +0800 Subject: [PATCH 376/553] integrate GroupState update --- .../cyfs-group/src/statepath/design.md | 11 +- .../src/statepath/group_statepath.rs | 257 +++++------- .../src/storage/engine/group_state_path.rs | 178 --------- .../cyfs-group/src/storage/engine/mod.rs | 2 - .../src/storage/engine/storage_engine.rs | 17 +- .../engine/storage_engine_group_state.rs | 367 +++++++++++++----- .../src/storage/engine/storage_engine_mock.rs | 30 +- .../cyfs-group/src/storage/group_storage.rs | 30 +- .../cyfs-stack/src/stack/cyfs_stack.rs | 1 + 9 files changed, 439 insertions(+), 454 deletions(-) delete mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 7ec71d4d5..70a61e428 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -25,15 +25,10 @@ | |--last-vote-round-->u64 // 最后一次投票的轮次 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height}) -| | |--block-->GroupConsensusBlock +| |--str(${height})->block | | -| |--prepares // Prepare状态的block -| | |--${block.id} -| | |--block -| |--pre-commits // pre-commit状态的block -| | |--${block.id} -| | |--block +| |--prepares->Set // Prepare状态的block +| |--pre-commits->Set // pre-commit状态的block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index c0daef478..eade0f9e4 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,19 +1,17 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; -pub const STATEPATH_SEPARATOR: &str = "/"; - -pub const STATEPATH_GROUPS: &str = "groups"; - -pub const STATEPATH_DEC_STATE: &str = ".dec-state"; - -pub const STATEPATH_LINK: &str = ".link"; -pub const STATEPATH_GROUP_HASH: &str = "group-hash"; -pub const STATEPATH_USERS: &str = "users"; -pub const STATEPATH_USERS_NONCE: &str = "nonce"; -pub const STATEPATH_RANGE: &str = "range"; -pub const STATEPATH_BLOCK: &str = "block"; - -pub const STATEPATH_RPATHS: &str = ".r-paths"; +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; @@ -23,180 +21,131 @@ lazy_static::lazy_static! { pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } -pub struct StatePath { - group_id: ObjectId, - group_id_str: String, - dec_id: ObjectId, - dec_id_str: String, +pub struct GroupStatePath { rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, } -impl StatePath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { +impl GroupStatePath { + pub fn new(rpath: String) -> Self { Self { - group_id_str: group_id.to_string(), - group_id, - dec_id_str: dec_id.to_string(), - dec_id, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), rpath, } } pub fn join(fields: &[&str]) -> String { - fields.join(STATEPATH_SEPARATOR) - } - - pub fn dec_state() -> String { - STATEPATH_DEC_STATE.to_string() - } - - pub fn dec_state_group(&self) -> String { - Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) - } - - pub fn dec_state_dec(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + fields.join(STATE_PATH_SEPARATOR) } - pub fn dec_state_rpath(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn root(&self) -> &str { + self.rpath.as_str() } - pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - sub_path, - ]) + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() } - pub fn link() -> String { - STATEPATH_LINK.to_string() + pub fn link(&self) -> &str { + self.link.as_str() } - pub fn link_group(&self) -> String { - Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() } - pub fn link_dec(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() } - pub fn link_rpath(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn range(&self) -> &str { + self.range.as_str() } - pub fn link_group_hash(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_GROUP_HASH, - ]) + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) } - pub fn link_users(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - ]) + pub fn prepares(&self) -> &str { + self.prepares.as_str() } - pub fn link_user(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - ]) + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() } - pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - STATEPATH_USERS_NONCE, - ]) + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() } - pub fn link_range(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_RANGE, - ]) - } - - pub fn link_height(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - ]) - } - - pub fn link_block(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - STATEPATH_BLOCK, - ]) - } - - pub fn rpaths(&self) -> String { - STATEPATH_RPATHS.to_string() - } -} - -pub struct GroupUpdateStatePath; - -impl GroupUpdateStatePath { - pub fn latest_version() -> &'static str { - STATEPATH_GROUP_DEC_LATEST_VERSION + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() } - pub fn version_seq(version_seq: u64) -> String { - version_seq.to_string() + pub fn recycle(&self) -> &str { + self.recycle.as_str() } - pub fn group_hash(group_hash: &ObjectId) -> String { - group_hash.to_string() + pub fn adding(&self) -> &str { + self.adding.as_str() } } diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs deleted file mode 100644 index 4e67d6e1f..000000000 --- a/src/component/cyfs-group/src/storage/engine/group_state_path.rs +++ /dev/null @@ -1,178 +0,0 @@ -use cyfs_base::ObjectId; - -pub const STATE_PATH_SEPARATOR: &str = "/"; -pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; -pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; -pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; -pub const GROUP_STATE_PATH_RANGE: &str = "range"; -pub const GROUP_STATE_PATH_BLOCK: &str = "block"; -pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; -pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; -pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; -pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; -pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; -pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; -pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; -pub const GROUP_STATE_PATH_ADDING: &str = "adding"; - -pub struct GroupStatePath { - rpath: String, - dec_state: String, - link: String, - group_blob: String, - last_vote_round: String, - range: String, - prepares: String, - pre_commits: String, - finish_proposals: String, - flip_time: String, - recycle: String, - adding: String, -} - -impl GroupStatePath { - pub fn new(rpath: String) -> Self { - Self { - rpath, - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, - ]), - last_vote_round: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, - ]), - range: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_RANGE, - ]), - prepares: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PREPARES, - ]), - pre_commits: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PRE_COMMITS, - ]), - finish_proposals: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - ]), - flip_time: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_FLIP_TIME, - ]), - recycle: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_RECYCLE, - ]), - adding: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_ADDING, - ]), - } - } - - pub fn join(fields: &[&str]) -> String { - fields.join(STATE_PATH_SEPARATOR) - } - - pub fn root(&self) -> &str { - self.rpath.as_str() - } - - pub fn dec_state(&self) -> &str { - self.dec_state.as_str() - } - - pub fn link(&self) -> &str { - self.link.as_str() - } - - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() - } - - pub fn last_vote_round(&self) -> &str { - self.last_vote_round.as_str() - } - - pub fn range(&self) -> &str { - self.range.as_str() - } - - pub fn commit_height(&self, height: u64) -> String { - Self::join(&[self.link.as_str(), height.to_string().as_str()]) - } - - pub fn commit_block(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn commit_proposals(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_PROPOSALS, - ]) - } - - pub fn prepares(&self) -> &str { - self.prepares.as_str() - } - - pub fn prepare_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.prepares.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn pre_commits(&self) -> &str { - self.pre_commits.as_str() - } - - pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.pre_commits.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn finish_proposals(&self) -> &str { - self.finish_proposals.as_str() - } - - pub fn flip_time(&self) -> &str { - self.flip_time.as_str() - } - - pub fn recycle(&self) -> &str { - self.recycle.as_str() - } - - pub fn adding(&self) -> &str { - self.adding.as_str() - } -} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs index 71d5cc49f..c185cb24c 100644 --- a/src/component/cyfs-group/src/storage/engine/mod.rs +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -1,9 +1,7 @@ -mod group_state_path; mod storage_engine; mod storage_engine_group_state; mod storage_engine_mock; -pub(super) use group_state_path::*; pub(super) use storage_engine::*; pub(super) use storage_engine_group_state::*; pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e48e607bc..e19c46b81 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,19 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { +pub trait StorageWriter: Send + Sync { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()>; async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()>; - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + + async fn commit(mut self) -> BuckyResult<()>; } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 3aba73e31..731725e95 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use crate::StatePath; +use crate::{ + GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, +}; -use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; +use super::{StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -41,7 +44,7 @@ impl StorageEngine for StorageEngineGroupState { async fn find_block_by_height(&self, height: u64) -> BuckyResult { let op_env = self.state_mgr.create_op_env(ACCESS)?; let block_id = op_env - .get_by_path(self.state_path.commit_block(height).as_str()) + .get_by_path(self.state_path.commit_height(height).as_str()) .await?; block_id.map_or( Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), @@ -57,6 +60,7 @@ pub struct StorageEngineGroupStateWriter { prepare_op_env: ObjectMapSingleOpEnvRef, prepare_map_id: Option, state_path: Arc, + write_result: BuckyResult<()>, } impl StorageEngineGroupStateWriter { @@ -65,16 +69,20 @@ impl StorageEngineGroupStateWriter { state_path: Arc, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; - let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; - match prepare_map_id.as_ref() { - Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, - None => { - prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await? - } - }; + let prepare_map_id = + if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { + if err.code() == BuckyErrorCode::NotFound { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + None + } else { + return Err(err); + } + } else { + prepare_op_env.get_current_root().await + }; Ok(Self { op_env, @@ -82,126 +90,299 @@ impl StorageEngineGroupStateWriter { state_path, state_mgr, prepare_map_id, + write_result: Ok(()), }) } -} - -#[async_trait::async_trait] -impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { - let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; - new_prepare - .create_new(ObjectMapSimpleContentType::Map) - .await?; - new_prepare - .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) - .await?; - let new_prepare_block = new_prepare.commit().await?; + async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { self.prepare_op_env - .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .insert(block_id) .await + .map(|is_changed| assert!(is_changed)) } - async fn insert_pre_commit( + async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, is_instead: bool, ) -> BuckyResult<()> { - if !self - .prepare_op_env - .remove_with_key(block_id.to_string().as_str()) - .await? - .is_some() - { - assert!(false); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); - // TODO if is_instead { - self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); - } else { - if !self.engine.pre_commit_blocks.insert(block_id.clone()) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block pre-commit twice", - )); - } + self.op_env + .remove_with_path(self.state_path.pre_commits(), &None) + .await?; } - Ok(()) + self.op_env + .insert_with_path(self.state_path.pre_commits(), block_id) + .await } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if self - .engine - .commit_blocks - .insert(height, block_id.clone()) - .is_some() - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block commit twice", - )); - } + async fn push_commit_inner( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.op_env + .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) + .await?; - self.engine.block_height_range.1 = height; + let range_obj = make_range_obj(min_height, height); + if height == 1 { + self.op_env + .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) + .await?; + } else { + let prev_range = make_range_obj(min_height, height - 1); + let prev_value = self + .op_env + .set_with_key( + self.state_path.link(), + GROUP_STATE_PATH_RANGE, + &range_obj, + &Some(prev_range), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_range); + }; + + // update state from dec-app + if result_state_id == prev_result_state_id { + return Ok(()); + } else { + match result_state_id { + Some(result_state_id) => { + if prev_result_state_id.is_none() { + self.op_env + .insert_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + ) + .await?; + } else { + let prev_value = self + .op_env + .set_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + prev_result_state_id, + false, + ) + .await?; + assert_eq!(&prev_value, prev_result_state_id); + } + } + None => { + self.op_env + .remove_with_path(self.state_path.dec_state(), prev_result_state_id) + .await?; + } + } + } Ok(()) } - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - if !self.engine.prepare_blocks.remove(block_id) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "try remove prepare not exists", - )); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); } Ok(()) } - async fn push_proposals( + async fn push_proposals_inner( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); - self.engine.finish_proposals.flip_timestamp = timestamp; + if proposal_ids.is_empty() { + return Ok(()); } - for proposal_id in proposal_ids { - if !self - .engine - .finish_proposals - .adding - .insert(proposal_id.clone()) - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "dup finish proposal", - )); + let add_single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + + if let Some((timestamp, prev_timestamp)) = timestamp { + let new_over = self + .op_env + .remove_with_path(self.state_path.adding(), &None) + .await?; + + if let Some(new_over) = new_over.as_ref() { + self.op_env + .set_with_path(self.state_path.recycle(), new_over, &None, true) + .await?; } + + let timestamp_obj = make_u64_obj(timestamp); + if prev_timestamp != 0 { + let prev_timestamp_obj = make_u64_obj(prev_timestamp); + let prev_value = self + .op_env + .set_with_path( + self.state_path.flip_time(), + ×tamp_obj, + &Some(prev_timestamp_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_timestamp_obj); + } else { + self.op_env + .insert_with_key( + self.state_path.finish_proposals(), + GROUP_STATE_PATH_FLIP_TIME, + ×tamp_obj, + ) + .await?; + } + + add_single_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + } else { + add_single_op_env + .load_by_path(self.state_path.adding()) + .await?; } + for proposal_id in proposal_ids { + let is_new = add_single_op_env.insert(proposal_id).await?; + assert!(is_new); + } + let adding_set_id = add_single_op_env.commit().await?; + let prev_value = self + .op_env + .set_with_path(self.state_path.adding(), &adding_set_id, &None, true) + .await?; + Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - self.engine.last_vote_round = round; + async fn set_last_vote_round_inner(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert!(round > prev_value); + if round == prev_value { + return Ok(()); + } - Ok(()) + let round_obj = make_u64_obj(round); + + if prev_value == 0 { + self.op_env + .insert_with_path(self.state_path.last_vote_round(), &round_obj) + .await + } else { + let prev_obj = make_u64_obj(prev_value); + let prev_value = self + .op_env + .set_with_path( + self.state_path.last_vote_round(), + &round_obj, + &Some(prev_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_obj); + Ok(()) + } + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result.clone() + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result.clone() + } + + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self + .push_commit_inner( + height, + block_id, + result_state_id, + prev_result_state_id, + min_height, + ) + .await; + self.write_result.clone() + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.remove_prepares_inner(block_ids).await; + self.write_result.clone() + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.push_proposals_inner(proposal_ids, timestamp).await; + self.write_result.clone() + } + + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.set_last_vote_round_inner(round, prev_value).await; + self.write_result.clone() + } + + async fn commit(mut self) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + + let prepare_map_id = self.prepare_op_env.commit().await?; + self.op_env + .set_with_path( + self.state_path.prepares(), + &prepare_map_id, + &self.prepare_map_id, + self.prepare_map_id.is_none(), + ) + .await?; + self.op_env.commit().await.map(|_| ()) } } -impl<'a> Drop for StorageEngineGroupStateWriter<'a> { - fn drop(&mut self) {} +fn make_range_obj(min: u64, max: u64) -> ObjectId { + let mut range_buf = [0u8; 24]; + let (low, high) = range_buf.split_at_mut(12); + low.copy_from_slice(&min.to_le_bytes()); + high.copy_from_slice(&max.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() +} + +fn make_u64_obj(value: u64) -> ObjectId { + let mut range_buf = [0u8; 8]; + range_buf.copy_from_slice(&value.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 6208b0680..b944d3735 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -13,6 +13,7 @@ struct StorageEngineMockFinishProposalMgr { pub struct StorageEngineMock { last_vote_round: u64, + result_state_id: Option, block_height_range: (u64, u64), commit_blocks: HashMap, @@ -30,6 +31,7 @@ impl StorageEngineMock { commit_blocks: HashMap::new(), prepare_blocks: HashSet::new(), pre_commit_blocks: HashSet::new(), + result_state_id: None, finish_proposals: StorageEngineMockFinishProposalMgr { flip_timestamp: 0, over: HashSet::new(), @@ -108,7 +110,18 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + assert!(height > min_height); + assert_eq!(height, self.engine.block_height_range.1 + 1); + assert_eq!(prev_result_state_id, &self.engine.result_state_id); + if self .engine .commit_blocks @@ -123,6 +136,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } self.engine.block_height_range.1 = height; + self.engine.result_state_id = result_state_id.clone(); Ok(()) } @@ -143,12 +157,13 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if let Some(timestamp) = timestamp { + if let Some((timestamp, prev_timestamp)) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + assert_eq!(prev_timestamp, self.engine.finish_proposals.flip_timestamp); self.engine.finish_proposals.flip_timestamp = timestamp; } @@ -170,13 +185,14 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert_eq!(self.engine.last_vote_round, prev_value); self.engine.last_vote_round = round; Ok(()) } -} -impl<'a> Drop for StorageEngineMockWriter<'a> { - fn drop(&mut self) {} + async fn commit(mut self) -> BuckyResult<()> { + Ok(()) + } } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index bc9fc6009..a7284f403 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -13,7 +13,7 @@ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; +use super::{engine::StorageEngineMock, StorageEngine}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -42,15 +42,14 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, + group_chunk_id: ObjectId, dec_state_id: Option, // commited/header state id - group_chunk_id: ObjectId, last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, prepares: HashMap, pre_commits: HashMap, - finish_proposals: FinishProposalMgr, storage_engine: StorageEngineMock, @@ -258,7 +257,15 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit(new_header.height(), new_header.block_id().object_id()) + .push_commit( + new_header.height(), + new_header.block_id().object_id(), + new_header.result_state_id(), + self.header_block + .as_ref() + .map_or(&None, |b| b.result_state_id()), + self.first_block.as_ref().map_or(0, |b| b.height()), + ) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -272,7 +279,10 @@ impl GroupStorage { let timestamp = new_header.named_object().desc().create_time(); if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer - .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.finish_proposals.flip_timestamp)), + ) .await?; } else { writer @@ -281,6 +291,8 @@ impl GroupStorage { } } + writer.commit().await?; + // update memory if self .prepares @@ -293,7 +305,6 @@ impl GroupStorage { match new_header { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); - self.header_block = Some(new_header); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); self.prepares.remove(&new_pre_commit.0); @@ -309,7 +320,7 @@ impl GroupStorage { } if self.first_block.is_none() { - self.first_block = self.header_block.clone(); + self.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); @@ -325,6 +336,7 @@ impl GroupStorage { assert!(is_new); } + self.header_block = Some(new_header); return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -359,7 +371,9 @@ impl GroupStorage { // storage let mut writer = self.storage_engine.create_writer().await?; - writer.set_last_vote_round(round).await?; + writer + .set_last_vote_round(round, self.last_vote_round) + .await?; self.last_vote_round = round; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index d208f57cf..8cf9bcad0 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -435,6 +435,7 @@ impl CyfsStackImpl { signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), + global_state_manager.clone_processor(), )?; let mut stack = Self { From 65e8a18d3bf056a09079f08641c6ad90c20bf257 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 20:15:19 +0800 Subject: [PATCH 377/553] integrate GroupState load --- .../cyfs-group/src/dec/group_manager.rs | 12 +- .../src/storage/engine/storage_engine.rs | 37 ++++ .../engine/storage_engine_group_state.rs | 180 ++++++++++++++-- .../cyfs-group/src/storage/group_storage.rs | 198 ++++++++++-------- 4 files changed, 327 insertions(+), 100 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95c931720..5ecfcdba2 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -372,6 +372,7 @@ impl GroupManager { let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -379,7 +380,15 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; + let store = GroupStorage::load( + group_id, + dec_id, + rpath, + non_driver.clone(), + local_device_id.object_id().clone(), + &root_state_mgr, + ) + .await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -430,6 +439,7 @@ impl GroupManager { init_state, non_driver.clone(), local_device_id.object_id().clone(), + &root_state_mgr, ) .await? } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e19c46b81..735277a3a 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,4 +1,41 @@ +use std::collections::{HashMap, HashSet}; + use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct FinishProposalMgr { + pub flip_timestamp: u64, + pub over: HashSet, + pub adding: HashSet, +} + +pub struct StorageCacheInfo { + pub dec_state_id: Option, // commited/header state id + pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub header_block: Option, + pub first_block: Option, + pub prepares: HashMap, + pub pre_commits: HashMap, + pub finish_proposals: FinishProposalMgr, +} + +impl StorageCacheInfo { + pub fn new(init_state_id: Option) -> Self { + Self { + dec_state_id: init_state_id, + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 731725e95..ee429a78f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,16 +1,18 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, - ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, + ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_RANGE, }; -use super::{StorageEngine, StorageWriter}; +use super::{StorageCacheInfo, StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -21,14 +23,110 @@ pub struct StorageEngineGroupState { } impl StorageEngineGroupState { - pub async fn load( - dec_group_state: ObjectMapRootManagerRef, - state_path: GroupStatePath, - ) -> BuckyResult { - Ok(Self { - state_mgr: todo!(), + pub(crate) async fn load_cache( + state_mgr: &ObjectMapRootManagerRef, + non_driver: &NONDriverHelper, + state_path: &GroupStatePath, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; + + let last_vote_round = op_env + .get_by_path(state_path.last_vote_round()) + .await? + .map(|id| parse_u64_obj(&id)); + + let mut first_header_block_ids: Vec = vec![]; + let commit_range = op_env + .get_by_path(state_path.range()) + .await? + .map(|id| parse_range_obj(&id)); + let commit_block = match commit_range { + Some((first_height, header_height)) => { + let first_block_id = op_env + .get_by_path(state_path.commit_height(first_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(first_block_id); + + if header_height == first_height { + Some((first_block_id, first_block_id)) + } else { + let header_block_id = op_env + .get_by_path(state_path.commit_height(header_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(header_block_id); + Some((first_block_id, header_block_id)) + } + } + None => None, + }; + + let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let pre_commit_block_ids = + load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + + let flip_timestamp = op_env + .get_by_path(state_path.flip_time()) + .await? + .map_or(0, |id| parse_u64_obj(&id)); + + let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; + let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + + let load_block_ids = [ + first_header_block_ids.as_slice(), + prepare_block_ids.as_slice(), + pre_commit_block_ids.as_slice(), + ] + .concat(); + + let load_blocks = futures::future::join_all( + load_block_ids + .iter() + .map(|id| non_driver.get_block(id, None)), + ) + .await; + + let mut cache = StorageCacheInfo::new(dec_state_id); + cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); + cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); + cache.finish_proposals.flip_timestamp = flip_timestamp; + + let prepare_block_pos = match commit_block { + Some((first_block_id, header_block_id)) => { + cache.first_block = Some(load_blocks.get(0).unwrap().clone()?); + if header_block_id == first_block_id { + cache.header_block = cache.first_block.clone(); + 1 + } else { + cache.header_block = Some(load_blocks.get(1).unwrap().clone()?); + 2 + } + } + None => 0, + }; + + let (prepare_blocks, pre_commit_blocks) = + load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); + for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { + cache.prepares.insert(block_id, block.clone()?); + } + for (block, block_id) in pre_commit_blocks.iter().zip(pre_commit_block_ids) { + cache.pre_commits.insert(block_id, block.clone()?); + } + + Ok(cache) + } + + pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + Self { + state_mgr, state_path: Arc::new(state_path), - }) + } } pub async fn create_writer(&self) -> BuckyResult { @@ -132,12 +230,14 @@ impl StorageEngineGroupStateWriter { .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) .await?; - let range_obj = make_range_obj(min_height, height); if height == 1 { + let range_obj = make_range_obj(1, height); self.op_env .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) .await?; } else { + assert!(min_height < height); + let range_obj = make_range_obj(min_height, height); let prev_range = make_range_obj(min_height, height - 1); let prev_value = self .op_env @@ -376,13 +476,63 @@ impl StorageWriter for StorageEngineGroupStateWriter { fn make_range_obj(min: u64, max: u64) -> ObjectId { let mut range_buf = [0u8; 24]; let (low, high) = range_buf.split_at_mut(12); - low.copy_from_slice(&min.to_le_bytes()); - high.copy_from_slice(&max.to_le_bytes()); + low[..8].copy_from_slice(&min.to_le_bytes()); + high[..8].copy_from_slice(&max.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } +fn parse_range_obj(obj: &ObjectId) -> (u64, u64) { + let range_buf = obj.data(); + assert_eq!(range_buf.len(), 24); + let (low_buf, high_buf) = range_buf.split_at(12); + let mut low = [0u8; 8]; + low.copy_from_slice(&low_buf[..8]); + let mut high = [0u8; 8]; + high.copy_from_slice(&high_buf[..8]); + + (u64::from_le_bytes(low), u64::from_le_bytes(high)) +} + fn make_u64_obj(value: u64) -> ObjectId { let mut range_buf = [0u8; 8]; range_buf.copy_from_slice(&value.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } + +fn parse_u64_obj(obj: &ObjectId) -> u64 { + let mut buf = [0u8; 8]; + buf.copy_from_slice(obj.data()); + u64::from_le_bytes(buf) +} + +async fn load_object_ids_with_path( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Set(id) => object_ids.push(id.clone()), + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a7284f403..5ad19ea15 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -11,9 +11,14 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::GlobalStateManagerRawProcessorRef; -use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; +use crate::{ + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, +}; -use super::{engine::StorageEngineMock, StorageEngine}; +use super::{ + engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + StorageEngine, +}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -29,12 +34,6 @@ pub enum BlockLinkState { InvalidBranch, } -struct FinishProposalMgr { - flip_timestamp: u64, - over: HashSet, - adding: HashSet, -} - pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -44,15 +43,9 @@ pub struct GroupStorage { non_driver: NONDriverHelper, group_chunk_id: ObjectId, - dec_state_id: Option, // commited/header state id - last_vote_round: u64, // 参与投票的最后一个轮次 - header_block: Option, - first_block: Option, - prepares: HashMap, - pre_commits: HashMap, - finish_proposals: FinishProposalMgr, + cache: StorageCacheInfo, - storage_engine: StorageEngineMock, + storage_engine: StorageEngineGroupState, } impl GroupStorage { @@ -63,18 +56,18 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); - // let group_state = root_state_mgr - // .load_root_state(group_id, Some(group_id.clone()), true) - // .await? - // .expect("create group state failed."); + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); - // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; Ok(Self { group, @@ -82,20 +75,13 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - dec_state_id: init_state_id, group_chunk_id: group_chunk_id.object_id(), - last_vote_round: 0, - header_block: None, - first_block: None, - prepares: HashMap::new(), - pre_commits: HashMap::new(), - storage_engine: StorageEngineMock::new(), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + GroupStatePath::new(rpath.to_string()), + ), local_device_id, - finish_proposals: FinishProposalMgr { - flip_timestamp: 0, - over: HashSet::new(), - adding: HashSet::new(), - }, + cache: StorageCacheInfo::new(init_state_id), }) } @@ -104,37 +90,62 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - // unimplemented!() - Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); + + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + + let state_path = GroupStatePath::new(rpath.to_string()); + let cache = + StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + group_chunk_id: group_chunk_id.object_id(), + storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + local_device_id, + cache: cache, + }) } pub fn header_block(&self) -> &Option { - &self.header_block + &self.cache.header_block } pub fn header_round(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.round()) + self.cache.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.height()) + self.cache.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - &self.first_block + &self.cache.first_block } pub fn prepares(&self) -> &HashMap { - &self.prepares + &self.cache.prepares } pub fn pre_commits(&self) -> &HashMap { - &self.pre_commits + &self.cache.pre_commits } pub fn group(&self) -> &Group { @@ -146,34 +157,37 @@ impl GroupStorage { } pub fn dec_state_id(&self) -> &Option { - &self.dec_state_id + &self.cache.dec_state_id } pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { let header_height = self.header_height(); let block = match height.cmp(&header_height) { std::cmp::Ordering::Less => { - if height == self.first_block.as_ref().map_or(0, |b| b.height()) { - self.first_block.clone() + if height == self.cache.first_block.as_ref().map_or(0, |b| b.height()) { + self.cache.first_block.clone() } else { // find in storage let block_id = self.storage_engine.find_block_by_height(height).await?; Some(self.non_driver.get_block(&block_id, None).await?) } } - std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Equal => self.cache.header_block.clone(), std::cmp::Ordering::Greater => { if height == header_height + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.height() == height) .or(self + .cache .prepares .iter() .find(|(_, block)| block.height() == height)) .map(|(_, block)| block.clone()) } else if height == header_height + 2 { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.height() == height) .map(|(_, block)| block.clone()) @@ -202,16 +216,17 @@ impl GroupStorage { // prepare update memory if let Some(prev_block_id) = prev_block_id { - if let Some(prev_block) = self.prepares.get(prev_block_id) { + if let Some(prev_block) = self.cache.prepares.get(prev_block_id) { new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); if let Some(prev_prev_block_id) = prev_block.prev_block_id() { - if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + if let Some(prev_prev_block) = self.cache.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); assert_eq!( prev_prev_block.prev_block_id(), - self.header_block + self.cache + .header_block .as_ref() .map(|b| b.block_id().object_id().clone()) .as_ref() @@ -220,7 +235,7 @@ impl GroupStorage { new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.block_id().object_id(); - for (id, block) in self.prepares.iter() { + for (id, block) in self.cache.prepares.iter() { if block.prev_block_id().map(|prev_id| { assert_ne!(prev_id, prev_block_id); prev_id == new_header_id @@ -261,10 +276,11 @@ impl GroupStorage { new_header.height(), new_header.block_id().object_id(), new_header.result_state_id(), - self.header_block + self.cache + .header_block .as_ref() .map_or(&None, |b| b.result_state_id()), - self.first_block.as_ref().map_or(0, |b| b.height()), + self.cache.first_block.as_ref().map_or(0, |b| b.height()), ) .await?; @@ -277,11 +293,11 @@ impl GroupStorage { .collect(); let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer .push_proposals( finish_proposals.as_slice(), - Some((timestamp, self.finish_proposals.flip_timestamp)), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), ) .await?; } else { @@ -295,6 +311,7 @@ impl GroupStorage { // update memory if self + .cache .prepares .insert(block_id.object_id().clone(), block) .is_some() @@ -304,53 +321,60 @@ impl GroupStorage { match new_header { Some(new_header) => { - self.dec_state_id = new_header.result_state_id().clone(); + self.cache.dec_state_id = new_header.result_state_id().clone(); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); - self.prepares.remove(&new_pre_commit.0); + self.cache.prepares.remove(&new_pre_commit.0); let mut removed_blocks = HashMap::from([new_pre_commit]); - std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + std::mem::swap(&mut self.cache.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = removed_blocks.into_values().collect(); for id in remove_prepares.iter() { - removed_blocks.push(self.prepares.remove(id).unwrap()); + removed_blocks.push(self.cache.prepares.remove(id).unwrap()); } - if self.first_block.is_none() { - self.first_block = Some(new_header.clone()); + if self.cache.first_block.is_none() { + self.cache.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MS + { let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.finish_proposals.over); - self.finish_proposals.flip_timestamp = timestamp; + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; } for proposal in new_header.proposals() { - let is_new = self.finish_proposals.adding.insert(proposal.proposal); + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); assert!(is_new); } - self.header_block = Some(new_header); - return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + self.cache.header_block = Some(new_header); + return Ok(Some(( + self.cache.header_block.as_ref().unwrap(), + removed_blocks, + ))); } None => { if let Some(new_pre_commit) = new_pre_commit { assert!(remove_prepares.is_empty()); if self + .cache .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) .is_some() { assert!(false); } - self.prepares + self.cache + .prepares .remove(&new_pre_commit.0) .expect("any block in pre-commit should be from prepare"); } @@ -361,21 +385,21 @@ impl GroupStorage { } pub fn last_vote_round(&self) -> u64 { - self.last_vote_round + self.cache.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - if round <= self.last_vote_round { + if round <= self.cache.last_vote_round { return Ok(()); } // storage let mut writer = self.storage_engine.create_writer().await?; writer - .set_last_vote_round(round, self.last_vote_round) + .set_last_vote_round(round, self.cache.last_vote_round) .await?; - self.last_vote_round = round; + self.cache.last_vote_round = round; Ok(()) } @@ -533,15 +557,16 @@ impl GroupStorage { } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { - if let Some(block) = self.header_block.as_ref() { + if let Some(block) = self.cache.header_block.as_ref() { if block.block_id().object_id() == block_id { return Ok(block.clone()); } } - self.prepares + self.cache + .prepares .get(block_id) - .or(self.pre_commits.get(block_id)) + .or(self.cache.pre_commits.get(block_id)) .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) .map(|block| block.clone()) } @@ -553,20 +578,24 @@ impl GroupStorage { std::cmp::Ordering::Less => { return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Equal => self.cache.header_block.as_ref(), std::cmp::Ordering::Greater => if round == header_round + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .prepares .iter() .find(|(_, block)| block.round() == round)) } else { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .pre_commits .iter() .find(|(_, block)| block.round() == round)) @@ -615,10 +644,11 @@ impl GroupStorage { // find in storage let is_finished = self + .cache .finish_proposals .adding .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) + .or(self.cache.finish_proposals.over.get(proposal_id)) .is_some(); Ok(is_finished) } @@ -647,7 +677,7 @@ impl GroupStorage { &self, round: u64, ) -> (BuckyResult, Vec) { - if self.header_block.is_none() { + if self.cache.header_block.is_none() { return ( Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), vec![], @@ -655,7 +685,7 @@ impl GroupStorage { } let mut blocks = vec![]; - let mut block = self.header_block.clone().unwrap(); + let mut block = self.cache.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; let mut max_height = block.height(); From e491cb4fc3119b872815608e887284e93a2b17cc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 15:20:55 +0800 Subject: [PATCH 378/553] update example for GroupState --- src/tests/group-example/src/main.rs | 479 +++++++++++++++++++--------- 1 file changed, 332 insertions(+), 147 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ffb45ccec..e7948f740 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -3,27 +3,28 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, }; use cyfs_stack::CyfsStack; -use Common::{ - create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, - EXAMPLE_RPATH, -}; +use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; + mod Common { - use std::sync::Arc; + use std::{fmt::format, io::ErrorKind, sync::Arc}; + use async_std::{fs, stream::StreamExt}; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, - UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -35,113 +36,109 @@ mod Common { CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, }; - use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members( + fn create_member( name_prefix: &str, - count: usize, - ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + index: usize, + port: u16, + ) -> ((People, PrivateKey), (Device, PrivateKey)) { log::info!("create members"); - let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); - let mut members = vec![]; + let name = format!("{}-{}", name_prefix, index); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); + endpoint.mut_addr().set_port(port); + endpoint.set_area(EndpointArea::Wan); + + let mut device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + device_private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); - for i in 0..count { - let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_rsa(1024).unwrap(); - let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); - let mut owner = - People::new(None, vec![], private_key.public(), None, Some(name), None).build(); - - let mut endpoint = Endpoint::default(); - endpoint.set_protocol(Protocol::Udp); - endpoint - .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); - endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_area(EndpointArea::Wan); - - let mut device = Device::new( - Some(owner.desc().object_id()), - UniqueId::create_with_random(), - vec![endpoint], - vec![], // TODO: 当前版本是否支持无SN? - vec![], - device_private_key.public(), - Area::default(), - DeviceCategory::PC, - ) - .build(); - - owner - .ood_list_mut() - .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - - let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); - let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); - let device_desc_hash = device.desc().raw_hash_value().unwrap(); - let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); - - let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = - async_std::task::block_on(async move { - let owner_desc_signature = signer - .sign( - owner_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let owner_body_signature = signer - .sign( - owner_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let desc_signature = signer - .sign( - device_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - let body_signature = signer - .sign( - device_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - ( - owner_desc_signature, - owner_body_signature, - desc_signature, - body_signature, + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), ) - }); + .await + .unwrap(); - device.signs_mut().set_desc_sign(desc_signature.clone()); - device.signs_mut().set_body_sign(body_signature); + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); - log::info!( + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", owner.name().unwrap(), owner.desc().object_id(), @@ -152,12 +149,9 @@ mod Common { owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() ); - owner.signs_mut().set_desc_sign(owner_desc_signature); - owner.signs_mut().set_body_sign(owner_body_signature); - members.push(((owner, private_key), (device, device_private_key))); - } - - members + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + ((owner, private_key), (device, device_private_key)) } fn create_group( @@ -194,16 +188,167 @@ mod Common { group } + // (succ, not-found) + fn check_read_buf(file_path: &str, result: &std::io::Result>) -> (bool, bool) { + match result.as_ref() { + Ok(b) => { + if b.len() == 0 { + (false, true) + } else { + (true, false) + } + } + Err(err) if ErrorKind::NotFound == err.kind() => (false, true), + Err(err) => { + log::warn!("read file {} failed: {:?}", file_path, err); + (false, false) + } + } + } + + async fn init_member_from_dir( + save_path: &str, + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + fs::create_dir_all(save_path) + .await + .expect(format!("create dir {} failed", save_path).as_str()); + + let min_port = 30217_u16; + + let mut members = vec![]; + + for i in 0..count { + let index = i + 1; + let people_desc_file_path = format!("{}/people-{}.desc", save_path, index); + let people_sec_file_path = format!("{}/people-{}.sec", save_path, index); + let device_desc_file_path = format!("{}/device-{}.desc", save_path, index); + let device_sec_file_path = format!("{}/device-{}.sec", save_path, index); + + let people_desc_r = fs::read(people_desc_file_path.clone()).await; + let people_sec_r = fs::read(people_sec_file_path.clone()).await; + let device_desc_r = fs::read(device_desc_file_path.clone()).await; + let device_sec_r = fs::read(device_sec_file_path.clone()).await; + + let (is_people_desc_succ, is_people_desc_not_found) = + check_read_buf(people_desc_file_path.as_str(), &people_desc_r); + let (is_people_sec_succ, is_people_sec_not_found) = + check_read_buf(people_sec_file_path.as_str(), &people_sec_r); + let (is_device_desc_succ, is_device_desc_not_found) = + check_read_buf(device_desc_file_path.as_str(), &device_desc_r); + let (is_device_sec_succ, is_device_sec_not_found) = + check_read_buf(device_sec_file_path.as_str(), &device_sec_r); + + if is_people_desc_succ + && is_people_sec_succ + && is_device_desc_succ + && is_device_sec_succ + { + // decode + let people_desc = People::raw_decode(people_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_desc_file_path).as_str()) + .0; + let people_sec = PrivateKey::raw_decode(people_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_sec_file_path).as_str()) + .0; + let device_desc = Device::raw_decode(device_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_desc_file_path).as_str()) + .0; + let device_sec = PrivateKey::raw_decode(device_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_sec_file_path).as_str()) + .0; + members.push(((people_desc, people_sec), (device_desc, device_sec))); + } else if is_people_desc_not_found + && is_people_sec_not_found + && is_device_desc_not_found + && is_device_sec_not_found + { + // create & save + let member = create_member(name_prefix, index, min_port + i as u16); + fs::write( + people_desc_file_path.as_str(), + member.0 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", people_desc_file_path).as_str()); + fs::write(people_sec_file_path.as_str(), member.0 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", people_sec_file_path).as_str()); + fs::write( + device_desc_file_path.as_str(), + member.1 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", device_desc_file_path).as_str()); + fs::write(device_sec_file_path.as_str(), member.1 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", device_sec_file_path).as_str()); + + members.push(member); + } else { + println!("read members failed!"); + std::process::exit(-1); + } + } + + members + } + + pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/admins", "admin", 4).await + } + + pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/members", "member", 9).await + } + + pub async fn init_group( + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + fs::create_dir_all("./test-group") + .await + .expect("create dir ./test-group failed"); + + let read_group_r = fs::read("./test-group/group.desc").await; + match read_group_r { + Ok(buf) => { + if buf.len() > 0 { + return Group::raw_decode(buf.as_slice()) + .expect("decode ./test-group/group.desc failed") + .0; + } + } + Err(err) => { + if ErrorKind::NotFound != err.kind() { + println!("read group failed: {:?}", err); + std::process::exit(-1); + } + } + } + + let group = create_group(admins.get(0).unwrap(), admins, members, oods); + fs::write("./test-group/group.desc", group.to_vec().unwrap()) + .await + .expect("save file ./test-group/group.desc failed"); + group + } + fn init_stack_params( people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); - let mut member_device: Vec = - EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); + let mut admin_device: Vec = admins.iter().map(|m| m.1.clone()).collect(); + let mut member_device: Vec = members.iter().map(|m| m.1.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { @@ -242,7 +387,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { + for (member, device) in admins.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -260,7 +405,7 @@ mod Common { )); } - for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { + for (member, device) in members.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -279,17 +424,17 @@ mod Common { } known_objects.list.push(NONObjectInfo::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_GROUP.to_vec().unwrap(), + group.desc().object_id(), + group.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( - EXAMPLE_GROUP.clone(), + group.clone(), )))), )); - let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( - EXAMPLE_DEC_APP.desc().object_id(), + dec_app.desc().object_id(), dec_app_vec, Some(Arc::new(AnyNamedObject::Core(typeless))), )); @@ -301,8 +446,13 @@ mod Common { people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> CyfsStack { - let params = init_stack_params(people, private_key, device); + let params = + init_stack_params(people, private_key, device, admins, members, group, dec_app); log::info!("cyfs-stack.open"); @@ -316,10 +466,6 @@ mod Common { stack } - - pub fn dummy(people: People, device: Device) { - log::info!("common::dummy"); - } } mod Client { @@ -352,22 +498,21 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + GroupProposalObject, }; use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; use cyfs_stack::CyfsStack; - use crate::Common::EXAMPLE_DEC_APP_ID; - pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { let group_mgr = cyfs_stack.group_mgr(); group_mgr .register( - EXAMPLE_DEC_APP_ID.clone(), + dec_app_id.clone(), Box::new(GroupRPathDelegateFactory { local_name }), ) .await @@ -575,13 +720,14 @@ mod GroupDecService { } } -fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { +fn create_proposal( + delta: u64, + owner: ObjectId, + group_id: ObjectId, + dec_id: ObjectId, +) -> GroupProposal { GroupProposal::create( - GroupRPath::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id().clone(), - EXAMPLE_RPATH.clone(), - ), + GroupRPath::new(group_id, dec_id, EXAMPLE_RPATH.to_string()), "add".to_string(), Some(Vec::from(delta.to_be_bytes())), None, @@ -614,23 +760,57 @@ async fn main_run() { log::info!("will open stacks"); + let admins = init_admins().await; + let members = init_members().await; + let group = init_group( + admins.iter().map(|m| &m.0 .0).collect(), + members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| &m.1 .0).collect(), + ) + .await; + let group_id = group.desc().object_id(); + let dec_app = DecApp::create( + admins.get(0).unwrap().0 .0.desc().object_id(), + EXAMPLE_APP_NAME.as_str(), + ); + let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); + let mut admin_stacks: Vec = vec![]; - for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { - // dummy(admin.clone(), device.clone()); - let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; + for ((admin, _), (device, private_key)) in admins.iter() { + let cyfs_stack = create_stack( + admin.clone(), + private_key, + device.clone(), + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + group.clone(), + dec_app.clone(), + ) + .await; admin_stacks.push(cyfs_stack); } for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); - DecService::run(&stack, admin.name().unwrap().to_string()).await; + let ((admin, _), _) = admins.get(i).unwrap(); + DecService::run( + &stack, + admin.name().unwrap().to_string(), + dec_app_id.clone(), + ) + .await; let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group.desc().object_id(), + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -647,14 +827,19 @@ async fn main_run() { let PROPOSAL_COUNT = 1000usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; - let proposal = create_proposal(i as u64, owner.desc().object_id()); + let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let proposal = create_proposal( + i as u64, + owner.desc().object_id(), + group_id, + dec_app_id.object_id().clone(), + ); let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -676,7 +861,7 @@ async fn main_run() { zone: None, zone_category: DeviceZoneCategory::CurrentDevice, }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + dec: dec_app_id.object_id().clone(), verified: None, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), @@ -700,8 +885,8 @@ async fn main_run() { let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) From fbf52446f280bdc334fe8eea63259df4d3607b67 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 17:36:21 +0800 Subject: [PATCH 379/553] fix: path error --- .../src/statepath/group_statepath.rs | 13 ++++++++-- src/tests/group-example/src/main.rs | 26 +++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eade0f9e4..280fb6948 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -39,51 +39,60 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_GROUP_BLOB, ]), last_vote_round: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), range: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_RANGE, ]), prepares: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PREPARES, ]), pre_commits: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PRE_COMMITS, ]), finish_proposals: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, ]), flip_time: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_FLIP_TIME, ]), recycle: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_RECYCLE, ]), adding: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e7948f740..e29b1be6d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -337,13 +337,13 @@ mod Common { } fn init_stack_params( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -443,13 +443,13 @@ mod Common { } pub async fn create_stack( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> CyfsStack { let params = init_stack_params(people, private_key, device, admins, members, group, dec_app); @@ -778,9 +778,9 @@ async fn main_run() { let mut admin_stacks: Vec = vec![]; for ((admin, _), (device, private_key)) in admins.iter() { let cyfs_stack = create_stack( - admin.clone(), + admin, private_key, - device.clone(), + device, admins .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) @@ -789,8 +789,8 @@ async fn main_run() { .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) .collect(), - group.clone(), - dec_app.clone(), + &group, + &dec_app, ) .await; admin_stacks.push(cyfs_stack); @@ -898,7 +898,7 @@ async fn main_run() { }); if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(200)).await; + async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } From e9196b00dfb5edee445d51bb3879258c8a28e942 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 18:34:11 +0800 Subject: [PATCH 380/553] fix: commit storage --- src/component/cyfs-group/src/storage/group_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 5ad19ea15..30fc08cad 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -398,6 +398,7 @@ impl GroupStorage { writer .set_last_vote_round(round, self.cache.last_vote_round) .await?; + writer.commit().await?; self.cache.last_vote_round = round; From 46babda174c2fa6be9dccd992c918fbf74625476 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 381/553] fix: type of pre-commits --- .../cyfs-group/src/dec/group_manager.rs | 21 ++++++++++--------- .../engine/storage_engine_group_state.rs | 20 +++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5ecfcdba2..7ba376368 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,16 +289,17 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - let rpath = header_block.r_path(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::StateChangeNotify(header_block, qc_block), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = header_block.r_path(); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::StateChangeNotify(header_block, qc_block), + // remote, + // ) + // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index ee429a78f..c6acb7b52 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,7 +5,6 @@ use cyfs_base::{ ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -213,9 +212,11 @@ impl StorageEngineGroupStateWriter { .await?; } - self.op_env - .insert_with_path(self.state_path.pre_commits(), block_id) - .await + let is_changed = self.op_env + .insert(self.state_path.pre_commits(), block_id) + .await?; + assert!(is_changed); + Ok(()) } async fn push_commit_inner( @@ -469,7 +470,16 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.prepare_map_id.is_none(), ) .await?; - self.op_env.commit().await.map(|_| ()) + self.op_env.commit().await.map_or_else( + |err| { + if err.code() == BuckyErrorCode::AlreadyExists { + Ok(()) + } else { + Err(err) + } + }, + |_| Ok(()), + ) } } From f49ce3b5119d7b24cf2f2d3452150498c99af31b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:42:12 +0800 Subject: [PATCH 382/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e29b1be6d..316630f6a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: None, + isolate: Some(device.desc().object_id()), sync_service: false, shared_stack: false, }, From ff0e2badf59f529416001eb5e23639b53f24c45c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:49:08 +0800 Subject: [PATCH 383/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 316630f6a..d69fcae2d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: Some(device.desc().object_id()), + isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: false, }, From a36f7a3bf9e99e66037b0decb162858afeb22e0a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 21 Feb 2023 19:52:57 +0800 Subject: [PATCH 384/553] fix: the round for the first block when restart --- src/component/cyfs-core/src/coreobj.rs | 1 + .../src/group/group_quorum_certificate.rs | 144 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 2 + .../src/consensus/hotstuff/hotstuff.rs | 60 +++++++- .../cyfs-group/src/dec/group_manager.rs | 34 +++-- .../cyfs-group/src/network/non_driver.rs | 30 +++- .../cyfs-group/src/statepath/design.md | 1 + .../src/statepath/group_statepath.rs | 16 +- .../src/storage/engine/storage_engine.rs | 5 +- .../engine/storage_engine_group_state.rs | 130 ++++++++++++---- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 136 ++++++++++++----- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- src/tests/group-example/src/main.rs | 24 +-- 14 files changed, 493 insertions(+), 100 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_quorum_certificate.rs diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 724f0debb..30bf0e013 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupRPathStatus = 703, GroupAction = 704, + GroupQuorumCertificate = 705, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs new file mode 100644 index 000000000..7c3ad77fc --- /dev/null +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -0,0 +1,144 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, DescContent, EmptyBodyContent, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBuilder, NamedObjectId, RawDecode, RawEncode, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_RAW, +}; + +use crate::{CoreObjectType, HotstuffBlockQC, HotstuffTimeout}; + +#[derive(Clone)] +pub enum GroupQuorumCertificateDescContent { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), +} + +impl DescContent for GroupQuorumCertificateDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupQuorumCertificate as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupQuorumCertificateDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +pub type GroupQuorumCertificateType = + NamedObjType; +pub type GroupQuorumCertificateBuilder = + NamedObjectBuilder; + +pub type GroupQuorumCertificateId = NamedObjectId; +pub type GroupQuorumCertificate = NamedObjectBase; + +pub trait GroupQuorumCertificateObject { + fn quorum_round(&self) -> u64; +} + +impl GroupQuorumCertificateObject for GroupQuorumCertificate { + fn quorum_round(&self) -> u64 { + match self.desc().content() { + GroupQuorumCertificateDescContent::QC(qc) => qc.round, + GroupQuorumCertificateDescContent::TC(tc) => tc.round, + } + } +} + +impl RawEncode for GroupQuorumCertificateDescContent { + fn raw_measure( + &self, + purpose: &Option, + ) -> cyfs_base::BuckyResult { + let len = match self { + GroupQuorumCertificateDescContent::QC(qc) => qc.raw_measure(purpose)?, + GroupQuorumCertificateDescContent::TC(tc) => tc.raw_measure(purpose)?, + }; + + Ok(len + 1) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> cyfs_base::BuckyResult<&'a mut [u8]> { + match self { + GroupQuorumCertificateDescContent::QC(qc) => { + buf[0] = 0; + let buf = &mut buf[1..]; + qc.raw_encode(buf, purpose) + } + GroupQuorumCertificateDescContent::TC(tc) => { + buf[0] = 1; + let buf = &mut buf[1..]; + tc.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for GroupQuorumCertificateDescContent { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let obj_type = buf[0]; + let buf = &buf[1..]; + match obj_type { + 0 => { + let (qc, remain) = HotstuffBlockQC::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::QC(qc), remain)) + } + 1 => { + let (qc, remain) = HotstuffTimeout::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::TC(qc), remain)) + } + _ => Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown qc")), + } + } +} + +impl From for GroupQuorumCertificate { + fn from(qc: HotstuffBlockQC) -> Self { + let desc = GroupQuorumCertificateDescContent::QC(qc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl From for GroupQuorumCertificate { + fn from(tc: HotstuffTimeout) -> Self { + let desc = GroupQuorumCertificateDescContent::TC(tc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::QC(qc) => Ok(qc), + GroupQuorumCertificateDescContent::TC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is tc, expect qc")) + } + } + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::TC(tc) => Ok(tc), + GroupQuorumCertificateDescContent::QC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is qc, expect tc")) + } + } + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4c315c090..c153ab1ba 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,6 +1,7 @@ mod group_consensus_block; mod group_proposal; mod group_proposal_decide_param; +mod group_quorum_certificate; mod group_rpath; mod group_rpath_status; mod group_update_group_proposal_param; @@ -8,6 +9,7 @@ mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; pub use group_proposal_decide_param::*; +pub use group_quorum_certificate::*; pub use group_rpath::*; pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e89498b83..7868a7f90 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,7 +9,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; @@ -238,11 +238,36 @@ impl HotstuffRunner { rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); + let last_qc = store.last_qc(); + let (tc, qc) = last_qc + .as_ref() + .map_or((None, None), |qc| { + match qc.desc().content() { + cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), + cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), + } + }); - let round = store - .last_vote_round() - .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let last_vote_round = store + .last_vote_round(); + let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); + let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); + + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" + , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + + let max_round_qc_round = max_round_block + .as_ref() + .map_or(0, |block| + block.qc().as_ref().map_or(0, |qc| qc.round) + ); + let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); + let high_qc = if max_round_qc_round >= last_qc_round { + max_round_block.map_or(None, |b| b.qc().clone()) + } else { + qc + }; let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); @@ -277,7 +302,7 @@ impl HotstuffRunner { rpath, proposal_consumer, rx_proposal_waiter: None, - tc: None, + tc, state_pusher, tx_block_gen, rx_block_gen, @@ -627,6 +652,16 @@ impl HotstuffRunner { * 验证过的块执行这个函数 */ + if let Err(err) = self.non_driver.put_block(block).await { + if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + log::warn!( + "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", + self, block.block_id(), block.height(), block.round() + ); + return Err(err); + } + } + log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", self, block.block_id(), block.height(), block.round() @@ -1072,6 +1107,10 @@ impl HotstuffRunner { let qc_round = qc.round; let qc_prev_block_id = qc.prev_block_id; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); + + self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.process_qc(&Some(qc)).await; let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { @@ -1211,10 +1250,14 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", @@ -1324,6 +1367,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1814,6 +1861,7 @@ impl HotstuffRunner { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id + && max_round_block.round() == self.round && latest_group.is_ok() && last_group.is_ok() && last_group diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7ba376368..70fb10ba6 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -302,22 +302,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.r_path(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); @@ -397,6 +398,7 @@ impl GroupManager { return Err(e); } if let BuckyErrorCode::NotFound = e.code() { + log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); None } else { return Err(e); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4212a0355..979451b79 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,7 +7,9 @@ use cyfs_base::{ TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, +}; use cyfs_lib::NONObjectInfo; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -106,6 +108,32 @@ impl NONDriverHelper { Ok(()) } + pub async fn get_qc( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupQuorumCertificate::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn put_qc(&self, qc: &GroupQuorumCertificate) -> BuckyResult<()> { + let buf = qc.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let qc = NONObjectInfo { + object_id: qc.desc().object_id(), + object_raw: qc.to_vec()?, + object: Some(block_any), + }; + self.put_object(qc).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 70a61e428..cb964e066 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -23,6 +23,7 @@ | | |--${user-id} | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 280fb6948..0e6a887b0 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -5,6 +5,7 @@ pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -23,10 +24,12 @@ lazy_static::lazy_static! { pub struct GroupStatePath { rpath: String, + root: String, dec_state: String, link: String, group_blob: String, last_vote_round: String, + last_qc: String, range: String, prepares: String, pre_commits: String, @@ -39,6 +42,7 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { + root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ @@ -53,6 +57,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), + last_qc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_QC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -107,7 +117,7 @@ impl GroupStatePath { } pub fn root(&self) -> &str { - self.rpath.as_str() + self.root.as_str() } pub fn dec_state(&self) -> &str { @@ -126,6 +136,10 @@ impl GroupStatePath { self.last_vote_round.as_str() } + pub fn last_qc(&self) -> &str { + self.last_qc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index 735277a3a..aebf6fb96 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,6 +12,7 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub last_qc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -33,6 +34,7 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, + last_qc: None, } } } @@ -58,6 +60,7 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index c6acb7b52..2b61dbc47 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, }; use crate::{ @@ -27,26 +27,35 @@ impl StorageEngineGroupState { non_driver: &NONDriverHelper, state_path: &GroupStatePath, ) -> BuckyResult { - let op_env = state_mgr.create_op_env(ACCESS)?; - - let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; - - let last_vote_round = op_env - .get_by_path(state_path.last_vote_round()) - .await? - .map(|id| parse_u64_obj(&id)); + let op_env = state_mgr.create_op_env(ACCESS).map_err(|err| { + log::warn!("create_op_env failed {:?}", err); + err + })?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await; + let dec_state_id = map_not_found_option_to_option(dec_state_id)?; + + let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; + let last_vote_round = + map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; + let last_qc = map_not_found_option_to_option(last_qc)?; + let last_qc = match last_qc.as_ref() { + Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + None => None, + }; let mut first_header_block_ids: Vec = vec![]; - let commit_range = op_env - .get_by_path(state_path.range()) - .await? - .map(|id| parse_range_obj(&id)); + let commit_range = op_env.get_by_path(state_path.range()).await; + let commit_range = + map_not_found_option_to_option(commit_range)?.map(|id| parse_range_obj(&id)); let commit_block = match commit_range { Some((first_height, header_height)) => { let first_block_id = op_env .get_by_path(state_path.commit_height(first_height).as_str()) - .await? - .expect("first block is lost"); + .await; + let first_block_id = + map_not_found_option_to_option(first_block_id)?.expect("first block is lost"); first_header_block_ids.push(first_block_id); if header_height == first_height { @@ -54,7 +63,8 @@ impl StorageEngineGroupState { } else { let header_block_id = op_env .get_by_path(state_path.commit_height(header_height).as_str()) - .await? + .await; + let header_block_id = map_not_found_option_to_option(header_block_id)? .expect("first block is lost"); first_header_block_ids.push(header_block_id); Some((first_block_id, header_block_id)) @@ -64,13 +74,27 @@ impl StorageEngineGroupState { }; let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + if prepare_block_ids.len() == 0 && commit_range.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "not found in storage", + )); + } + let pre_commit_block_ids = load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; - let flip_timestamp = op_env - .get_by_path(state_path.flip_time()) - .await? - .map_or(0, |id| parse_u64_obj(&id)); + let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; + let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { + let n = parse_u64_obj(&id); + // log::debug!( + // "load flip timestamp {}/{} -> {}", + // id, + // id.to_hex().unwrap(), + // n + // ); + n + }); let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; @@ -82,15 +106,18 @@ impl StorageEngineGroupState { ] .concat(); - let load_blocks = futures::future::join_all( - load_block_ids - .iter() - .map(|id| non_driver.get_block(id, None)), - ) + let load_blocks = futures::future::join_all(load_block_ids.iter().map(|id| async { + let id = id.clone(); + non_driver.get_block(&id, None).await.map_err(|err| { + log::warn!("get block {} failed {:?}", id, err); + err + }) + })) .await; let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.last_qc = last_qc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -212,7 +239,8 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self.op_env + let is_changed = self + .op_env .insert(self.state_path.pre_commits(), block_id) .await?; assert!(is_changed); @@ -326,6 +354,15 @@ impl StorageEngineGroupStateWriter { let timestamp_obj = make_u64_obj(timestamp); if prev_timestamp != 0 { let prev_timestamp_obj = make_u64_obj(prev_timestamp); + // log::debug!( + // "will update flip-time from {} -> {}/{} to {} -> {}/{}", + // prev_timestamp, + // prev_timestamp_obj, + // prev_timestamp_obj.to_hex().unwrap(), + // timestamp, + // timestamp_obj, + // timestamp_obj.to_hex().unwrap(), + // ); let prev_value = self .op_env .set_with_path( @@ -337,6 +374,7 @@ impl StorageEngineGroupStateWriter { .await?; assert_eq!(prev_value.unwrap(), prev_timestamp_obj); } else { + // log::debug!("will update flip-time from None to {}", timestamp); self.op_env .insert_with_key( self.state_path.finish_proposals(), @@ -395,6 +433,13 @@ impl StorageEngineGroupStateWriter { Ok(()) } } + + async fn save_last_qc_inner(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_qc(), qc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -458,6 +503,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_qc_inner(qc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; @@ -522,6 +573,7 @@ async fn load_object_ids_with_path( let content = match op_env.list(full_path).await { Ok(content) => content, Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); if err.code() == BuckyErrorCode::NotFound { return Ok(vec![]); } else { @@ -546,3 +598,29 @@ async fn load_object_ids_with_path( Ok(object_ids) } + +fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { + match r { + Ok(t) => Ok(Some(t)), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} + +fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult> { + match r { + Ok(t) => Ok(t), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b944d3735..79491b186 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -192,6 +192,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 30fc08cad..3f9fc9910 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -8,7 +8,10 @@ use cyfs_base::{ ObjectDesc, ObjectId, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupQuorumCertificateObject, HotstuffTimeout, +}; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ @@ -20,7 +23,7 @@ use super::{ StorageEngine, }; -const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; +const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() as u64; pub enum BlockLinkState { Expired, @@ -96,16 +99,32 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver.get_group(group_id, None, None).await?; + let group = non_driver + .get_group(group_id, None, None) + .await + .map_err(|err| { + log::warn!("get group {} from noc failed {:?}", group_id, err); + err + })?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) - .await? + .await + .map_err(|err| { + log::warn!("load root state for group {} failed {:?}", group_id, err); + err + })? .expect("create group state failed."); - let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state + .get_dec_root_manager(dec_id, true) + .await + .map_err(|err| { + log::warn!("get root state manager for dec {} failed {:?}", dec_id, err); + err + })?; let state_path = GroupStatePath::new(rpath.to_string()); let cache = @@ -120,7 +139,7 @@ impl GroupStorage { group_chunk_id: group_chunk_id.object_id(), storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, - cache: cache, + cache, }) } @@ -286,24 +305,33 @@ impl GroupStorage { writer.remove_prepares(remove_prepares.as_slice()).await?; - let finish_proposals: Vec = new_header - .proposals() - .iter() - .map(|p| p.proposal.clone()) - .collect(); - - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { - writer - .push_proposals( - finish_proposals.as_slice(), - Some((timestamp, self.cache.finish_proposals.flip_timestamp)), - ) - .await?; - } else { - writer - .push_proposals(finish_proposals.as_slice(), None) - .await?; + if new_header.proposals().len() > 0 { + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + + let timestamp = new_header.named_object().desc().create_time(); + // log::debug!( + // "push proposals storage flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + writer + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), + ) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } } @@ -340,19 +368,28 @@ impl GroupStorage { self.cache.first_block = Some(new_header.clone()); } - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp - > PROPOSAL_MAX_TIMEOUT_AS_MS - { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); - self.cache.finish_proposals.flip_timestamp = timestamp; - } + if new_header.proposals().len() > 0 { + let timestamp = new_header.named_object().desc().create_time(); + + // log::debug!( + // "push proposals flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; + } - for proposal in new_header.proposals() { - let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); - assert!(is_new); + for proposal in new_header.proposals() { + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } } self.cache.header_block = Some(new_header); @@ -405,6 +442,33 @@ impl GroupStorage { Ok(()) } + pub fn last_qc(&self) -> &Option { + &self.cache.last_qc + } + + pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { + let quorum_round = qc.quorum_round(); + if quorum_round < self.cache.last_vote_round + || quorum_round + <= self + .cache + .last_qc + .as_ref() + .map_or(0, |qc| qc.quorum_round()) + { + return Ok(()); + } + + self.non_driver.put_qc(&qc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_qc(&qc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_qc = Some(qc); + Ok(()) + } + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { log::debug!( "[group storage] {} block_linked {} step1", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9414cda7c..fcb0dd6da 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, @@ -55,6 +55,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { } async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let access = AccessString::full(); + log::debug!("put object {} with access {}", obj.object_id, access); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { @@ -76,7 +78,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { flags: 0, }, object: obj, - access: None, // TODO access + access: Some(AccessString::full()), // TODO access }) .await .map(|_| ()) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d69fcae2d..b5b6f4ce4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,7 +1,8 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ - AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; @@ -23,8 +24,8 @@ mod Common { AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, - TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, - SIGNATURE_SOURCE_REFINDEX_SELF, + TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -210,13 +211,12 @@ mod Common { save_path: &str, name_prefix: &str, count: usize, + min_port: u16, ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { fs::create_dir_all(save_path) .await .expect(format!("create dir {} failed", save_path).as_str()); - let min_port = 30217_u16; - let mut members = vec![]; for i in 0..count { @@ -296,11 +296,13 @@ mod Common { } pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/admins", "admin", 4).await + let min_port = 30217_u16; + init_member_from_dir("./test-group/admins", "admin", 4, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/members", "member", 9).await + let min_port = 31217_u16; + init_member_from_dir("./test-group/members", "member", 9, min_port).await } pub async fn init_group( @@ -369,7 +371,7 @@ mod Common { }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { - bdt_listeners: vec![], + bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], tcp_listeners: vec![], ws_listener: None, }, @@ -868,7 +870,7 @@ async fn main_run() { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: Some(AccessString::full().value()), }; noc.put_object(&req).await; proposals.push(proposal); @@ -878,8 +880,8 @@ async fn main_run() { log::info!("proposals prepared."); - for i in 0..(PROPOSAL_COUNT - 1) { - let proposal = proposals.get(i).unwrap().clone(); + for i in 1..PROPOSAL_COUNT { + let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let control = stack From 3e397a92f60a90963f930df29ef3af6c2710a648 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 16:04:16 +0800 Subject: [PATCH 385/553] fix: first block with tc --- .../src/consensus/hotstuff/hotstuff.rs | 75 ++++++++++--------- .../src/statepath/group_statepath.rs | 12 +++ .../src/storage/engine/storage_engine.rs | 9 ++- .../engine/storage_engine_group_state.rs | 35 ++++++++- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 41 +++++++--- src/tests/group-example/src/main.rs | 2 + 7 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7868a7f90..a2a5e8f70 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -239,36 +239,30 @@ impl HotstuffRunner { ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); - let (tc, qc) = last_qc - .as_ref() - .map_or((None, None), |qc| { - match qc.desc().content() { - cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), - cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), - } - }); + let last_tc = store.last_tc(); let last_vote_round = store .last_vote_round(); - let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); - let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); + let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); + let quorum_round = block_quorum_round.max(timeout_quorum_round); + let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" - , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" + , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); - let max_round_qc_round = max_round_block - .as_ref() - .map_or(0, |block| - block.qc().as_ref().map_or(0, |qc| qc.round) - ); - let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); - let high_qc = if max_round_qc_round >= last_qc_round { + let high_qc = if max_round_qc_round >= block_quorum_round { max_round_block.map_or(None, |b| b.qc().clone()) } else { - qc + last_qc.clone() }; + let tc = last_tc.clone(); + let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; @@ -954,18 +948,22 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && qc_round - >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; if !is_valid_round { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {:?}", self, block.block_id(), block.round(), qc_round, - block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + block.tc().as_ref().map_or((0, 0), |tc| { + let qc_round = tc.votes.iter().map(|v| v.high_qc_round).max().unwrap(); + (tc.round, qc_round) + })); return None; } @@ -1109,7 +1107,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); - self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.store.save_qc(&qc).await?; self.process_qc(&Some(qc)).await; @@ -1125,7 +1123,7 @@ impl HotstuffRunner { })?; if self.local_device_id == new_leader { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } Ok(()) } @@ -1251,12 +1249,12 @@ impl HotstuffRunner { max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( @@ -1367,9 +1365,9 @@ impl HotstuffRunner { err })?; - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1535,7 +1533,7 @@ impl HotstuffRunner { self.remove_pending_proposals(remove_proposals).await; if self - .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .try_wait_proposals(executed_proposals.len(), &prev_block) .await { log::debug!( @@ -1739,12 +1737,12 @@ impl HotstuffRunner { async fn try_wait_proposals( &mut self, - executed_proposals: &[(GroupProposal, ExecuteResult)], + proposal_count: usize, pre_block: &Option, ) -> bool { // empty block, qc only, it's unuseful when no block to qc let mut will_wait_proposals = false; - if executed_proposals.len() == 0 { + if proposal_count == 0 { match pre_block.as_ref() { None => { log::warn!( @@ -1814,14 +1812,17 @@ impl HotstuffRunner { assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); - let tc = self.tc.as_ref().map_or(None, |tc| { + self.generate_block(self.with_tc()).await + } + + fn with_tc(&self) -> Option { + self.tc.as_ref().map_or(None, |tc| { if tc.round + 1 == self.round { Some(tc.clone()) } else { None } - }); - self.generate_block(tc).await + }) } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { @@ -1876,7 +1877,7 @@ impl HotstuffRunner { ); } _ => { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } } } diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0e6a887b0..72f48e601 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -6,6 +6,7 @@ pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; +pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -30,6 +31,7 @@ pub struct GroupStatePath { group_blob: String, last_vote_round: String, last_qc: String, + last_tc: String, range: String, prepares: String, pre_commits: String, @@ -63,6 +65,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_QC, ]), + last_tc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_TC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -140,6 +148,10 @@ impl GroupStatePath { self.last_qc.as_str() } + pub fn last_tc(&self) -> &str { + self.last_tc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index aebf6fb96..c4803d6ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,7 +12,8 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 - pub last_qc: Option, + pub last_qc: Option, + pub last_tc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -25,6 +26,8 @@ impl StorageCacheInfo { Self { dec_state_id: init_state_id, last_vote_round: 0, + last_qc: None, + last_tc: None, header_block: None, first_block: None, prepares: HashMap::new(), @@ -34,7 +37,6 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, - last_qc: None, } } } @@ -61,6 +63,7 @@ pub trait StorageWriter: Send + Sync { async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 2b61dbc47..b3a01fd60 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -38,10 +39,26 @@ impl StorageEngineGroupState { let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; let last_vote_round = map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; let last_qc = map_not_found_option_to_option(last_qc)?; let last_qc = match last_qc.as_ref() { - Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + Some(qc_id) => non_driver + .get_qc(qc_id, None) + .await? + .try_into() + .map_or(None, |qc| Some(qc)), + None => None, + }; + + let last_tc = op_env.get_by_path(state_path.last_tc()).await; + let last_tc = map_not_found_option_to_option(last_tc)?; + let last_tc = match last_tc.as_ref() { + Some(tc_id) => non_driver + .get_qc(tc_id, None) + .await? + .try_into() + .map_or(None, |tc| Some(tc)), None => None, }; @@ -118,6 +135,7 @@ impl StorageEngineGroupState { let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); cache.last_qc = last_qc; + cache.last_tc = last_tc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -440,6 +458,13 @@ impl StorageEngineGroupStateWriter { .await .map(|_| ()) } + + async fn save_last_tc_inner(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_tc(), tc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -509,6 +534,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_tc_inner(tc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 79491b186..ebeedd7ca 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -196,6 +196,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3f9fc9910..ee2618cde 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -10,7 +10,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffTimeout, + GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; @@ -442,30 +442,49 @@ impl GroupStorage { Ok(()) } - pub fn last_qc(&self) -> &Option { + pub fn last_qc(&self) -> &Option { &self.cache.last_qc } - pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { - let quorum_round = qc.quorum_round(); + pub async fn save_qc(&mut self, qc: &HotstuffBlockQC) -> BuckyResult<()> { + let quorum_round = qc.round; if quorum_round < self.cache.last_vote_round - || quorum_round - <= self - .cache - .last_qc - .as_ref() - .map_or(0, |qc| qc.quorum_round()) + || quorum_round <= self.cache.last_qc.as_ref().map_or(0, |qc| qc.round) { return Ok(()); } + let qc = GroupQuorumCertificate::from(qc.clone()); self.non_driver.put_qc(&qc).await?; let mut writer = self.storage_engine.create_writer().await?; writer.save_last_qc(&qc.desc().object_id()).await?; writer.commit().await?; - self.cache.last_qc = Some(qc); + self.cache.last_qc = Some(qc.try_into().unwrap()); + Ok(()) + } + + pub fn last_tc(&self) -> &Option { + &self.cache.last_tc + } + + pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + let quorum_round = tc.round; + if quorum_round < self.cache.last_vote_round + || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) + { + return Ok(()); + } + + let tc = GroupQuorumCertificate::from(tc.clone()); + self.non_driver.put_qc(&tc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_tc(&tc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_tc = Some(tc.try_into().unwrap()); Ok(()) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b5b6f4ce4..2ba99716e 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -798,6 +798,8 @@ async fn main_run() { admin_stacks.push(cyfs_stack); } + async_std::task::sleep(Duration::from_millis(10000)).await; + for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); From e84c2521d18ca06b16b50607f5c18667e2e10497 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:23:03 +0800 Subject: [PATCH 386/553] prepare for verify --- .../cyfs-core/protos/core_objects.proto | 14 -- src/component/cyfs-core/src/coreobj.rs | 1 - .../src/group/group_consensus_block.rs | 23 +++ .../cyfs-core/src/group/group_rpath_status.rs | 17 --- src/component/cyfs-core/src/group/mod.rs | 2 - .../protos/group_bft_protocol.proto | 6 + src/component/cyfs-group/src/crypto/crypto.rs | 14 -- src/component/cyfs-group/src/crypto/mod.rs | 3 - .../cyfs-group/src/dec/group_manager.rs | 35 +++-- .../src/dec_state/dec_state_requestor.rs | 32 ++-- src/component/cyfs-group/src/helper/verify.rs | 6 +- src/component/cyfs-group/src/lib.rs | 2 - .../src/objects/group_rpath_status.rs | 89 +++++++++++ src/component/cyfs-group/src/objects/mod.rs | 2 + .../cyfs-group/src/objects/protocol.rs | 140 +++++++++++++----- .../cyfs-group/src/storage/dec_storage.rs | 6 +- 16 files changed, 259 insertions(+), 133 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs delete mode 100644 src/component/cyfs-group/src/crypto/crypto.rs delete mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/objects/group_rpath_status.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 164c6bcd6..487ece4bd 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -431,20 +431,6 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } -message GroupRPathSubStatus { - string sub_path = 1; - repeated bytes state_id = 2; // for set -} - -message GroupRPathStatusDescContent { - bytes block_id = 1; - optional bytes sub_status_hash = 2; -} - -message GroupRPathStatusBodyContent { - repeated GroupRPathSubStatus sub_status = 1; -} - message GroupActionDescContent { // target GroupRPath r_path = 1; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 30bf0e013..3d53a082f 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -64,7 +64,6 @@ pub enum CoreObjectType { GroupProposal = 700, GroupUpdateGroup = 701, GroupConsensusBlock = 702, - GroupRPathStatus = 703, GroupAction = 704, GroupQuorumCertificate = 705, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 5d6d114c0..35c418552 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -38,6 +38,28 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } +impl GroupConsensusBlockDescContent { + pub fn rpath(&self) -> &GroupRPath { + &self.r_path + } + + pub fn result_state_id(&self) -> &Option { + &self.result_state_id + } + + pub fn height(&self) -> u64 { + self.height + } + + pub fn round(&self) -> u64 { + self.round + } + + pub fn group_chunk_id(&self) -> &ObjectId { + &self.group_chunk_id + } +} + #[derive(Clone, ProtobufTransformType)] #[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] pub struct HotstuffBlockQCSign { @@ -175,6 +197,7 @@ impl BodyContent for GroupConsensusBlockBodyContent { } } +pub type GroupConsensusBlockDesc = NamedObjectDesc; type GroupConsensusBlockType = NamedObjType; type GroupConsensusBlockBuilder = diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs deleted file mode 100644 index c55c41243..000000000 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::atomic::{AtomicU8, Ordering}; - -use crate::CoreObjectType; -use cyfs_base::*; -use serde::Serialize; -use sha2::Digest; - -// TODO: 后面再封装这个对象 -#[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus { - pub value_object_id: ObjectId, - pub block_id: ObjectId, - pub qc_block_id: ObjectId, -} - -#[cfg(test)] -mod test {} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index c153ab1ba..b2885d637 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -3,7 +3,6 @@ mod group_proposal; mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_rpath_status; mod group_update_group_proposal_param; pub use group_consensus_block::*; @@ -11,5 +10,4 @@ pub use group_proposal::*; pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 6ed8c3afe..621186522 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -15,3 +15,9 @@ message HotstuffTimeoutVote { bytes voter = 3; bytes signature = 4; } + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs deleted file mode 100644 index 9949f7a67..000000000 --- a/src/component/cyfs-group/src/crypto/crypto.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cyfs_base::{HashValue, ObjectId, Signature}; - -#[derive(Clone)] -pub struct Crypto {} - -impl Crypto { - pub fn sign(&self, hash: &HashValue) -> Signature { - unimplemented!() - } - - pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs deleted file mode 100644 index 066e79b6b..000000000 --- a/src/component/cyfs-group/src/crypto/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod crypto; - -pub use crypto::*; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 70fb10ba6..2f2229890 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,7 +289,7 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - // TODO: 暂时不实现 + // TODO: unimplemented // let rpath = header_block.r_path(); // let client = self // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) @@ -302,23 +302,22 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - // TODO: 暂时不实现 - // let rpath = result.as_ref().map_or_else( - // |(_, target)| target.check_rpath(), - // |(_, block, _)| block.r_path(), - // ); - // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - // .await?; - // client - // .on_message( - // HotstuffMessage::ProposalResult( - // proposal_id, - // result.map_err(|(err, _)| err), - // ), - // remote, - // ) - // .await; + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) + .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e30c0a5a7..369b3db6e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,10 +3,13 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; -use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; +use crate::{ + helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + CHANNEL_CAPACITY, +}; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -143,7 +146,7 @@ impl DecStateRequestorRunner { let result = self .verify_verifiable_state(sub_path.as_str(), &result, &remote) .await - .map(|_| result.value_object_id); + .map(|_| unimplemented!()); // TODO: 搜索目标值 self.query_state_notifier.reply(&sub_path, result).await } @@ -157,25 +160,22 @@ impl DecStateRequestorRunner { result: &GroupRPathStatus, remote: &ObjectId, ) -> BuckyResult<()> { - let header_block = self - .non_driver - .get_block(&result.block_id, Some(remote)) - .await?; - let qc_block = self - .non_driver - .get_block(&result.qc_block_id, Some(remote)) - .await?; + // let header_block = self + // .non_driver + // .get_block(&result.block_id, Some(remote)) + // .await?; + // let qc_block = self + // .non_driver + // .get_block(&result.qc_block_id, Some(remote)) + // .await?; - let qc = match qc_block.qc() { - Some(qc) => qc, - None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), - }; + let qc = &result.certificate; let group = self .non_driver .get_group( self.rpath.group_id(), - Some(header_block.group_chunk_id()), + Some(result.block_desc.content().group_chunk_id()), Some(&remote), ) .await?; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 2a384d1cf..b8ab12b69 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; + +use crate::GroupRPathStatus; pub async fn verify_block( block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index fefe3f808..ba8e83569 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -1,6 +1,5 @@ mod consensus; mod constant; -mod crypto; mod dec; mod dec_state; mod helper; @@ -12,7 +11,6 @@ mod utils; pub use consensus::*; pub use constant::*; -pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs new file mode 100644 index 000000000..f266d3dbd --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use cyfs_base::*; +use cyfs_core::{GroupConsensusBlockDesc, HotstuffBlockQC}; +use cyfs_lib::NONObjectInfo; +use prost::Message; + +#[derive(Clone)] +pub struct GroupRPathStatus { + pub block_desc: GroupConsensusBlockDesc, + pub certificate: HotstuffBlockQC, + pub status_map: HashMap, +} + +impl RawEncode for GroupRPathStatus { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + Ok(proto.encoded_len()) + } + + fn raw_encode<'a>( + &self, + mut buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + proto.encode_raw(&mut buf); + + Ok(buf) + } +} + +impl<'de> RawDecode<'de> for GroupRPathStatus { + fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + let (block_desc, remain) = + GroupConsensusBlockDesc::raw_decode(proto.block_desc.as_slice())?; + assert_eq!(remain.len(), 0); + let (certificate, remain) = HotstuffBlockQC::raw_decode(proto.certificate.as_slice())?; + assert_eq!(remain.len(), 0); + let mut status_map = HashMap::new(); + for obj_buf in proto.status_list.iter() { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status_map.insert(status.object_id, status); + } + + Ok(( + Self { + block_desc, + certificate, + status_map, + }, + buf, + )) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs index d6de55d79..5d1a8b13f 100644 --- a/src/component/cyfs-group/src/objects/mod.rs +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -1,7 +1,9 @@ mod group_decide_proposal; +mod group_rpath_status; mod group_update_proposal; mod protocol; pub use group_decide_proposal::*; +pub use group_rpath_status::*; pub use group_update_proposal::*; pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 3e5f513df..6c9f89e96 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,16 +2,15 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } -use std::result; - use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; +use crate::GroupRPathStatus; + #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), @@ -163,20 +162,16 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::ProposalResult({}, {:?})", proposal_id, - result.as_ref().map_or_else( - |err| { Err(err) }, - |(obj, block, qc)| { - let ok = format!( - "({:?}, {}/{}, {}/{})", - obj.as_ref().map(|o| o.object_id), - block.block_id(), - block.round(), - qc.block_id(), - qc.round() - ); - Ok(ok) - } - ) + result.as_ref().map(|(obj, block, qc)| { + format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + }) ) } Self::QueryState(sub_path) => { @@ -187,7 +182,17 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map(|status| { + let desc = status.block_desc.content(); + format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ) + }) ) } } @@ -196,6 +201,7 @@ impl std::fmt::Debug for HotstuffMessage { const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; +const PACKAGE_FLAG_QUERY_STATE_RESULT_OK: u8 = 0x80u8; #[derive(Clone)] pub(crate) enum HotstuffPackage { @@ -220,7 +226,10 @@ pub(crate) enum HotstuffPackage { >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, String, BuckyResult), + VerifiableState( + String, + Result, + ), } impl std::fmt::Debug for HotstuffPackage { @@ -296,12 +305,26 @@ impl std::fmt::Debug for HotstuffPackage { Self::QueryState(_, sub_path) => { write!(f, "HotstuffPackage::QueryState({})", sub_path) } - Self::VerifiableState(_, sub_path, result) => { + Self::VerifiableState(sub_path, result) => { write!( f, "HotstuffPackage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |status| { + let desc = status.block_desc.content(); + let ok = format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ); + Ok(ok) + } + ) ) } } @@ -323,7 +346,10 @@ impl HotstuffPackage { |(_, block, _)| block.r_path(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), - HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |status| status.block_desc.content().rpath(), + ), } } } @@ -399,10 +425,14 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::QueryState(addr, sub_path) => { addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { - 2 + addr.raw_measure(purpose)? - + sub_path.raw_measure(purpose)? - + result.raw_measure(purpose)? + HotstuffPackage::VerifiableState(sub_path, result) => { + sub_path.raw_measure(purpose)? + + match result { + Ok(status) => status.raw_measure(purpose)?, + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } } }; @@ -459,7 +489,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; if result.is_ok() { - buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + buf[0] |= PACKAGE_FLAG_PROPOSAL_RESULT_OK; } let buf = &mut buf[1..]; @@ -482,12 +512,20 @@ impl RawEncode for HotstuffPackage { let buf = sub_path.raw_encode(buf, purpose)?; addr.raw_encode(buf, purpose) } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { + HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; + if result.is_ok() { + buf[0] |= PACKAGE_FLAG_QUERY_STATE_RESULT_OK; + } let buf = &mut buf[1..]; - let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = sub_path.raw_encode(buf, purpose)?; - result.raw_encode(buf, purpose) + match result { + Ok(status) => status.raw_encode(buf, purpose), + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } } } } @@ -502,24 +540,28 @@ impl<'de> RawDecode<'de> for HotstuffPackage { 0 => { let buf = &buf[1..]; let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { @@ -527,17 +569,20 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } 7 => { @@ -549,6 +594,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), buf, @@ -557,6 +603,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { false => { let (err, buf) = BuckyError::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } } @@ -565,17 +612,29 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let buf = &buf[1..]; let (sub_path, buf) = String::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } 9 => { + let is_ok = (buf[0] & PACKAGE_FLAG_QUERY_STATE_RESULT_OK) != 0; let buf = &buf[1..]; - let (addr, buf) = decode_with_length(buf, 3)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (result, buf) = BuckyResult::::raw_decode(buf)?; - Ok(( - HotstuffPackage::VerifiableState(addr, sub_path, result), - buf, - )) + match is_ok { + true => { + let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok(( + HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), + buf, + )) + } + } } _ => unreachable!("unknown protocol"), } @@ -613,9 +672,10 @@ impl HotstuffPackage { HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) } - HotstuffMessage::VerifiableState(sub_path, result) => { - HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) - } + HotstuffMessage::VerifiableState(sub_path, result) => HotstuffPackage::VerifiableState( + sub_path, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ), } } } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 12e3629d8..cce00e736 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use async_std::sync::RwLock; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; +use cyfs_core::GroupConsensusBlock; + +use crate::GroupRPathStatus; #[derive(Clone)] pub struct DecStorageCache { @@ -11,8 +13,6 @@ pub struct DecStorageCache { pub qc_block: GroupConsensusBlock, } -// TODO: storage - #[derive(Clone)] pub struct DecStorage { cache: Arc>>, From 33035e2db466fe0ea5cd3e9bdb80bd9d48b9c3e8 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:28:28 +0800 Subject: [PATCH 387/553] compile --- .../cyfs-group/src/dec/group_manager.rs | 12 +++++++++--- .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 14 +++++++++----- src/component/cyfs-group/src/helper/verify.rs | 16 +++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 2f2229890..0d863e17b 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -328,13 +328,19 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - HotstuffPackage::VerifiableState(target, sub_path, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::VerifiableState(sub_path, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |status| status.block_desc.content().rpath(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .on_message( + HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), + remote, + ) .await; } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 369b3db6e..b5c3b107e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -180,7 +180,7 @@ impl DecStateRequestorRunner { ) .await?; - if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { Err(BuckyError::new( BuckyErrorCode::InvalidSignature, "verify failed", diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f33ec5fa..73afb0ad0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -315,10 +315,7 @@ impl DecStateSynchronizerRunner { remote: ObjectId, ) -> BuckyResult<()> { if qc_block.qc().is_none() { - log::warn!( - "the qc is none for qc-block({})", - qc_block.block_id() - ); + log::warn!("the qc is none for qc-block({})", qc_block.block_id()); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } @@ -365,7 +362,14 @@ impl DecStateSynchronizerRunner { } }; - if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + if header_block.check() + && verify_block( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + &group.1, + ) + .await? + { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index b8ab12b69..759bf2c4a 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,15 +1,17 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, +}; use crate::GroupRPathStatus; pub async fn verify_block( - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.block_id().object_id(); - if qc.round != block.round() || &qc.block_id != block_id { + let block_id = block_desc.object_id(); + if qc.round != block_desc.content().round() || qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, @@ -18,17 +20,13 @@ pub async fn verify_block( return Ok(false); } - if !block.check() { - return Ok(false); - } - unimplemented!() } pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { From ede4012b5bf8864b55ea1e7c23f7339f75b7760e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 23 Feb 2023 21:02:07 +0800 Subject: [PATCH 388/553] Verify the value on sub-path from anyone OOD in group --- .../src/consensus/hotstuff/hotstuff.rs | 28 ++++- .../src/consensus/vote/committee.rs | 66 ++++++++++- .../cyfs-group/src/dec/group_manager.rs | 54 ++++++--- .../cyfs-group/src/dec/rpath_client.rs | 34 ++++-- .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../src/dec_state/dec_state_requestor.rs | 73 ++++++------ .../src/dec_state/dec_state_synchronizer.rs | 80 ++++++-------- src/component/cyfs-group/src/helper/verify.rs | 18 --- .../src/objects/group_rpath_status.rs | 4 +- .../cyfs-group/src/storage/dec_storage.rs | 76 ++++++++++++- .../src/storage/engine/storage_engine.rs | 4 +- .../engine/storage_engine_group_state.rs | 23 +++- .../cyfs-group/src/storage/group_storage.rs | 104 +++++++++++++++++- src/component/cyfs-group/src/utils.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 15 files changed, 410 insertions(+), 166 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index a2a5e8f70..667966a6c 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -187,6 +187,19 @@ impl Hotstuff { self.state_pusher.request_last_state(remote).await; } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_query_state: sub_path: {}, remote: {:?},", + self, + sub_path, + remote + ); + + self.tx_message + .send((HotstuffMessage::QueryState(sub_path), remote)) + .await; + } } struct HotstuffRunner { @@ -1834,6 +1847,19 @@ impl HotstuffRunner { Ok(()) } + async fn handle_query_state(&self, sub_path: String, remote: ObjectId) -> BuckyResult<()> { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + + Ok(()) + } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; @@ -1918,7 +1944,7 @@ impl HotstuffRunner { Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), - Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d3fbd489c..ad3a21e35 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,9 +10,13 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { @@ -136,6 +140,47 @@ impl Committee { Ok(()) } + pub async fn verify_block_desc_with_qc( + &self, + block_desc: &GroupConsensusBlockDesc, + qc: &HotstuffBlockQC, + from: ObjectId, + ) -> BuckyResult<()> { + let block_id = block_desc.object_id(); + + log::debug!( + "[group committee] {} verify block desc {} step1", + self.local_device_id, + block_id + ); + + if block_id != qc.block_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the block id is unmatch with the qc", + )); + } + + self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + .await?; + + log::debug!( + "[group committee] {} verify block desc {} step2", + self.local_device_id, + block_id + ); + + self.verify_qc_with_desc(qc, block_desc.content()).await?; + + log::debug!( + "[group committee] {} verify block desc {} step3", + self.local_device_id, + block_id + ); + + Ok(()) + } + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { let hash = vote.hash(); let device = self.non_driver.get_device(&vote.voter).await?; @@ -250,8 +295,17 @@ impl Committee { qc: &HotstuffBlockQC, prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { - if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); + self.verify_qc_with_desc(qc, prev_block.named_object().desc().content()) + .await + } + + pub async fn verify_qc_with_desc( + &self, + qc: &HotstuffBlockQC, + prev_block_desc: &GroupConsensusBlockDescContent, + ) -> BuckyResult<()> { + if qc.round != prev_block_desc.round() { + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block_desc.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, "round not match in qc", @@ -261,7 +315,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block.group_chunk_id()), + Some(prev_block_desc.group_chunk_id()), ) .await?; @@ -291,7 +345,7 @@ impl Committee { .map_or(Ok(()), |e| e) } - async fn check_group( + pub async fn check_group( &self, chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 0d863e17b..f7b7fbbbe 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -123,6 +123,7 @@ impl GroupManager { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); + let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), @@ -143,9 +144,13 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let state_proccessor = state_mgr + .load_root_state(local_device_id.object_id(), Some(local_id), true) + .await?; let client = RPathClient::load( - local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + state_proccessor.unwrap(), non_driver, network_sender, ) @@ -199,7 +204,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, Some(&block), Some(&remote), ) @@ -215,7 +220,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -231,7 +236,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -247,7 +252,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -263,7 +268,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -279,7 +284,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -321,12 +326,32 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message(HotstuffMessage::QueryState(sub_path), remote) + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + IsCreateRPath::No, + None, + Some(&remote), + ) .await; + + match control { + Ok(control) => { + control + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + _ => { + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + } } HotstuffPackage::VerifiableState(sub_path, result) => { let rpath = result.as_ref().map_or_else( @@ -436,15 +461,10 @@ impl GroupManager { let store = match store { Some(store) => store, None => { - let init_state = match is_auto_create { - IsCreateRPath::Yes(init_state) => init_state, - _ => unreachable!(), - }; GroupStorage::create( group_id, dec_id, rpath, - init_state, non_driver.clone(), local_device_id.object_id().clone(), &root_state_mgr, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 9f1d08579..8a1dd34a7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -5,18 +5,18 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, storage::DecStorage, - HotstuffMessage, CLIENT_POLL_TIMEOUT, + Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; struct RPathClientRaw { rpath: GroupRPath, - local_id: ObjectId, + local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, @@ -28,22 +28,31 @@ pub struct RPathClient(Arc); impl RPathClient { pub(crate) async fn load( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { - let dec_store = DecStorage::load().await?; + let dec_store = DecStorage::load(state_processor).await?; + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); + let state_sync = DecStateSynchronizer::new( - local_id, + local_device_id, rpath.clone(), + committee.clone(), non_driver.clone(), dec_store.clone(), ); let state_requestor = DecStateRequestor::new( - local_id, + local_device_id, rpath.clone(), + committee, network_sender.clone(), non_driver.clone(), dec_store.clone(), @@ -53,7 +62,7 @@ impl RPathClient { rpath, non_driver, network_sender, - local_id, + local_device_id, state_sync, state_requestor, }; @@ -77,7 +86,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -143,7 +152,7 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let random = rand::thread_rng().gen_range(0..oods.len()); let ood = oods.get(random).unwrap().clone(); @@ -154,14 +163,15 @@ impl RPathClient { Ok(()) } - pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 .non_driver .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); + let members = + group.select_members_with_distance(&self.0.local_device_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 101b34075..7abff1ec1 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -89,7 +89,9 @@ impl RPathControl { HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), HotstuffMessage::ProposalResult(_, _) => unreachable!(), - HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::QueryState(sub_path) => { + self.0.hotstuff.on_query_state(sub_path, remote).await + } HotstuffMessage::VerifiableState(_, _) => unreachable!(), } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index b5c3b107e..0a3544c09 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,10 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, CHANNEL_CAPACITY, }; @@ -19,9 +20,9 @@ enum DecStateRequestorMessage { } struct DecStateRequestorRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } #[derive(Clone)] @@ -29,8 +30,9 @@ pub struct DecStateRequestor(Arc); impl DecStateRequestor { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, store: DecStorage, @@ -39,8 +41,9 @@ impl DecStateRequestor { let notifier = CallReplyNotifier::new(); let mut runner = DecStateRequestorRunner::new( - local_id, + local_device_id, rpath, + committee, rx, store, network_sender, @@ -51,7 +54,7 @@ impl DecStateRequestor { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateRequestorRaw { - local_id, + local_device_id, tx_dec_state_req_message: tx, query_state_notifier: notifier, })) @@ -60,7 +63,7 @@ impl DecStateRequestor { pub async fn wait_query_state( &self, sub_path: String, - ) -> CallReplyWaiter> { + ) -> CallReplyWaiter>> { self.0.query_state_notifier.prepare(sub_path).await } @@ -88,21 +91,23 @@ impl DecStateRequestor { } struct DecStateRequestorRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, // timer: Timer, store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } impl DecStateRequestorRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<( DecStateRequestorMessage, ObjectId, @@ -110,10 +115,10 @@ impl DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, rx_dec_state_req_message, // timer: Timer::new(SYNCHRONIZER_TIMEOUT), @@ -121,6 +126,7 @@ impl DecStateRequestorRunner { query_state_notifier, network_sender, non_driver, + committee, } } @@ -144,9 +150,9 @@ impl DecStateRequestorRunner { match result { Ok(result) => { let result = self - .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .check_sub_path_value(sub_path.as_str(), &result, &remote) .await - .map(|_| unimplemented!()); // TODO: 搜索目标值 + .map(|r| r.cloned()); self.query_state_notifier.reply(&sub_path, result).await } @@ -154,40 +160,23 @@ impl DecStateRequestorRunner { } } - async fn verify_verifiable_state( + async fn check_sub_path_value<'a>( &self, sub_path: &str, - result: &GroupRPathStatus, + verifiable_status: &'a GroupRPathStatus, remote: &ObjectId, - ) -> BuckyResult<()> { - // let header_block = self - // .non_driver - // .get_block(&result.block_id, Some(remote)) - // .await?; - // let qc_block = self - // .non_driver - // .get_block(&result.qc_block_id, Some(remote)) - // .await?; - - let qc = &result.certificate; - - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(result.block_desc.content().group_chunk_id()), - Some(&remote), + ) -> BuckyResult> { + self.committee + .verify_block_desc_with_qc( + &verifiable_status.block_desc, + &verifiable_status.certificate, + remote.clone(), ) .await?; - if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "verify failed", - )) - } else { - Ok(()) - } + self.store + .check_sub_path_value(sub_path, verifiable_status) + .await } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 73afb0ad0..7272b3882 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -10,10 +10,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::{verify_block, Timer}, + helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, + Committee, CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -32,7 +32,7 @@ enum DecStateSynchronizerMessage { } struct DecStateSynchronizerRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, proposal_result_notifier: CallReplyNotifier>>, } @@ -42,8 +42,9 @@ pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { @@ -51,8 +52,9 @@ impl DecStateSynchronizer { let notifier = CallReplyNotifier::new(); let mut runner = DecStateSynchronizerRunner::new( - local_id, + local_device_id, rpath, + committee, tx.clone(), rx, store, @@ -63,7 +65,7 @@ impl DecStateSynchronizer { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateSynchronizerRaw { - local_id, + local_device_id, tx_dec_state_sync_message: tx, proposal_result_notifier: notifier, })) @@ -126,8 +128,9 @@ struct UpdateNotifyInfo { } struct DecStateSynchronizerRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, @@ -142,8 +145,9 @@ struct DecStateSynchronizerRunner { impl DecStateSynchronizerRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<( DecStateSynchronizerMessage, ObjectId, @@ -157,7 +161,7 @@ impl DecStateSynchronizerRunner { proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, tx_dec_state_sync_message, rx_dec_state_sync_message, @@ -167,6 +171,7 @@ impl DecStateSynchronizerRunner { update_notifies: None, non_driver, proposal_result_notifier, + committee, } } @@ -330,52 +335,29 @@ impl DecStateSynchronizerRunner { } } - let group = match self.update_notifies.as_ref() { - Some(n) => Some((n.group_chunk_id, n.group.clone())), - None => self - .check_cache() - .await - .as_ref() - .map(|c| (c.group_chunk_id, c.group.clone())), - } - .map_or(None, |(chunk_id, group)| { - if &chunk_id == header_block.group_chunk_id() { - Some((chunk_id, group)) - } else { - None - } - }); - - // group changed - let group = match group { - Some(group) => group, - None => { - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(header_block.group_chunk_id()), - Some(&remote), - ) - .await?; - (header_block.group_chunk_id().clone(), group) - } - }; - if header_block.check() - && verify_block( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - &group.1, - ) - .await? + && self + .committee + .verify_block_desc_with_qc( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + remote, + ) + .await + .is_ok() { + let group = self + .committee + .check_group(Some(header_block.group_chunk_id()), None) + .await?; + let group_chunk_id = header_block.group_chunk_id().clone(); + self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, remotes: HashSet::from([remote]), - group_chunk_id: group.0, - group: group.1, + group_chunk_id, + group, }); }; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 759bf2c4a..ef3e34495 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -5,24 +5,6 @@ use cyfs_core::{ use crate::GroupRPathStatus; -pub async fn verify_block( - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - let block_id = block_desc.object_id(); - if qc.round != block_desc.content().round() || qc.block_id != block_id { - log::error!( - "the qc-block({}) should be next block({})", - qc.round, - block_id - ); - return Ok(false); - } - - unimplemented!() -} - pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index f266d3dbd..858c37fff 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -13,7 +13,7 @@ pub struct GroupRPathStatus { } impl RawEncode for GroupRPathStatus { - fn raw_measure(&self, purpose: &Option) -> BuckyResult { + fn raw_measure(&self, _purpose: &Option) -> BuckyResult { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; let mut status_list = vec![]; @@ -33,7 +33,7 @@ impl RawEncode for GroupRPathStatus { fn raw_encode<'a>( &self, mut buf: &'a mut [u8], - purpose: &Option, + _purpose: &Option, ) -> BuckyResult<&'a mut [u8]> { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index cce00e736..de5a0fd4a 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -1,10 +1,14 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, + ObjectTypeCode, RawDecode, +}; use cyfs_core::GroupConsensusBlock; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::GroupRPathStatus; +use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; #[derive(Clone)] pub struct DecStorageCache { @@ -16,13 +20,15 @@ pub struct DecStorageCache { #[derive(Clone)] pub struct DecStorage { cache: Arc>>, + pub state_processor: GlobalStateRawProcessorRef, } impl DecStorage { - pub async fn load() -> BuckyResult { - unimplemented!(); + pub async fn load(state_processor: GlobalStateRawProcessorRef) -> BuckyResult { + // unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), + state_processor, }; Ok(obj) @@ -45,4 +51,64 @@ impl DecStorage { pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } + + pub async fn check_sub_path_value<'a>( + &self, + sub_path: &str, + verifiable_status: &'a GroupRPathStatus, + ) -> BuckyResult> { + let block_desc = &verifiable_status.block_desc; + let qc = &verifiable_status.certificate; + + let mut parent_state_id = match block_desc.content().result_state_id() { + Some(state_id) => state_id.clone(), + None => return Ok(None), + }; + + let root_cache = self.state_processor.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { + Some(state) => state, + None => return Ok(None), + }; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(None); + } + } + } + + Ok(verifiable_status.status_map.get(&parent_state_id)) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index c4803d6ff..eb0ede98f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -22,9 +22,9 @@ pub struct StorageCacheInfo { } impl StorageCacheInfo { - pub fn new(init_state_id: Option) -> Self { + pub fn new(dec_state_id: Option) -> Self { Self { - dec_state_id: init_state_id, + dec_state_id, last_vote_round: 0, last_qc: None, last_tc: None, diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index b3a01fd60..604e44744 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,10 +2,10 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, + ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -154,6 +154,19 @@ impl StorageEngineGroupState { None => 0, }; + let dec_state_id_in_header = cache + .header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); + + assert_eq!(dec_state_id, dec_state_id_in_header); + if dec_state_id != dec_state_id_in_header { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the state should same as it in header-block", + )); + } + let (prepare_blocks, pre_commit_blocks) = load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { @@ -179,6 +192,10 @@ impl StorageEngineGroupState { .await?, ) } + + pub fn root_cache(&self) -> &ObjectMapRootCacheRef { + self.state_mgr.root_cache() + } } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index ee2618cde..d233025ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -5,7 +5,7 @@ use std::{ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, + ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -15,7 +15,8 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ @@ -56,7 +57,6 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, @@ -84,7 +84,7 @@ impl GroupStorage { GroupStatePath::new(rpath.to_string()), ), local_device_id, - cache: StorageCacheInfo::new(init_state_id), + cache: StorageCacheInfo::new(None), }) } @@ -809,4 +809,100 @@ impl GroupStorage { ) } } + + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let (header_block, qc) = match self.cache.header_block.as_ref() { + Some(block) => { + let (_, qc_block) = self + .cache + .pre_commits + .iter() + .next() + .expect("pre-commit should not be empty"); + + assert_eq!( + qc_block.prev_block_id().unwrap(), + block.block_id().object_id(), + "the prev-block for all pre-commits should be the header" + ); + + (block, qc_block.qc().as_ref().unwrap()) + } + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "the header block is none", + )); + } + }; + + let mut parent_state_id = match header_block.result_state_id() { + Some(state_id) => state_id.clone(), + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map: HashMap::new(), + }) + } + }; + + let mut status_map = HashMap::new(); + + let root_cache = self.storage_engine.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + status_map.insert(parent_state_id, parent_state); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } + } + } + + let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + status_map.insert(parent_state_id, leaf_state); + + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } } diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 9fbc4eb4f..5d005a726 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), // init state + Yes, } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 2ba99716e..0401c55a0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -816,7 +816,7 @@ async fn main_run() { &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -845,7 +845,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -892,7 +892,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); From a5395e6c15b56a90ae758b99610613f7bb4bdde6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 17:03:44 +0800 Subject: [PATCH 389/553] Example for APP-State as tree --- .../src/consensus/hotstuff/hotstuff.rs | 9 +- .../cyfs-group/src/dec/delegate_factory.rs | 10 +- .../src/storage/engine/storage_engine.rs | 2 +- .../engine/storage_engine_group_state.rs | 23 ++- .../cyfs-group/src/storage/group_storage.rs | 18 +- src/tests/group-example/src/main.rs | 155 +++++++++++++++--- 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 667966a6c..d9773bd88 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,13 +9,13 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, @@ -499,7 +499,7 @@ impl HotstuffRunner { if self .delegate - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -851,6 +851,7 @@ impl HotstuffRunner { .on_commited( &proposal_obj, pre_state_id, + self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1528,7 +1529,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id).await { + match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index bdcb98f60..0b13d97ce 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -34,12 +34,14 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult; @@ -47,7 +49,13 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ); } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index eb0ede98f..cbb5d99df 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 604e44744..aae81394b 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -8,8 +8,8 @@ use cyfs_base::{ use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -672,3 +672,22 @@ fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult Self { + Self { + state_mgr: state_mgr.clone(), + } + } +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { + async fn create_single_op_env(&self) -> BuckyResult { + self.state_mgr.create_single_op_env(ACCESS) + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d233025ab..3a1c20f2a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,12 +15,15 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ - engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + engine::{ + GroupObjectMapProcessorGroupState, StorageCacheInfo, StorageEngineGroupState, + StorageEngineMock, + }, StorageEngine, }; @@ -50,6 +53,7 @@ pub struct GroupStorage { cache: StorageCacheInfo, storage_engine: StorageEngineGroupState, + object_map_processor: GroupObjectMapProcessorGroupState, } impl GroupStorage { @@ -71,6 +75,7 @@ impl GroupStorage { .expect("create group state failed."); let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -85,6 +90,7 @@ impl GroupStorage { ), local_device_id, cache: StorageCacheInfo::new(None), + object_map_processor, }) } @@ -129,6 +135,7 @@ impl GroupStorage { let state_path = GroupStatePath::new(rpath.to_string()); let cache = StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -140,6 +147,7 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, cache, + object_map_processor, }) } @@ -905,4 +913,8 @@ impl GroupStorage { status_map, }); } + + pub fn get_object_map_processor(&self) -> &dyn GroupObjectMapProcessor { + &self.object_map_processor + } } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0401c55a0..0fae6dd53 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -38,16 +38,18 @@ mod Common { CyfsStackNOCParams, CyfsStackParams, }; - lazy_static::lazy_static! { - // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + /** + * |--root + * |--folder1 + * |--folder2 + * |--value-->u64 + */ - // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); + pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } fn create_member( @@ -495,7 +497,7 @@ mod Client { } mod GroupDecService { - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, fmt::format, sync::Arc}; use async_std::sync::Mutex; use cyfs_base::*; @@ -503,9 +505,11 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; use cyfs_stack::CyfsStack; + use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; + pub struct DecService {} impl DecService { @@ -580,17 +584,78 @@ mod GroupDecService { } impl MyRPathDelegate { - pub fn execute( + pub async fn get_value_from_state_tree_with_single_op_envs( + pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<( + Option, + Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + )> { + let mut single_op_envs = vec![]; + let mut parent_map_id = pre_state_id; + for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + let single_op_env = object_map_processor.create_single_op_env().await.expect( + format!( + "create_single_op_env load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + parent_map_id = match parent_map_id { + Some(parent_map_id) => { + single_op_env.load(&parent_map_id).await.expect( + format!( + "load folder {} parent with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + single_op_env.get_by_key(folder).await.expect( + format!( + "load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ) + } + None => { + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!( + "create folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + None + } + }; + single_op_envs.push((single_op_env, folder, parent_map_id)); + } + + Ok((parent_map_id, single_op_envs)) + } + + pub async fn execute( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let result_state_id = { + let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await?; + + let result_value = { /** * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); + let pre_value = pre_value.map_or(0, |pre_value| { + let buf = pre_value.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -608,6 +673,32 @@ mod GroupDecService { .unwrap() }; + let result_state_id = { + let mut sub_folder_value = result_value; + for (parent_single_op_env, folder, sub_folder_prev_value) in + single_op_envs.into_iter().rev() + { + parent_single_op_env + .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + .await + .expect( + format!( + "update folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + sub_folder_value = parent_single_op_env.commit().await.expect( + format!( + "commit folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + } + sub_folder_value + }; + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? @@ -623,7 +714,7 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_state_id + proposal + context + * (result_state_id, return_object) = pre_value + proposal + context */ Ok(ExecuteResult { context, @@ -632,17 +723,20 @@ mod GroupDecService { }) } - pub fn verify( + pub async fn verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context */ - let result = self.execute(proposal, pre_state_id)?; + let result = self + .execute(proposal, pre_state_id, object_map_processor) + .await?; let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() @@ -658,23 +752,28 @@ mod GroupDecService { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id) + self.execute(proposal, pre_state_id, object_map_processor) + .await } async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) + self.verify(proposal, pre_state_id, object_map_processor, execute_result) + .await } async fn on_commited( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { @@ -685,14 +784,28 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let pre_value = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); - let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let result_value = Self::get_value_from_state_tree_with_single_op_envs( + execute_result.result_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); @@ -901,7 +1014,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } From 986552580cfa4bcb63da5545883058ac2852a8f0 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 19:51:46 +0800 Subject: [PATCH 390/553] Fix: Update the state structure, mount the template dec-state of blocks in prepare/pre-commit, to avoid it's recycled. --- .../cyfs-base/src/objects/object_map/mod.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 5 +- .../cyfs-group/src/statepath/design.md | 12 +- .../src/statepath/group_statepath.rs | 34 +++ .../src/storage/engine/storage_engine.rs | 20 +- .../engine/storage_engine_group_state.rs | 139 ++++++++-- .../src/storage/engine/storage_engine_mock.rs | 7 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 248 +++++++++++------- 9 files changed, 351 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index 3bbc5f131..75589834b 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -18,6 +18,7 @@ mod visitor; pub use access::*; pub use cache::*; pub use diff::*; +pub use isolate_path_env::*; pub use iterator::*; pub use object_map::*; pub use op_env::*; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 0b13d97ce..f5092dbfc 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,6 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -58,4 +60,5 @@ pub trait RPathDelegate: Sync + Send { #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; } diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index cb964e066..885888d5b 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -22,14 +22,20 @@ | |--users | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-vote-round-->u64 // 最后一次投票的 轮次 | |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block | | -| |--prepares->Set // Prepare状态的block -| |--pre-commits->Set // pre-commit状态的block +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 72f48e601..0ed0abd25 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -10,6 +10,8 @@ pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; @@ -164,10 +166,42 @@ impl GroupStatePath { self.prepares.as_str() } + pub fn prepares_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn prepares_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn pre_commits(&self) -> &str { self.pre_commits.as_str() } + pub fn pre_commits_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn finish_proposals(&self) -> &str { self.finish_proposals.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index cbb5d99df..e14445695 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -43,9 +43,19 @@ impl StorageCacheInfo { #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()>; + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + is_instead: bool, + ) -> BuckyResult<()>; + async fn push_commit( &mut self, height: u64, @@ -54,7 +64,9 @@ pub trait StorageWriter: Send + Sync { prev_result_state_id: &Option, min_height: u64, ) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( &mut self, proposal_ids: &[ObjectId], @@ -62,7 +74,9 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index aae81394b..8b8799207 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,14 +2,15 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, - ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -90,7 +91,8 @@ impl StorageEngineGroupState { None => None, }; - let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let prepare_block_ids = + load_object_ids_with_path_map_key(&op_env, state_path.prepares()).await?; if prepare_block_ids.len() == 0 && commit_range.is_none() { return Err(BuckyError::new( BuckyErrorCode::NotFound, @@ -99,7 +101,7 @@ impl StorageEngineGroupState { } let pre_commit_block_ids = - load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + load_object_ids_with_path_map_key(&op_env, state_path.pre_commits()).await?; let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { @@ -113,8 +115,10 @@ impl StorageEngineGroupState { n }); - let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; - let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + let adding_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.adding()).await?; + let over_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.recycle()).await?; let load_block_ids = [ first_header_block_ids.as_slice(), @@ -233,7 +237,7 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new(ObjectMapSimpleContentType::Map) .await?; None } else { @@ -253,20 +257,51 @@ impl StorageEngineGroupStateWriter { }) } - async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn create_block_result_object_map( + &self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult { + let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await?; + single_op_env + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + if let Some(state_id) = result_state_id.as_ref() { + single_op_env + .insert_with_key(GROUP_STATE_PATH_RESULT_STATE, state_id) + .await?; + } + + single_op_env.commit().await + } + + async fn insert_prepares_inner( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) + .await?; self.prepare_op_env - .insert(block_id) + .insert_with_key(block_id.to_string().as_str(), &block_result_pair) .await - .map(|is_changed| assert!(is_changed)) } async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); if is_instead { self.op_env @@ -274,12 +309,17 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self - .op_env - .insert(self.state_path.pre_commits(), block_id) + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) .await?; - assert!(is_changed); - Ok(()) + + self.op_env + .insert_with_key( + self.state_path.pre_commits(), + block_id.to_string().as_str(), + &block_result_pair, + ) + .await } async fn push_commit_inner( @@ -357,8 +397,11 @@ impl StorageEngineGroupStateWriter { async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); } Ok(()) } @@ -486,19 +529,26 @@ impl StorageEngineGroupStateWriter { #[async_trait::async_trait] impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result = self.insert_prepares_inner(block_id, result_state_id).await; self.write_result.clone() } async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result = self + .insert_pre_commit_inner(block_id, result_state_id, is_instead) + .await; self.write_result.clone() } @@ -614,7 +664,7 @@ fn parse_u64_obj(obj: &ObjectId) -> u64 { u64::from_le_bytes(buf) } -async fn load_object_ids_with_path( +async fn load_object_ids_with_path_set( op_env: &ObjectMapPathOpEnvRef, full_path: &str, ) -> BuckyResult> { @@ -647,6 +697,41 @@ async fn load_object_ids_with_path( Ok(object_ids) } +async fn load_object_ids_with_path_map_key( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Map((key_id_base58, _)) => { + object_ids.push(ObjectId::from_base58(key_id_base58)?) + } + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} + fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { match r { Ok(t) => Ok(Some(t)), @@ -690,4 +775,8 @@ impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { async fn create_single_op_env(&self) -> BuckyResult { self.state_mgr.create_single_op_env(ACCESS) } + + async fn create_sub_tree_op_env(&self) -> BuckyResult { + self.state_mgr.create_isolate_path_op_env(ACCESS) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index ebeedd7ca..fbc7cafdc 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -71,7 +71,11 @@ pub struct StorageEngineMockWriter<'a> { #[async_trait::async_trait] impl<'a> StorageWriter for StorageEngineMockWriter<'a> { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { if !self.engine.prepare_blocks.insert(block_id.clone()) { assert!(false); return Err(BuckyError::new( @@ -85,6 +89,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { if !self.engine.prepare_blocks.remove(block_id) { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a1c20f2a..491d029dd 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -291,10 +291,16 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(block_id.object_id()).await?; - if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_prepares(block_id.object_id(), block.result_state_id()) + .await?; + if let Some((new_pre_commit_id, new_pre_commit)) = new_pre_commit.as_ref() { writer - .insert_pre_commit(new_pre_commit, new_header.is_some()) + .insert_pre_commit( + new_pre_commit_id, + new_pre_commit.result_state_id(), + new_header.is_some(), + ) .await?; } if let Some(new_header) = new_header.as_ref() { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0fae6dd53..394b15acb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -584,59 +584,59 @@ mod GroupDecService { } impl MyRPathDelegate { - pub async fn get_value_from_state_tree_with_single_op_envs( - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, - ) -> BuckyResult<( - Option, - Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - )> { - let mut single_op_envs = vec![]; - let mut parent_map_id = pre_state_id; - for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - let single_op_env = object_map_processor.create_single_op_env().await.expect( - format!( - "create_single_op_env load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - parent_map_id = match parent_map_id { - Some(parent_map_id) => { - single_op_env.load(&parent_map_id).await.expect( - format!( - "load folder {} parent with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - single_op_env.get_by_key(folder).await.expect( - format!( - "load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ) - } - None => { - single_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await - .expect( - format!( - "create folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - None - } - }; - single_op_envs.push((single_op_env, folder, parent_map_id)); - } - - Ok((parent_map_id, single_op_envs)) - } + // pub async fn get_value_from_state_tree_with_single_op_envs( + // pre_state_id: Option, + // object_map_processor: &dyn GroupObjectMapProcessor, + // ) -> BuckyResult<( + // Option, + // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + // )> { + // let mut single_op_envs = vec![]; + // let mut parent_map_id = pre_state_id; + // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + // let single_op_env = object_map_processor.create_single_op_env().await.expect( + // format!( + // "create_single_op_env load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // parent_map_id = match parent_map_id { + // Some(parent_map_id) => { + // single_op_env.load(&parent_map_id).await.expect( + // format!( + // "load folder {} parent with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // single_op_env.get_by_key(folder).await.expect( + // format!( + // "load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ) + // } + // None => { + // single_op_env + // .create_new(ObjectMapSimpleContentType::Map) + // .await + // .expect( + // format!( + // "create folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // None + // } + // }; + // single_op_envs.push((single_op_env, folder, parent_map_id)); + // } + + // Ok((parent_map_id, single_op_envs)) + // } pub async fn execute( &self, @@ -644,11 +644,30 @@ mod GroupDecService { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await?; + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + let pre_value = match pre_state_id { + Some(pre_state_id) => { + state_op_env.load(&pre_state_id).await?; + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ) + } + None => { + state_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ); + None + } + }; let result_value = { /** @@ -674,29 +693,50 @@ mod GroupDecService { }; let result_state_id = { - let mut sub_folder_value = result_value; - for (parent_single_op_env, folder, sub_folder_prev_value) in - single_op_envs.into_iter().rev() - { - parent_single_op_env - .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - .await - .expect( - format!( - "update folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value - ) - .as_str(), - ); - sub_folder_value = parent_single_op_env.commit().await.expect( + state_op_env + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .await + .expect( format!( - "commit folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value + "set_with_path {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value ) .as_str(), ); - } - sub_folder_value + state_op_env.commit().await.expect( + format!( + "commit {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value + ) + .as_str(), + ) + // let mut sub_folder_value = result_value; + // for (parent_single_op_env, folder, sub_folder_prev_value) in + // single_op_envs.into_iter().rev() + // { + // parent_single_op_env + // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + // .await + // .expect( + // format!( + // "update folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // sub_folder_value = parent_single_op_env.commit().await.expect( + // format!( + // "commit folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // } + // sub_folder_value }; let receipt = { @@ -784,13 +824,26 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let pre_value = match pre_state_id { + Some(pre_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&pre_state_id) + .await + .expect(format!("load {} failed", pre_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; @@ -798,13 +851,26 @@ mod GroupDecService { u64::from_be_bytes(pre_value) }); - let result_value = Self::get_value_from_state_tree_with_single_op_envs( - execute_result.result_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let result_value = match execute_result.result_state_id { + Some(result_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&result_state_id) + .await + .expect(format!("load {} failed", result_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; From 508904cd3c6546ddd75babe362478626678b5be2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:00 +0800 Subject: [PATCH 391/553] Accept the invalid block with vote it. --- src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 138 +++++++++++++----- .../cyfs-group/src/storage/group_storage.rs | 102 +------------ 3 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index aaab4ed76..4a7aae6c2 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' +itertools = "0.10.3" cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d9773bd88..511b0b32e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -13,6 +13,7 @@ use cyfs_core::{ }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; +use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, @@ -365,7 +366,7 @@ impl HotstuffRunner { } } - let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, Err(err) => return err }; @@ -391,9 +392,6 @@ impl HotstuffRunner { self, block.block_id()); - self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await?; - self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -402,7 +400,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote, &proposals).await + self.process_block(block, remote, &HashMap::new()).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -574,7 +572,7 @@ impl HotstuffRunner { } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { match self.store.block_linked(block).await .map_err(|err| Err(err))? { @@ -585,16 +583,6 @@ impl HotstuffRunner { ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - Err (Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - ))) - } crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", @@ -605,7 +593,7 @@ impl HotstuffRunner { "duplicate block", ))) } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { + crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", self, @@ -614,7 +602,7 @@ impl HotstuffRunner { // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; - Ok((prev_block, proposals)) + Ok(prev_block) } crate::storage::BlockLinkState::Pending => { log::warn!( @@ -942,20 +930,6 @@ impl HotstuffRunner { return None; } - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 - let mut proposal_temp: HashMap = HashMap::new(); - if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { - Ok(_) => proposals = &proposal_temp, - Err(_) => return None - } - } else { - assert_eq!(proposals.len(), block.proposals().len()); - } - if !Self::check_timestamp_precision(block, proposals) { - return None; - } - // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -982,6 +956,22 @@ impl HotstuffRunner { return None; } + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block.clone()), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None + }, + }, + None => None + }; + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -993,6 +983,77 @@ impl HotstuffRunner { } } + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + return None + } + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + return None; + } + + if proposals.len() != block.proposals().len() { + let mut dup_proposals = block.proposals().clone(); + dup_proposals.sort_unstable_by_key(|p| p.proposal); + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + ); + return None; + } + + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + match block.prev_block_id() { + Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await.map(|is_finished| (is_finished, &proposal_result.proposal)), + None => Ok((false, &proposal_result.proposal)) + } + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok((is_finished, proposal_id)) => { + if is_finished { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + proposal_id + ); + return None; + } + }, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", + self, + block.block_id(), + err + ); + return None; + }, + } + } + + if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await.is_err() { + return None; + } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1021,12 +1082,23 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { false } else { + if let Some(prev_block) = prev_block { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { + if duration > TIME_PRECISION { + return false + } + } + } + for proposal in block.proposals() { let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 491d029dd..04e4c80fc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,22 +1,19 @@ -use std::{ - collections::{HashMap, HashSet}, - time::SystemTime, -}; +use std::collections::{HashMap, HashSet}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ @@ -31,11 +28,10 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, - DuplicateProposal, Duplicate, Link( Option, - HashMap, + // HashMap, ), // Pending, InvalidBranch, @@ -528,18 +524,6 @@ impl GroupStorage { return Ok(BlockLinkState::Duplicate); } - let now = SystemTime::now(); - let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); - - if let Ok(duration) = block_time.duration_since(now) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } - log::debug!( "[group storage] {} block_linked {} step2", self.local_device_id, @@ -554,17 +538,6 @@ impl GroupStorage { } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); - if let Ok(duration) = prev_block_time.duration_since(block_time) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } Some(prev_block) } } @@ -592,66 +565,7 @@ impl GroupStorage { block.block_id() ); - let mut proposals = HashMap::new(); - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? - { - return Ok(BlockLinkState::DuplicateProposal); - } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - - Ok(BlockLinkState::Link( - None, - HashMap::from([(proposal_result.proposal, proposal)]), - )) - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok(result) => match result { - BlockLinkState::Link(_, proposal) => { - let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); - if proposals.get(&proposal_id).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } - proposals.insert(proposal_id, proposal); - } - _ => return Ok(result), - }, - _ => return check_result, - } - } - - log::debug!( - "[group storage] {} block_linked {} step4", - self.local_device_id, - block.block_id() - ); - - Ok(BlockLinkState::Link(prev_block, proposals)) + Ok(BlockLinkState::Link(prev_block)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From de22151dcfcf3f5114fc675b9fd609d8e3381a56 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:55 +0800 Subject: [PATCH 392/553] Chore unused code --- src/component/cyfs-group/src/storage/group_storage.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 04e4c80fc..122ae72ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -29,10 +29,7 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, Duplicate, - Link( - Option, - // HashMap, - ), // + Link(Option), // Pending, InvalidBranch, } From 78e7c26dbcb1b040c3595ee2ac2ac4c29178f305 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 12:20:23 +0800 Subject: [PATCH 393/553] get VerifiableState from the admin --- .../src/consensus/hotstuff/hotstuff.rs | 260 +++++++++++------- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 2 +- src/component/cyfs-group/src/constant.rs | 2 +- .../src/dec_state/dec_state_requestor.rs | 5 + .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../src/objects/group_rpath_status.rs | 21 +- .../cyfs-group/src/objects/protocol.rs | 11 +- .../cyfs-group/src/storage/dec_storage.rs | 6 + .../cyfs-group/src/storage/group_storage.rs | 27 +- src/tests/group-example/Cargo.toml | 3 +- src/tests/group-example/src/main.rs | 79 +++++- 11 files changed, 302 insertions(+), 116 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 511b0b32e..10c5d9635 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -4,7 +4,7 @@ use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, + RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -19,11 +19,13 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * + * synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -212,6 +214,7 @@ struct HotstuffRunner { round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, + max_quorum_round: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -311,6 +314,7 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, + max_quorum_round: round - 1, state_pusher, tx_block_gen, rx_block_gen, @@ -366,15 +370,6 @@ impl HotstuffRunner { } } - let prev_block = match self.check_block_linked(&block, remote).await { - Ok(link) => link, - Err(err) => return err - }; - - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", - self, - block.block_id()); - self.committee .verify_block(block, remote) .await @@ -388,6 +383,18 @@ impl HotstuffRunner { err })?; + let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); + self.update_max_quorum_round(quorum_round); + + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + + let prev_block = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err + }; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", self, block.block_id()); @@ -452,10 +459,19 @@ impl HotstuffRunner { block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, + remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = prev_block - .as_ref() - .map_or(None, |block| block.result_state_id().clone()); + let mut prev_state_id = match prev_block + .as_ref() { + Some(prev_block) => { + let result_state_id = block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; + } + result_state_id.clone() + }, + None => None + }; for proposal_exe_info in block.proposals() { // 去重 @@ -672,7 +688,7 @@ impl HotstuffRunner { err })?; - if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", self, header_block.block_id() @@ -696,29 +712,18 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(header_block.clone(), qc_block).await; + self.notify_block_committed(&header_block, &old_header_block, qc_block).await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", self, block.block_id() ); - let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self, self.round, err - ); - - err - }); - // notify by leader - if let Ok(leader) = leader { - if self.local_device_id == leader { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } + if &self.local_id == header_block.owner() { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; } log::debug!( @@ -733,7 +738,7 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, the qc of block {:?} has received before", self, block.block_id() ); - return self.process_block_qc(qc, block, remote).await; + return self.process_block_qc(qc, block).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( @@ -762,7 +767,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block, proposals).await { + if let Some(vote) = self.make_vote(block, proposals, &remote).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -791,22 +796,12 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - let mut pre_state_id = match new_header.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); + + let mut pre_state_id = old_header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); for proposal in new_header.proposals() { let proposal_obj = self @@ -900,6 +895,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_round(&mut self, quorum_round: u64) { + if quorum_round > self.max_quorum_round { + self.max_quorum_round = quorum_round; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -922,7 +923,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -930,6 +931,13 @@ impl HotstuffRunner { return None; } + if self.max_quorum_round >= self.round { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } + // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -1002,6 +1010,10 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + self, + block.block_id(), + ); return None; } @@ -1016,44 +1028,15 @@ impl HotstuffRunner { return None; } - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - match block.prev_block_id() { - Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await.map(|is_finished| (is_finished, &proposal_result.proposal)), - None => Ok((false, &proposal_result.proposal)) - } - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok((is_finished, proposal_id)) => { - if is_finished { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", - self, - block.block_id(), - proposal_id - ); - return None; - } - }, - Err(err) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", - self, - block.block_id(), - err - ); - return None; - }, - } + if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err + ); + return None; } - if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await.is_err() { - return None; - } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1075,7 +1058,12 @@ impl HotstuffRunner { } }; - if self.store.set_last_vote_round(block.round()).await.is_err() { + if let Err(err) = self.store.set_last_vote_round(block.round()).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for update last-vote-round failed {:?}", + self, + block.block_id(), + err + ); return None; } @@ -1086,23 +1074,39 @@ impl HotstuffRunner { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + block.block_id(), + block_timestamp, + now + ); + false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); + let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + block.block_id(), + block_timestamp, + prev_block_time + ); return false } } } for proposal in block.proposals() { - let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_id = proposal.proposal; + let proposal = proposals.get(&proposal_id).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + block.block_id(), + block_timestamp, + proposal_id, + proposal_timestamp + ); return false } } @@ -1174,7 +1178,7 @@ impl HotstuffRunner { if is_prev_none {"None"} else {"Some"} ); - self.process_block_qc(qc, &block, remote).await?; + self.process_block_qc(qc, &block).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1185,7 +1189,6 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, - remote: ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1334,7 +1337,10 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - + + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1453,6 +1459,9 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1501,8 +1510,7 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ) - .await.map_err(|err| { + ).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", self, err @@ -1541,7 +1549,13 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let prev_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), + Some(qc) => { + let prev_block = self.store.find_block_in_cache(&qc.block_id)?; + if let Some(result_state_id) = prev_block.result_state_id() { + self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + } + Some(prev_block) + }, None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1940,6 +1954,58 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } + async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 + let obj_map_processor = self.store.get_object_map_processor(); + + #[async_recursion::async_recursion] + async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if non_driver.get_object(&root_id, None).await.is_ok() { + // TODO: 可能有下级分支子树因为异常不齐全 + return Ok(()); + } + let obj = non_driver.get_object(root_id, Some(remote)).await?; + match obj.object.as_ref() { + Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { + let single_op_env = obj_map_processor.create_single_op_env().await?; + single_op_env.load(root_id).await?; + loop { + let branchs = single_op_env.next(16).await?; + for branch in branchs.list.iter() { + let branch_id = match branch { + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Map(map) => &map.1, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Set(set) => set, + }; + make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + } + + if branchs.list.len() < 16 { + return Ok(()) + } + } + }, + _ => return Ok(()) + } + } + + let mut result = Ok(()); + for remote in remotes { + result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + if result.is_ok() { + return result; + } + } + result + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 82f4017a0..f44260a04 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 1170176b2..77a652a7e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,7 +17,7 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; -pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(5000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 0a3544c09..790429c6c 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -154,6 +154,11 @@ impl DecStateRequestorRunner { .await .map(|r| r.cloned()); + log::debug!( + "handle_verifiable_state sub_path: {}, result: {:?}", + sub_path, + result + ); self.query_state_notifier.reply(&sub_path, result).await } Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cc0b4aff2..b1506a192 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -13,7 +13,7 @@ use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), - BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), // LastStateRequest(ObjectId), DelayBroadcast, } diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index 858c37fff..bfc9bc5d2 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -69,8 +69,25 @@ impl<'de> RawDecode<'de> for GroupRPathStatus { assert_eq!(remain.len(), 0); let mut status_map = HashMap::new(); for obj_buf in proto.status_list.iter() { - let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; - assert_eq!(remain.len(), 0); + log::debug!("will decode len: {}", obj_buf.len()); + // size + object_id + let status = if obj_buf.len() > OBJECT_ID_LEN + 1 { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status + } else if obj_buf.len() == OBJECT_ID_LEN + 1 { + NONObjectInfo::new( + ObjectId::clone_from_slice(&obj_buf.as_slice()[1..])?, + obj_buf.clone(), + None, + ) + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidData, + "expect NONObjectInfo", + )); + }; + status_map.insert(status.object_id, status); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 6c9f89e96..932e5cd46 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use itertools::Itertools; use sha2::Digest; use crate::GroupRPathStatus; @@ -185,12 +186,13 @@ impl std::fmt::Debug for HotstuffMessage { result.as_ref().map(|status| { let desc = status.block_desc.content(); format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ) }) ) @@ -315,12 +317,13 @@ impl std::fmt::Debug for HotstuffPackage { |status| { let desc = status.block_desc.content(); let ok = format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ); Ok(ok) } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index de5a0fd4a..60a45724f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -69,6 +69,10 @@ impl DecStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { Some(state) => state, None => return Ok(None), @@ -98,6 +102,8 @@ impl DecStorage { assert_eq!(remain.len(), 0); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 122ae72ab..966fa518a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, - ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, @@ -223,7 +223,13 @@ impl GroupStorage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - ) -> BuckyResult)>> { + ) -> BuckyResult< + Option<( + &GroupConsensusBlock, + Option, + Vec, + )>, + > { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); @@ -399,9 +405,10 @@ impl GroupStorage { } } - self.cache.header_block = Some(new_header); + let old_header_block = self.cache.header_block.replace(new_header); return Ok(Some(( self.cache.header_block.as_ref().unwrap(), + old_header_block, removed_blocks, ))); } @@ -736,6 +743,7 @@ impl GroupStorage { } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + // TODO: 需要一套通用的同步ObjectMap树的实现 let (header_block, qc) = match self.cache.header_block.as_ref() { Some(block) => { let (_, qc_block) = self @@ -778,6 +786,9 @@ impl GroupStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { @@ -806,6 +817,8 @@ impl GroupStorage { status_map.insert(parent_state_id, parent_state); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder @@ -821,7 +834,11 @@ impl GroupStorage { } } - let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + let leaf_state = if parent_state_id.is_data() { + NONObjectInfo::new(parent_state_id, parent_state_id.to_vec()?, None) + } else { + self.non_driver.get_object(&parent_state_id, None).await? + }; status_map.insert(parent_state_id, leaf_state); return Ok(GroupRPathStatus { diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 0053ccd5f..01094f12a 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -27,4 +27,5 @@ cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } -cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 394b15acb..618336df4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -14,7 +14,7 @@ use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; mod Common { use std::{fmt::format, io::ErrorKind, sync::Arc}; @@ -505,8 +505,15 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + use cyfs_group::{ + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, + }; + use cyfs_lib::{ + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, + }; use cyfs_stack::CyfsStack; + use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -522,10 +529,42 @@ mod GroupDecService { Box::new(GroupRPathDelegateFactory { local_name }), ) .await - .unwrap() + .unwrap(); + + // let source = RequestSourceInfo { + // protocol: todo!(), + // zone: todo!(), + // dec: todo!(), + // verified: todo!(), + // }; + + // cyfs_stack + // .router_handlers() + // .handlers(&RouterHandlerChain::PostRouter) + // .post_object() + // .add_handler(RouterHandler::new()); } } + // pub struct PostProposalRoutine { + // controller: RPathControl, + // } + + // #[async_trait::async_trait] + // impl EventListenerAsyncRoutine + // for PostProposalRoutine + // { + // async fn call( + // &self, + // param: &NONPostObjectInputRequest, + // ) -> BuckyResult { + // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // self.controller.push_proposal(proposal).await?; + // Ok(NONPostObjectInputResponse { object: None }) + // } + // } + pub struct GroupRPathDelegateFactory { local_name: String, } @@ -778,6 +817,16 @@ mod GroupDecService { .execute(proposal, pre_state_id, object_map_processor) .await?; + log::info!( + "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + execute_result.result_state_id, + execute_result.context.is_none(), + execute_result.receipt.is_none(), + result.result_state_id, + result.context.is_none(), + result.receipt.is_none() + ); + let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() && execute_result.receipt.is_none(); @@ -1007,7 +1056,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 1000usize; + let PROPOSAL_COUNT = 5usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1085,6 +1134,28 @@ async fn main_run() { log::info!("will push new proposals, i: {}", i); } } + + let client = admin_stacks + .get(0) + .unwrap() + .group_mgr() + .rpath_client( + &group.desc().object_id(), + dec_app_id.object_id(), + &EXAMPLE_RPATH, + ) + .await + .unwrap(); + + let value_obj = client + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .unwrap(); + let buf = value_obj.as_ref().unwrap().object_id.data(); + let mut value = [0u8; 8]; + value.copy_from_slice(&buf[..8]); + + log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From de8b47285624f86022cca474c6c3dee9dfc002ad Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 15:46:00 +0800 Subject: [PATCH 394/553] Fix: result-state verify failed --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++++++++++++++---- src/tests/group-example/src/main.rs | 3 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 10c5d9635..e142d4069 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -464,7 +464,7 @@ impl HotstuffRunner { let mut prev_state_id = match prev_block .as_ref() { Some(prev_block) => { - let result_state_id = block.result_state_id(); + let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; } @@ -520,14 +520,24 @@ impl HotstuffRunner { err })? { + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); + prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", self, proposal_exe_info.proposal, - prev_state_id, - proposal_exe_info.result_state + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); @@ -966,7 +976,7 @@ impl HotstuffRunner { let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block.clone()), + Ok(block) => Some(block), Err(_) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", self, @@ -1960,11 +1970,18 @@ impl HotstuffRunner { #[async_recursion::async_recursion] async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if root_id.is_data() { + return Ok(()); + } + if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await?; + let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { + log::warn!("get branch {} failed {:?}", root_id, err); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { let single_op_env = obj_map_processor.create_single_op_env().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 618336df4..4daa0d4f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -818,7 +818,8 @@ mod GroupDecService { .await?; log::info!( - "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + pre_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), From 5f4584fe0a2da41e7707ab578088475cbca64ebf Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 28 Feb 2023 20:27:49 +0800 Subject: [PATCH 395/553] Redefine the Group object for Permission --- .../protos/standard_objects-permission.proto | 203 ++++++++++++++++++ src/tests/group-example/src/main.rs | 8 +- 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto new file mode 100644 index 000000000..b2ec61f60 --- /dev/null +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -0,0 +1,203 @@ +syntax="proto3"; + +// contract +message ContractBodyContent { + bytes data = 1; +} + +// device +message DeviceBodyContent { + repeated bytes endpoints = 1; + repeated bytes sn_list = 2; + repeated bytes passive_pn_list = 3; + optional string name = 4; + optional uint32 bdt_version = 5; +} + +// dir +message DirBodyContent { + enum Type { + Chunk = 0; + ObjList = 1; + } + Type type = 1; + optional bytes chunk_id = 2; + + // 使用list编码hash_map + message ObjItem { + bytes obj_id = 1; + bytes value = 2; + } + repeated ObjItem obj_list = 3; +} + +// file +message ChunkList { + enum Type { + ChunkInList = 0; + ChunkInFile = 1; + ChunkInBundle = 2; + } + enum HashMethod { + Serial = 0; + } + + Type type = 1; + repeated bytes chunk_id_list = 2; + bytes file_id = 3; + optional HashMethod hash_method = 4; +} + +message FileBodyContent { + ChunkList chunk_list = 1; +} + +// people +message PeopleBodyContent { + repeated bytes ood_list = 1; + optional string name = 2; + optional bytes icon = 3; + optional string ood_work_mode = 4; +} + +message GroupRPathPermissionWeight { + string rpath = 1; + GroupFunctionPermissionWeight weight = 2; +} + +message GroupDecPermissionWeight { + bytes dec_id = 1; + optional GroupRPathPermissionWeight default_dec_weight = 2; + repeated GroupRPathPermissionWeight rpath_weight = 3; +} + +message GroupMember { + bytes id = 1; + string title = 2; + // uint64 shares = 3; delay + optional GroupGlobalPermissionWeight global_weight = 4; + optional GroupDecPermissionWeight weight = 5; +} + +/** +admin 修改管理员列表 +member 修改成员列表 +display-${scope} 修改展示信息 + ${scope}=g: 修改group信息 + ${scope}=s: 修改自身信息 + ${scope}=m: 修改任意member信息 + ${scope}=a: 修改任意admin信息 +property 修改资产信息 +conclusion 修改决议类别列表 +conclusion-${category} 修改决议类别配置 +it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) +c-${any} 其他自定义(custom)权限 +*/ + +message GroupGlobalPermissionWeight { + optional uint32 admin = 1; + optional uint32 member = 2; + optional uint32 display_group = 3; + optional uint32 display_self = 4; + optional uint32 display_member = 5; + optional uint32 display_admin = 6; + optional uint32 property = 7; +} + +message GroupCommonPermissionWeight { + string category = 1; + uint32 weight = 2; +} + +message GroupFunctionPermissionWeight { + optional uint32 it = 1; + optional uint32 conclusion = 2; + repeated GroupCommonPermissionWeight conclusion_category = 3; + repeated GroupCommonPermissionWeight custom = 4; +} + +message GroupITConfig { + repeated bytes ood_list = 8; + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms +} + +message GroupConclusionConfig { + string category = 1; + uint64 lifespan = 2; // ms +} + +message GroupConfigItem { + optional GroupITConfig it = 1; + repeated GroupConclusionConfig conclusions = 2; + optional GroupFunctionPermissionWeight weight_threshold = 3; +} + +message GroupRPathConfig { + string rpath = 1; + GroupConfigItem config = 2; +} + +message GroupDecConfig { + bytes dec_id = 1; + optional GroupConfigItem default_dec_config = 2; + repeated GroupRPathConfig rpath_configs = 3; +} + +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; + + repeated GroupMember members = 4; + + // uint64 total_equity = 5; // delay + + repeated bytes revoked_conclusions = 6; + + GroupConfigItem default_config = 7; + repeated GroupDecConfig dec_configs = 8; + + GroupGlobalPermissionWeight global_weight_threshold = 9; + GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + + uint64 version = 11; +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} + +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} + +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; +} + +// tx +message TxBodyContent { + bytes data = 1; +} + +// proof_of_service +message ProofData { + bytes data = 1; +} + +message ProofOfServiceBodyContent { + ProofData data = 1; +} \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 4daa0d4f1..ef2366de0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1051,13 +1051,13 @@ async fn main_run() { .unwrap(); } - async_std::task::sleep(Duration::from_millis(30000)).await; + async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 5usize; + let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1130,12 +1130,14 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } + async_std::task::sleep(Duration::from_millis(10000)).await; + let client = admin_stacks .get(0) .unwrap() From f3d3bafa89838e715c0f518d56d41cb109028116 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 14:41:55 +0800 Subject: [PATCH 396/553] Simplify group definition --- .../protos/standard_objects-permission.proto | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto index b2ec61f60..09f9e3684 100644 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -60,89 +60,9 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } -message GroupRPathPermissionWeight { - string rpath = 1; - GroupFunctionPermissionWeight weight = 2; -} - -message GroupDecPermissionWeight { - bytes dec_id = 1; - optional GroupRPathPermissionWeight default_dec_weight = 2; - repeated GroupRPathPermissionWeight rpath_weight = 3; -} - message GroupMember { bytes id = 1; string title = 2; - // uint64 shares = 3; delay - optional GroupGlobalPermissionWeight global_weight = 4; - optional GroupDecPermissionWeight weight = 5; -} - -/** -admin 修改管理员列表 -member 修改成员列表 -display-${scope} 修改展示信息 - ${scope}=g: 修改group信息 - ${scope}=s: 修改自身信息 - ${scope}=m: 修改任意member信息 - ${scope}=a: 修改任意admin信息 -property 修改资产信息 -conclusion 修改决议类别列表 -conclusion-${category} 修改决议类别配置 -it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) -c-${any} 其他自定义(custom)权限 -*/ - -message GroupGlobalPermissionWeight { - optional uint32 admin = 1; - optional uint32 member = 2; - optional uint32 display_group = 3; - optional uint32 display_self = 4; - optional uint32 display_member = 5; - optional uint32 display_admin = 6; - optional uint32 property = 7; -} - -message GroupCommonPermissionWeight { - string category = 1; - uint32 weight = 2; -} - -message GroupFunctionPermissionWeight { - optional uint32 it = 1; - optional uint32 conclusion = 2; - repeated GroupCommonPermissionWeight conclusion_category = 3; - repeated GroupCommonPermissionWeight custom = 4; -} - -message GroupITConfig { - repeated bytes ood_list = 8; - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms -} - -message GroupConclusionConfig { - string category = 1; - uint64 lifespan = 2; // ms -} - -message GroupConfigItem { - optional GroupITConfig it = 1; - repeated GroupConclusionConfig conclusions = 2; - optional GroupFunctionPermissionWeight weight_threshold = 3; -} - -message GroupRPathConfig { - string rpath = 1; - GroupConfigItem config = 2; -} - -message GroupDecConfig { - bytes dec_id = 1; - optional GroupConfigItem default_dec_config = 2; - repeated GroupRPathConfig rpath_configs = 3; } message CommonGroupBodyContent { @@ -152,17 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - // uint64 total_equity = 5; // delay - - repeated bytes revoked_conclusions = 6; - - GroupConfigItem default_config = 7; - repeated GroupDecConfig dec_configs = 8; - - GroupGlobalPermissionWeight global_weight_threshold = 9; - GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + repeated bytes ood_list = 5; - uint64 version = 11; + optional bytes prev_version = 6; + uint64 version_num = 7; } // simple_group @@ -184,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx From b942a2c88177273ee9c506d70ff4112da40d11a0 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 20:16:27 +0800 Subject: [PATCH 397/553] Move the interface to cyfs-lib --- .../src/consensus/hotstuff/hotstuff.rs | 8 +++--- .../cyfs-group/src/dec/group_manager.rs | 6 ++--- src/component/cyfs-group/src/dec/mod.rs | 6 ++--- .../cyfs-group/src/dec/rpath_control.rs | 3 ++- .../engine/storage_engine_group_state.rs | 6 ++--- .../cyfs-group/src/storage/group_storage.rs | 6 ++--- .../src/group}/delegate_factory.rs | 2 +- .../cyfs-lib/src/group/group_manager.rs | 20 ++++++++++++++ src/component/cyfs-lib/src/group/mod.rs | 7 +++++ .../cyfs-lib/src/group/rpath_client.rs | 27 +++++++++++++++++++ src/component/cyfs-lib/src/lib.rs | 6 +++-- src/tests/group-example/src/main.rs | 8 +++--- 12 files changed, 79 insertions(+), 26 deletions(-) rename src/component/{cyfs-group/src/dec => cyfs-lib/src/group}/delegate_factory.rs (98%) create mode 100644 src/component/cyfs-lib/src/group/group_manager.rs create mode 100644 src/component/cyfs-lib/src/group/mod.rs create mode 100644 src/component/cyfs-lib/src/group/rpath_client.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e142d4069..52dcdd650 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,15 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, + GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7b7fbbbe..60ddba1fb 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,11 +6,11 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; use crate::{ - storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, + NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index b4e753a27..8a43844b2 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,11 +1,9 @@ // dec framework -mod delegate_factory; +mod group_manager; mod rpath_client; mod rpath_control; -mod group_manager; -pub use delegate_factory::*; +pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 7abff1ec1..c3a25b060 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,10 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathDelegate, + PendingProposalHandler, PendingProposalMgr, }; struct RPathControlRaw { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 8b8799207..adf11c7e4 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,11 +6,11 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_lib::GroupObjectMapProcessor; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, - GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, - GROUP_STATE_PATH_RESULT_STATE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 966fa518a..fa6f4930f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,11 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-lib/src/group/delegate_factory.rs similarity index 98% rename from src/component/cyfs-group/src/dec/delegate_factory.rs rename to src/component/cyfs-lib/src/group/delegate_factory.rs index f5092dbfc..9e55ff8f4 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-lib/src/group/delegate_factory.rs @@ -1,8 +1,8 @@ +use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-lib/src/group/group_manager.rs new file mode 100644 index 000000000..7d836ae49 --- /dev/null +++ b/src/component/cyfs-lib/src/group/group_manager.rs @@ -0,0 +1,20 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +use crate::{DelegateFactory, RPathClient}; + +#[derive(Clone)] +pub struct GroupManager; + +impl GroupManager { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self) { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-lib/src/group/mod.rs new file mode 100644 index 000000000..482d9ea0d --- /dev/null +++ b/src/component/cyfs-lib/src/group/mod.rs @@ -0,0 +1,7 @@ +mod delegate_factory; +mod group_manager; +mod rpath_client; + +pub use delegate_factory::*; +pub use group_manager::*; +pub use rpath_client::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-lib/src/group/rpath_client.rs new file mode 100644 index 000000000..4162abe68 --- /dev/null +++ b/src/component/cyfs-lib/src/group/rpath_client.rs @@ -0,0 +1,27 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{GroupProposal, GroupRPath}; + +use crate::NONObjectInfo; + +struct RPathClientRaw {} + +#[derive(Clone)] +pub struct RPathClient(Arc); + +impl RPathClient { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index f74e62985..d2f02315a 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,9 +4,11 @@ mod base; mod crypto; mod default_app; mod events; +mod group; mod ndn; mod non; mod prelude; +mod requestor; mod rmeta; mod root_state; mod router_handler; @@ -17,7 +19,6 @@ mod trans; mod util; mod ws; mod zone; -mod requestor; pub use crate::util::*; pub use acl::*; @@ -26,9 +27,11 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; +pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; +pub use requestor::*; pub use rmeta::*; pub use root_state::*; pub use router_handler::*; @@ -38,7 +41,6 @@ pub use sync::*; pub use trans::*; pub use ws::*; pub use zone::*; -pub use requestor::*; // 重新导出cache相关接口,由于bdt层的依赖关系,只能放在util工程 pub use cyfs_util::cache::*; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ef2366de0..42544e51c 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,12 +505,10 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, - }; + use cyfs_group::RPathControl; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, + NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, }; use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; From bb57a77c8308b8143b912cc61ef193852af80d8e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 12:20:30 +0800 Subject: [PATCH 398/553] Remove the `decide` from proposal, It seems unuseful --- .../cyfs-core/protos/core_objects.proto | 9 +- .../cyfs-core/src/group/group_proposal.rs | 415 +++++++++--------- src/component/cyfs-core/src/group/mod.rs | 10 +- 3 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 487ece4bd..abd299e9d 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -352,7 +352,7 @@ message GroupProposalDescContent { message GroupProposalBodyContent { optional bytes payload = 1; - +/* message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; @@ -360,8 +360,10 @@ message GroupProposalBodyContent { } repeated Signature decide_signatures = 2; +*/ } +/* message GroupUpdateGroupPropsalParam { repeated bytes target_dec_id = 1; // the proccesor decs optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) @@ -373,6 +375,7 @@ message GroupPropsalDecideParam { bytes proposal_id = 2; bytes decide = 3; } +*/ message HotstuffBlockQc { bytes block_id = 1; @@ -431,6 +434,7 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } +/* message GroupActionDescContent { // target GroupRPath r_path = 1; @@ -441,4 +445,5 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 10aeed798..bf28aafb2 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,4 +1,4 @@ -use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; +use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use sha2::Digest; @@ -34,45 +34,44 @@ impl DescContent for GroupProposalDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone)] -pub struct GroupProposalSignature { - signature: Signature, - proponent_id: ObjectId, - decide: Vec, -} - -impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> - for GroupProposalSignature -{ - fn transform( - value: &crate::codec::protos::group_proposal_body_content::Signature, - ) -> BuckyResult { - Ok(Self { - signature: Signature::raw_decode(value.signature.as_slice())?.0, - proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, - decide: value.decide.clone(), - }) - } -} - -impl ProtobufTransform<&GroupProposalSignature> - for crate::codec::protos::group_proposal_body_content::Signature -{ - fn transform(value: &GroupProposalSignature) -> BuckyResult { - Ok(Self { - signature: value.signature.to_vec()?, - proponent_id: value.proponent_id.to_vec()?, - decide: value.decide.clone(), - }) - } -} +// #[derive(Clone)] +// pub struct GroupProposalSignature { +// signature: Signature, +// proponent_id: ObjectId, +// decide: Vec, +// } + +// impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> +// for GroupProposalSignature +// { +// fn transform( +// value: &crate::codec::protos::group_proposal_body_content::Signature, +// ) -> BuckyResult { +// Ok(Self { +// signature: Signature::raw_decode(value.signature.as_slice())?.0, +// proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, +// decide: value.decide.clone(), +// }) +// } +// } + +// impl ProtobufTransform<&GroupProposalSignature> +// for crate::codec::protos::group_proposal_body_content::Signature +// { +// fn transform(value: &GroupProposalSignature) -> BuckyResult { +// Ok(Self { +// signature: value.signature.to_vec()?, +// proponent_id: value.proponent_id.to_vec()?, +// decide: value.decide.clone(), +// }) +// } +// } #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] pub struct GroupProposalBodyContent { payload: Option>, - - decide_signatures: Vec, + // decide_signatures: Vec, } impl BodyContent for GroupProposalBodyContent { @@ -85,14 +84,14 @@ impl ProtobufTransform for GroupProposalBodyContent { fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push(GroupProposalSignature::transform(sign)?); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push(GroupProposalSignature::transform(sign)?); + // } Ok(Self { payload: value.payload, - decide_signatures, + // decide_signatures, }) } } @@ -101,16 +100,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> for crate::codec::protos::GroupProposalBodyContent { fn transform(value: &GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push( - crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, - ); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push( + // crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + // ); + // } Ok(Self { payload: value.payload.clone(), - decide_signatures, + // decide_signatures, }) } } @@ -143,17 +142,17 @@ impl GroupProposalDescContent { } impl GroupProposalBodyContent { - fn hash_decide_signature( - proposal_id: &ObjectId, - proponent_id: &ObjectId, - decide: &[u8], - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(proposal_id.as_slice()); - sha256.input(proponent_id.as_slice()); - sha256.input(decide); - sha256.result().into() - } + // fn hash_decide_signature( + // proposal_id: &ObjectId, + // proponent_id: &ObjectId, + // decide: &[u8], + // ) -> HashValue { + // let mut sha256 = sha2::Sha256::new(); + // sha256.input(proposal_id.as_slice()); + // sha256.input(proponent_id.as_slice()); + // sha256.input(decide); + // sha256.result().into() + // } } #[async_trait] @@ -182,27 +181,27 @@ pub trait GroupProposalObject { fn payload(&self) -> &Option>; fn set_payload(&mut self, payload: Option>); - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult>; - - fn decided_members_no_verify(&self) -> &Vec; - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult; - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()>; + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult>; + + // fn decided_members_no_verify(&self) -> &Vec; + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult; + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()>; } #[async_trait] @@ -231,7 +230,7 @@ impl GroupProposalObject for GroupProposal { desc, GroupProposalBodyContent { payload, - decide_signatures: vec![], + // decide_signatures: vec![], }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) @@ -252,9 +251,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { - Some(params) => { - HashValue::try_from(params.as_slice()).map(|h| Some(h)) - } + Some(params) => HashValue::try_from(params.as_slice()).map(|h| Some(h)), None => Ok(None), } } @@ -298,134 +295,130 @@ impl GroupProposalObject for GroupProposal { self.body_mut().as_mut().unwrap().content_mut().payload = payload; } - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult> { - let signs = self - .body() - .as_ref() - .unwrap() - .content() - .decide_signatures - .as_slice(); - - let proposal_id = self.desc().object_id(); - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - - let mut decides = vec![]; - - for sign in signs { - if &sign.proponent_id == member_id { - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &sign.proponent_id, - sign.decide.as_slice(), - ); - - if verifier.verify(hash.as_slice(), &sign.signature).await { - decides.push(sign.decide.as_slice()); - } else { - return Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )); - } - } - } - - Ok(decides) - } - - fn decided_members_no_verify(&self) -> &Vec { - &self.body().as_ref().unwrap().content().decide_signatures - } - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult { - let signs = &self.body().as_ref().unwrap().content().decide_signatures; - - if signs.iter().find(|s| s.proponent_id == member_id).is_some() { - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicated decide", - )); - } - - let proposal_id = self.desc().object_id(); - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.as_slice(), - ); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - let sign = signer - .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) - .await?; - - Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) - } - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()> { - let proposal_id = self.desc().object_id(); - - if decide.proposal_id() != &proposal_id { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - format!( - "proposal id not match for decide signature: {}/{}", - proposal_id, - decide.proposal_id() - ), - )); - } - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.decide(), - ); - - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - if verifier.verify(hash.as_slice(), decide.signature()).await { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - for exist in signs.iter() { - if &exist.proponent_id == &member_id && exist.decide == decide.decide() { - return Ok(()); - } - } - - signs.push(GroupProposalSignature { - signature: decide.signature().clone(), - proponent_id: member_id, - decide: Vec::from(decide.decide()), - }); - - Ok(()) - } else { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )) - } - } + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult> { + // let signs = self + // .body() + // .as_ref() + // .unwrap() + // .content() + // .decide_signatures + // .as_slice(); + + // let proposal_id = self.desc().object_id(); + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + // let mut decides = vec![]; + + // for sign in signs { + // if &sign.proponent_id == member_id { + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &sign.proponent_id, + // sign.decide.as_slice(), + // ); + + // if verifier.verify(hash.as_slice(), &sign.signature).await { + // decides.push(sign.decide.as_slice()); + // } else { + // return Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )); + // } + // } + // } + + // Ok(decides) + // } + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult { + // let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + // if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + // return Err(BuckyError::new( + // BuckyErrorCode::AlreadyExists, + // "duplicated decide", + // )); + // } + + // let proposal_id = self.desc().object_id(); + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.as_slice(), + // ); + + // let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + // let sign = signer + // .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + // .await?; + + // Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) + // } + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()> { + // let proposal_id = self.desc().object_id(); + + // if decide.proposal_id() != &proposal_id { + // return Err(BuckyError::new( + // BuckyErrorCode::NotMatch, + // format!( + // "proposal id not match for decide signature: {}/{}", + // proposal_id, + // decide.proposal_id() + // ), + // )); + // } + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.decide(), + // ); + + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + // if verifier.verify(hash.as_slice(), decide.signature()).await { + // let signs = &mut self + // .body_mut() + // .as_mut() + // .unwrap() + // .content_mut() + // .decide_signatures; + // for exist in signs.iter() { + // if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + // return Ok(()); + // } + // } + + // signs.push(GroupProposalSignature { + // signature: decide.signature().clone(), + // proponent_id: member_id, + // decide: Vec::from(decide.decide()), + // }); + + // Ok(()) + // } else { + // Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )) + // } + // } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b2885d637..4310f48a5 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,13 +1,15 @@ mod group_consensus_block; mod group_proposal; -mod group_proposal_decide_param; +// mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_update_group_proposal_param; +// mod group_update_group_proposal_param; +mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; -pub use group_proposal_decide_param::*; +// pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_update_group_proposal_param::*; +// pub use group_update_group_proposal_param::*; +pub use group_protocol::*; From 472aabd5507b3297ce27173973bc3794ad603bac Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 20:52:45 +0800 Subject: [PATCH 399/553] Prepare for export interface to SDK --- .../cyfs-core/protos/core_objects.proto | 2 +- src/component/cyfs-core/src/coreobj.rs | 1 + src/component/cyfs-core/src/group/mod.rs | 2 - src/component/cyfs-group-lib/Cargo.toml | 34 ++ .../{cyfs-group => cyfs-group-lib}/build.rs | 27 +- .../protos/group_bft_protocol.proto | 63 +++ src/component/cyfs-group-lib/readme.md | 14 + .../src/delegate.rs} | 18 +- .../src}/group_manager.rs | 6 +- .../mod.rs => cyfs-group-lib/src/lib.rs} | 6 +- .../cyfs-group-lib/src/objects/certificate.rs | 190 ++++++++ .../cyfs-group-lib/src/objects/codec/mod.rs | 3 + .../src/objects/group_command.rs | 428 ++++++++++++++++++ .../src/objects/group_decide_proposal.rs | 0 .../src/objects/group_rpath_status.rs | 6 +- .../src/objects/group_update_proposal.rs | 0 .../cyfs-group-lib/src/objects/mod.rs | 12 + .../src}/rpath_client.rs | 3 +- src/component/cyfs-group/Cargo.toml | 3 +- .../protos/group_bft_protocol.proto | 23 - .../src/consensus/hotstuff/hotstuff.rs | 60 +-- .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 7 +- .../cyfs-group/src/dec/group_events.rs | 42 ++ .../cyfs-group/src/dec/group_manager.rs | 94 ++-- src/component/cyfs-group/src/dec/mod.rs | 2 + .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec/rpath_control.rs | 8 +- .../src/dec_state/dec_state_requestor.rs | 6 +- .../src/dec_state/dec_state_synchronizer.rs | 64 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/helper/mod.rs | 2 - src/component/cyfs-group/src/helper/verify.rs | 16 - src/component/cyfs-group/src/lib.rs | 4 - src/component/cyfs-group/src/network/mod.rs | 2 + .../src/{objects => network}/protocol.rs | 306 +++---------- src/component/cyfs-group/src/objects/mod.rs | 9 - .../cyfs-group/src/storage/dec_storage.rs | 9 +- .../engine/storage_engine_group_state.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 7 +- src/component/cyfs-group/src/utils.rs | 8 - src/component/cyfs-lib/src/lib.rs | 2 - 42 files changed, 977 insertions(+), 529 deletions(-) create mode 100644 src/component/cyfs-group-lib/Cargo.toml rename src/component/{cyfs-group => cyfs-group-lib}/build.rs (66%) create mode 100644 src/component/cyfs-group-lib/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group-lib/readme.md rename src/component/{cyfs-lib/src/group/delegate_factory.rs => cyfs-group-lib/src/delegate.rs} (81%) rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/group_manager.rs (100%) rename src/component/{cyfs-lib/src/group/mod.rs => cyfs-group-lib/src/lib.rs} (56%) create mode 100644 src/component/cyfs-group-lib/src/objects/certificate.rs create mode 100644 src/component/cyfs-group-lib/src/objects/codec/mod.rs create mode 100644 src/component/cyfs-group-lib/src/objects/group_command.rs rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_decide_proposal.rs (100%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_rpath_status.rs (93%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_update_proposal.rs (100%) create mode 100644 src/component/cyfs-group-lib/src/objects/mod.rs rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/rpath_client.rs (94%) delete mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group/src/dec/group_events.rs delete mode 100644 src/component/cyfs-group/src/helper/verify.rs rename src/component/cyfs-group/src/{objects => network}/protocol.rs (70%) delete mode 100644 src/component/cyfs-group/src/objects/mod.rs delete mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index abd299e9d..742c14904 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -446,4 +446,4 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; } -*/ \ No newline at end of file +*/ diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3d53a082f..8eb96a930 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupAction = 704, GroupQuorumCertificate = 705, + GroupCommand = 706, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4310f48a5..d7134a3c0 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,7 +4,6 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; @@ -12,4 +11,3 @@ pub use group_proposal::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; -pub use group_protocol::*; diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml new file mode 100644 index 000000000..e7cfda851 --- /dev/null +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -0,0 +1,34 @@ + +[package] +name = 'cyfs-group-lib' +version = '0.1.1' +authors = ['zhangzhen '] +edition = '2021' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +prost-build = { version = '0.9.0' } +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +itertools = "0.10.3" +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group-lib/build.rs similarity index 66% rename from src/component/cyfs-group/build.rs rename to src/component/cyfs-group-lib/build.rs index 8d4efe9c9..206d6bc6f 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group-lib/build.rs @@ -37,28 +37,13 @@ fn gen_protos() { } fn main() { - println!("cargo:rerun-if-env-changed=VERSION"); - println!("cargo:rerun-if-env-changed=CHANNEL"); - println!("cargo:rerun-if-env-changed=TARGET"); - println!( - "cargo:rustc-env=VERSION={}", - std::env::var("VERSION").unwrap_or("0".to_owned()) - ); - println!( - "cargo:rustc-env=CHANNEL={}", - std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) - ); - println!( - "cargo:rustc-env=TARGET={}", - std::env::var("TARGET").unwrap() - ); - + println!("cargo:rerun-if-changed=protos"); println!( - "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + "cargo:warning={}", + format!( + "cyfs-core run build script, OUT_DIR={}", + std::env::var("OUT_DIR").unwrap() + ) ); - - println!("cargo:rerun-if-changed=protos"); - gen_protos(); } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto new file mode 100644 index 000000000..2bfdd8d21 --- /dev/null +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -0,0 +1,63 @@ + +syntax = "proto3"; + +message HotstuffBlockQCVote { + bytes block_id = 1; + optional bytes prev_block_id = 2; + uint64 round = 3; + bytes voter = 4; + bytes signature = 5; +} + +message HotstuffTimeoutVote { + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; +} + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} + +// GroupCommand + +message GroupCommandDescContent { + +} + +message GroupCommandNewRPath { + bytes group_id = 1; + string rpath = 2; + optional bytes with_block = 3; // Block.to_vec() +} + +message GroupCommandExecute { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId +} + +message GroupCommandExecuteResult { + optional bytes result_state_id = 1; // ObjectId + optional bytes receipt = 2; // NONObjectInfo.to_vec() + optional bytes context = 3; // Vec +} + +message GroupCommandVerify { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec +} + +message GroupCommandCommited { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec + bytes block = 6; // Block.to_vec() +} diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group-lib/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-lib/src/group/delegate_factory.rs b/src/component/cyfs-group-lib/src/delegate.rs similarity index 81% rename from src/component/cyfs-lib/src/group/delegate_factory.rs rename to src/component/cyfs-group-lib/src/delegate.rs index 9e55ff8f4..21b1e6346 100644 --- a/src/component/cyfs-lib/src/group/delegate_factory.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,25 +1,17 @@ -use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult>; - - async fn on_state_changed( &self, group_id: &ObjectId, rpath: &str, - state_id: Option, - pre_state_id: Option, - ); + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()>; } pub struct ExecuteResult { @@ -30,8 +22,6 @@ pub struct ExecuteResult { #[async_trait::async_trait] pub trait RPathDelegate: Sync + Send { - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; - async fn on_execute( &self, proposal: &GroupProposal, @@ -45,7 +35,7 @@ pub trait RPathDelegate: Sync + Send { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult; + ) -> BuckyResult<()>; async fn on_commited( &self, diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs similarity index 100% rename from src/component/cyfs-lib/src/group/group_manager.rs rename to src/component/cyfs-group-lib/src/group_manager.rs index 7d836ae49..8c82bc9e1 100644 --- a/src/component/cyfs-lib/src/group/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -6,15 +6,15 @@ use crate::{DelegateFactory, RPathClient}; pub struct GroupManager; impl GroupManager { - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { unimplemented!() } - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn unregister(&self) { unimplemented!() } } diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-group-lib/src/lib.rs similarity index 56% rename from src/component/cyfs-lib/src/group/mod.rs rename to src/component/cyfs-group-lib/src/lib.rs index 482d9ea0d..199307bcc 100644 --- a/src/component/cyfs-lib/src/group/mod.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,7 +1,9 @@ -mod delegate_factory; +mod delegate; mod group_manager; +mod objects; mod rpath_client; -pub use delegate_factory::*; +pub use delegate::*; pub use group_manager::*; +pub use objects::*; pub use rpath_client::*; diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs new file mode 100644 index 000000000..32b1b53c8 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -0,0 +1,190 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, HashValue, ObjectId, ObjectLink, ProtobufDecode, + ProtobufEncode, ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, + RawEncodePurpose, RsaCPUObjectSigner, Signature, SignatureSource, Signer, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffBlockQcVote)] +pub struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub prev_block_id: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.block_id().object_id(); + let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let signature = signer + .sign( + hash.as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + block_id: block_id.clone(), + round, + voter: local_device_id, + signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) + } + + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: super::codec::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for super::codec::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffTimeoutVote)] +pub struct HotstuffTimeoutVote { + pub high_qc: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: Option, + round: u64, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_device_id, + signature, + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + } + + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: super::codec::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffTimeoutVote { + high_qc: match value.high_qc.as_ref() { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} diff --git a/src/component/cyfs-group-lib/src/objects/codec/mod.rs b/src/component/cyfs-group-lib/src/objects/codec/mod.rs new file mode 100644 index 000000000..66df9053f --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/codec/mod.rs @@ -0,0 +1,3 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs new file mode 100644 index 000000000..912ced438 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -0,0 +1,428 @@ +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, NamedObjType, NamedObject, + NamedObjectBase, NamedObjectBuilder, NamedObjectId, ObjectId, ProtobufDecode, ProtobufEncode, + ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, RawEncode, RawEncodePurpose, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, +}; + +use cyfs_core::{CoreObjectType, GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandDescContent)] +pub struct GroupCommandDescContent {} + +impl DescContent for GroupCommandDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupCommand as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupCommandDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Debug)] +pub enum GroupCommandType { + NewRPath, + Execute, + ExecuteResult, + Verify, + Commited, +} + +#[derive(Clone, RawEncode, RawDecode)] +pub enum GroupCommandBodyContent { + NewRPath(GroupCommandNewRPath), + Execute(GroupCommandExecute), + ExecuteResult(GroupCommandExecuteResult), + Verify(GroupCommandVerify), + Commited(GroupCommandCommited), +} + +pub type GroupCommandObjectType = NamedObjType; +pub type GroupCommandBuilder = NamedObjectBuilder; + +pub type GroupCommandId = NamedObjectId; +pub type GroupCommand = NamedObjectBase; + +impl GroupCommandBodyContent { + pub fn cmd_type(&self) -> GroupCommandType { + match self { + GroupCommandBodyContent::NewRPath(_) => GroupCommandType::NewRPath, + GroupCommandBodyContent::Execute(_) => GroupCommandType::Execute, + GroupCommandBodyContent::ExecuteResult(_) => GroupCommandType::ExecuteResult, + GroupCommandBodyContent::Verify(_) => GroupCommandType::Verify, + GroupCommandBodyContent::Commited(_) => GroupCommandType::Commited, + } + } +} + +pub trait GroupCommandObject { + fn cmd_type(&self) -> GroupCommandType; + fn into_cmd(self) -> GroupCommandBodyContent; +} + +impl GroupCommandObject for GroupCommand { + fn cmd_type(&self) -> GroupCommandType { + self.body().as_ref().unwrap().content().cmd_type() + } + + fn into_cmd(self) -> GroupCommandBodyContent { + self.into_body().unwrap().into_content() + } +} + +impl BodyContent for GroupCommandBodyContent { + fn version(&self) -> u8 { + 0 + } + + fn format(&self) -> u8 { + cyfs_base::OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupCommandBodyContent") + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandNewRPath)] +pub struct GroupCommandNewRPath { + pub group_id: ObjectId, + pub rpath: String, + pub with_block: Option, +} + +impl ProtobufTransform for GroupCommandNewRPath { + fn transform(value: super::codec::protos::GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: ObjectId::raw_decode(value.group_id.as_slice())?.0, + with_block: match value.with_block.as_ref() { + Some(buf) => Some(GroupConsensusBlock::raw_decode(buf.as_slice())?.0), + None => None, + }, + rpath: value.rpath, + }) + } +} + +impl ProtobufTransform<&GroupCommandNewRPath> for super::codec::protos::GroupCommandNewRPath { + fn transform(value: &GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: value.group_id.to_vec()?, + rpath: value.rpath.clone(), + with_block: match value.with_block.as_ref() { + Some(block) => Some(block.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecute)] +pub struct GroupCommandExecute { + pub proposal: GroupProposal, + pub prev_state_id: Option, +} + +impl ProtobufTransform for GroupCommandExecute { + fn transform(value: super::codec::protos::GroupCommandExecute) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecute> for super::codec::protos::GroupCommandExecute { + fn transform(value: &GroupCommandExecute) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecuteResult)] +pub struct GroupCommandExecuteResult { + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform + for GroupCommandExecuteResult +{ + fn transform(value: super::codec::protos::GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecuteResult> + for super::codec::protos::GroupCommandExecuteResult +{ + fn transform(value: &GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandVerify)] +pub struct GroupCommandVerify { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform for GroupCommandVerify { + fn transform(value: super::codec::protos::GroupCommandVerify) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + receipt: match value.receipt { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupCommandVerify { + fn transform(value: &GroupCommandVerify) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] +pub struct GroupCommandCommited { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, + pub block: GroupConsensusBlock, +} + +impl ProtobufTransform for GroupCommandCommited { + fn transform(value: super::codec::protos::GroupCommandCommited) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, + }, + block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { + fn transform(value: &GroupCommandCommited) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + block: value.block.to_vec()?, + }) + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandNewRPath) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::NewRPath(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecute) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Execute(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecuteResult) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::ExecuteResult(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandVerify) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Verify(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandCommited) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Commited(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::NewRPath(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect NewRPath", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Execute(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Execute", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::ExecuteResult(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect ExecuteResult", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Verify(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Verify", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Commited(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Commited", cmd_type), + )), + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_decide_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs similarity index 93% rename from src/component/cyfs-group/src/objects/group_rpath_status.rs rename to src/component/cyfs-group-lib/src/objects/group_rpath_status.rs index bfc9bc5d2..ae656b5ad 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs @@ -21,7 +21,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -42,7 +42,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -56,7 +56,7 @@ impl RawEncode for GroupRPathStatus { impl<'de> RawDecode<'de> for GroupRPathStatus { fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let proto = super::codec::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::Failed, msg) diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_update_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_update_proposal.rs diff --git a/src/component/cyfs-group-lib/src/objects/mod.rs b/src/component/cyfs-group-lib/src/objects/mod.rs new file mode 100644 index 000000000..668afe8cf --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/mod.rs @@ -0,0 +1,12 @@ +mod group_command; +// mod group_decide_proposal; +mod group_rpath_status; +// mod group_update_proposal; +mod certificate; +mod codec; + +pub use group_command::*; +// pub use group_decide_proposal::*; +pub use group_rpath_status::*; +// pub use group_update_proposal::*; +pub use certificate::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs similarity index 94% rename from src/component/cyfs-lib/src/group/rpath_client.rs rename to src/component/cyfs-group-lib/src/rpath_client.rs index 4162abe68..2fea6dcf7 100644 --- a/src/component/cyfs-lib/src/group/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -5,8 +5,7 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupProposal, GroupRPath}; - -use crate::NONObjectInfo; +use cyfs_lib::NONObjectInfo; struct RPathClientRaw {} diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 4a7aae6c2..1caf5b9a4 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,5 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto deleted file mode 100644 index 621186522..000000000 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ /dev/null @@ -1,23 +0,0 @@ - -syntax = "proto3"; - -message HotstuffBlockQCVote { - bytes block_id = 1; - optional bytes prev_block_id = 2; - uint64 round = 3; - bytes voter = 4; - bytes signature = 5; -} - -message HotstuffTimeoutVote { - optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) - uint64 round = 2; - bytes voter = 3; - bytes signature = 4; -} - -message GroupRPathStatus { - bytes block_desc = 1; // GroupConsensusBlockDescContent - bytes certificate = 2; // HotstuffBlockQC for block - repeated bytes status_list = 4; // Array> -} \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52dcdd650..cc555298b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,16 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; +use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, }; /** @@ -51,7 +52,7 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -81,7 +82,7 @@ impl Hotstuff { rx_message, proposal_consumer, state_pusher_runner, - delegate, + event_notifier, rpath2, ) .run() @@ -224,7 +225,7 @@ struct HotstuffRunner { tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, synchronizer: Synchronizer, rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, @@ -251,7 +252,7 @@ impl HotstuffRunner { rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, state_pusher: StatePusher, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); @@ -307,7 +308,7 @@ impl HotstuffRunner { network_sender, tx_message, rx_message, - delegate, + event_notifier, synchronizer, non_driver, rpath, @@ -511,37 +512,25 @@ impl HotstuffRunner { context: proposal_exe_info.context.clone(), }; - if self - .delegate - .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) + self + .event_notifier + .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); err - })? - { - log::debug!( - "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + })?; - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); - return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); - } + prev_state_id = proposal_exe_info.result_state; } assert_eq!( @@ -840,11 +829,10 @@ impl HotstuffRunner { None => None, }; - self.delegate + self.event_notifier .on_commited( &proposal_obj, pre_state_id, - self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1625,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { + match self.event_notifier.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ad3a21e35..398274723 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -14,9 +14,10 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::network::NONDriverHelper; #[derive(Clone)] pub(crate) struct Committee { diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index f44260a04..6a9735a7f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,13 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, -}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, HotstuffTimeout, HotstuffTimeoutSign, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::Committee; pub(crate) struct VoteMgr { committee: Committee, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs new file mode 100644 index 000000000..67f79cfdd --- /dev/null +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -0,0 +1,42 @@ +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_group_lib::ExecuteResult; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone)] +pub(crate) struct RPathEventNotifier {} + +impl RPathEventNotifier { + pub fn new() -> Self { + unimplemented!() + } + + pub async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 60ddba1fb..95bdbcd17 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,15 +2,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, - NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, + RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -22,7 +22,6 @@ type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - delegate_by_dec: HashMap>, control_by_group: ControlByGroup, client_by_group: ClientByGroup, } @@ -33,6 +32,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,12 +54,12 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { control_by_group: ControlByGroup::default(), client_by_group: ClientByGroup::default(), - delegate_by_dec: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -69,29 +69,12 @@ impl GroupManager { Ok(mgr) } - pub async fn register( - &self, - dec_id: DecAppId, - delegate_factory: Box, - ) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec - .insert(dec_id.object_id().clone(), delegate_factory); - Ok(()) - } - - pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec.remove(dec_id.object_id()); - Ok(()) - } - pub async fn find_rpath_control( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -204,7 +187,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, Some(&block), Some(&remote), ) @@ -220,7 +203,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -236,7 +219,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -252,7 +235,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -268,7 +251,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -284,7 +267,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -331,7 +314,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::No, + false, None, Some(&remote), ) @@ -378,7 +361,7 @@ impl GroupManager { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -398,7 +381,6 @@ impl GroupManager { { // write - let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); @@ -411,6 +393,7 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -424,40 +407,25 @@ impl GroupManager { let store = match store { Ok(store) => Some(store), Err(e) => { - if let IsCreateRPath::No = is_auto_create { - return Err(e); - } if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - None + + self.on_new_rpath_request(group_id, dec_id, rpath, block) + .await?; + + if !is_auto_create { + return Err(e); + } else { + None + } } else { return Err(e); } } }; - // TODO: query group - let group = non_driver - .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) - .await?; - let mut raw = self.write().await; - let delegate = { - let delegate_factory = raw.delegate_by_dec.get(dec_id); - if delegate_factory.is_none() { - return Err(BuckyError::new( - BuckyErrorCode::DecNotRunning, - "dec not running for the rpath-control", - )); - } - let delegate_factory = delegate_factory.unwrap(); - - delegate_factory - .create_rpath_delegate(&group, rpath, block) - .await? - }; - let store = match store { Some(store) => store, None => { @@ -489,7 +457,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - Arc::new(delegate), + event_notifier, network_sender, non_driver, store, @@ -501,4 +469,14 @@ impl GroupManager { } } } + + async fn on_new_rpath_request( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 8a43844b2..2ad717514 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,9 +1,11 @@ // dec framework +mod group_events; mod group_manager; mod rpath_client; mod rpath_control; +pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 8a1dd34a7..08be0f5a0 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -224,10 +224,10 @@ impl RPathClient { HotstuffMessage::Timeout(tc) => unreachable!(), HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), HotstuffMessage::LastStateRequest => unreachable!(), - HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffMessage::StateChangeNotify(header_block, qc) => { self.0 .state_sync - .on_state_change(header_block, qc_block, remote) + .on_state_change(header_block, qc, remote) .await } HotstuffMessage::ProposalResult(proposal_id, result) => { diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c3a25b060..593d82db4 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::RPathDelegate; +use cyfs_group_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, + PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; struct RPathControlRaw { @@ -26,7 +26,7 @@ impl RPathControl { local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, - delegate: Arc>, + event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, store: GroupStorage, @@ -46,7 +46,7 @@ impl RPathControl { network_sender.clone(), non_driver, pending_proposal_consumer, - delegate, + event_notifier, rpath.clone(), ); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 790429c6c..8fd67496b 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,13 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, - CHANNEL_CAPACITY, -}; +use crate::{storage::DecStorage, Committee, HotstuffMessage, CHANNEL_CAPACITY}; use super::{CallReplyNotifier, CallReplyWaiter}; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 7272b3882..e019db892 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -2,15 +2,12 @@ use std::{collections::HashSet, sync::Arc}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, -}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, Committee, CHANNEL_CAPACITY, @@ -21,13 +18,9 @@ use super::{CallReplyNotifier, CallReplyWaiter}; enum DecStateSynchronizerMessage { ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, ), - StateChange(GroupConsensusBlock, GroupConsensusBlock), + StateChange(GroupConsensusBlock, HotstuffBlockQC), DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } @@ -81,11 +74,7 @@ impl DecStateSynchronizer { pub async fn on_proposal_complete( &self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { self.0 @@ -100,13 +89,13 @@ impl DecStateSynchronizer { pub async fn on_state_change( &self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { self.0 .tx_dec_state_sync_message .send(( - DecStateSynchronizerMessage::StateChange(header_block, qc_block), + DecStateSynchronizerMessage::StateChange(header_block, qc), remote, )) .await; @@ -121,7 +110,7 @@ struct DecStateSynchronizerCache { struct UpdateNotifyInfo { header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remotes: HashSet, group_chunk_id: ObjectId, group: Group, @@ -178,15 +167,11 @@ impl DecStateSynchronizerRunner { async fn handle_proposal_complete( &mut self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { match result { - Ok((result, header_block, qc_block)) => { + Ok((result, header_block, qc)) => { if header_block .proposals() .iter() @@ -200,7 +185,7 @@ impl DecStateSynchronizerRunner { } if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_err() { @@ -226,11 +211,11 @@ impl DecStateSynchronizerRunner { async fn handle_state_change( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_ok() { @@ -251,11 +236,7 @@ impl DecStateSynchronizerRunner { for remote in notify_info.remotes.iter() { match self .store - .sync( - ¬ify_info.header_block, - ¬ify_info.qc_block, - remote.clone(), - ) + .sync(¬ify_info.header_block, ¬ify_info.qc, remote.clone()) .await { Ok(_) => { @@ -264,7 +245,7 @@ impl DecStateSynchronizerRunner { state_cache: DecStorageCache { state: notify_info.header_block.result_state_id().clone(), header_block: notify_info.header_block.clone(), - qc_block: notify_info.qc_block.clone(), + qc: notify_info.qc.clone(), }, group_chunk_id: notify_info.group_chunk_id, group: notify_info.group.clone(), @@ -316,14 +297,9 @@ impl DecStateSynchronizerRunner { async fn push_update_notify( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { - if qc_block.qc().is_none() { - log::warn!("the qc is none for qc-block({})", qc_block.block_id()); - return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); - } - if let Some(notify) = self.update_notifies.as_mut() { match notify.header_block.height().cmp(&header_block.height()) { std::cmp::Ordering::Less => {} @@ -338,11 +314,7 @@ impl DecStateSynchronizerRunner { if header_block.check() && self .committee - .verify_block_desc_with_qc( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - remote, - ) + .verify_block_desc_with_qc(header_block.named_object().desc(), &qc, remote) .await .is_ok() { @@ -354,7 +326,7 @@ impl DecStateSynchronizerRunner { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, - qc_block: qc_block, + qc: qc, remotes: HashSet::from([remote]), group_chunk_id, group, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b1506a192..571c1ca13 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -194,7 +194,11 @@ impl StateChanggeRunner { .post_message( HotstuffMessage::ProposalResult( exe_info.proposal, - Ok((receipt, block.clone(), qc_block.clone())), + Ok(( + receipt, + block.clone(), + qc_block.qc().as_ref().unwrap().clone(), + )), ), rpath.clone(), &proposer, @@ -320,7 +324,7 @@ impl StateChanggeRunner { let msg = HotstuffMessage::StateChangeNotify( progress.header_block.clone(), - progress.qc_block.clone(), + progress.qc_block.qc().as_ref().unwrap().clone(), ); if notify_targets.len() > 0 { diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index ce36043a3..4d3f1b1c6 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,5 +1,3 @@ mod timer; -mod verify; pub use timer::*; -pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs deleted file mode 100644 index ef3e34495..000000000 --- a/src/component/cyfs-group/src/helper/verify.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, -}; - -use crate::GroupRPathStatus; - -pub async fn verify_rpath_value( - value: &GroupRPathStatus, - sub_path: &str, - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - unimplemented!() -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index ba8e83569..c493f13c5 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -4,10 +4,8 @@ mod dec; mod dec_state; mod helper; mod network; -mod objects; mod statepath; mod storage; -mod utils; pub use consensus::*; pub use constant::*; @@ -15,7 +13,5 @@ pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; pub use network::*; -pub use objects::*; pub use statepath::*; pub(crate) use storage::*; -pub use utils::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index f79e67dd4..096bd0950 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,7 +1,9 @@ mod listener; mod non_driver; +mod protocol; mod sender; pub(crate) use listener::*; pub use non_driver::*; +pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs similarity index 70% rename from src/component/cyfs-group/src/objects/protocol.rs rename to src/component/cyfs-group/src/network/protocol.rs index 932e5cd46..7e32fdc4d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -1,16 +1,8 @@ -pub mod protos { - include!(concat!(env!("OUT_DIR"), "/mod.rs")); -} - use cyfs_base::*; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_group_lib::{GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; use itertools::Itertools; -use sha2::Digest; - -use crate::GroupRPathStatus; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { @@ -96,15 +88,11 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, - ), // (proposal-id, (ExecuteResult, block, qc-block)) + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, + ), // (proposal-id, (ExecuteResult, block, qc)) QueryState(String), VerifiableState(String, BuckyResult), } @@ -151,8 +139,8 @@ impl std::fmt::Debug for HotstuffMessage { "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest => { @@ -169,8 +157,8 @@ impl std::fmt::Debug for HotstuffMessage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) }) ) @@ -214,16 +202,12 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) LastStateRequest(ProtocolAddress), ProposalResult( ObjectId, Result< - ( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - ), + (Option, GroupConsensusBlock, HotstuffBlockQC), (BuckyError, ProtocolAddress), >, ), // (proposal-id, ExecuteResult) @@ -276,8 +260,8 @@ impl std::fmt::Debug for HotstuffPackage { "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest(_) => { @@ -296,8 +280,8 @@ impl std::fmt::Debug for HotstuffPackage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ); Ok(ok) } @@ -394,23 +378,25 @@ fn decode_with_length<'de, O: RawDecode<'de>>( impl RawEncode for HotstuffPackage { fn raw_measure(&self, purpose: &Option) -> BuckyResult { let len = match self { - HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::Block(b) => 3 + b.raw_measure(purpose)?, HotstuffPackage::BlockVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::TimeoutVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::Timeout(addr, tc) => { - 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + tc.raw_measure(purpose)? } HotstuffPackage::SyncRequest(addr, min, max) => { - addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + + min.raw_measure(purpose)? + + max.raw_measure(purpose)? } HotstuffPackage::StateChangeNotify(block, qc) => { - 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + 3 + qc.raw_measure(purpose)? } - HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::LastStateRequest(addr) => 2 + addr.raw_measure(purpose)?, HotstuffPackage::ProposalResult(id, result) => { id.raw_measure(purpose)? + match result { @@ -418,22 +404,23 @@ impl RawEncode for HotstuffPackage { non.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + + 3 + block_qc.raw_measure(purpose)? } Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } HotstuffPackage::QueryState(addr, sub_path) => { - addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } HotstuffPackage::VerifiableState(sub_path, result) => { sub_path.raw_measure(purpose)? + match result { - Ok(status) => status.raw_measure(purpose)?, + Ok(status) => 3 + status.raw_measure(purpose)?, Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } @@ -451,43 +438,43 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::Block(b) => { buf[0] = 0; let buf = &mut buf[1..]; - b.raw_encode(buf, purpose) + encode_with_length(buf, b, purpose, 3) } HotstuffPackage::BlockVote(addr, vote) => { buf[0] = 1; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::TimeoutVote(addr, vote) => { buf[0] = 2; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::Timeout(addr, tc) => { buf[0] = 3; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - tc.raw_encode(buf, purpose) + encode_with_length(buf, tc, purpose, 3) } HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; + encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; - let buf = max.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + max.raw_encode(buf, purpose) } HotstuffPackage::StateChangeNotify(block, qc) => { buf[0] = 5; let buf = &mut buf[1..]; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } HotstuffPackage::LastStateRequest(addr) => { buf[0] = 6; let buf = &mut buf[1..]; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; @@ -501,19 +488,19 @@ impl RawEncode for HotstuffPackage { Ok((non, block, qc)) => { let buf = non.raw_encode(buf, purpose)?; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } HotstuffPackage::QueryState(addr, sub_path) => { buf[0] = 8; let buf = &mut buf[1..]; - let buf = sub_path.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2)?; + sub_path.raw_encode(buf, purpose) } HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; @@ -523,10 +510,10 @@ impl RawEncode for HotstuffPackage { let buf = &mut buf[1..]; let buf = sub_path.raw_encode(buf, purpose)?; match result { - Ok(status) => status.raw_encode(buf, purpose), + Ok(status) => encode_with_length(buf, status, purpose, 3), Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } @@ -542,49 +529,49 @@ impl<'de> RawDecode<'de> for HotstuffPackage { match pkg_type { 0 => { let buf = &buf[1..]; - let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (b, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } @@ -596,7 +583,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { true => { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), @@ -605,7 +592,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } @@ -613,8 +600,8 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } 8 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } @@ -624,13 +611,13 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (sub_path, buf) = String::raw_decode(buf)?; match is_ok { true => { - let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + let (status, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), @@ -698,188 +685,5 @@ impl ProtocolAddress { } } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] -pub(crate) struct HotstuffBlockQCVote { - pub block_id: ObjectId, - pub prev_block_id: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let block_id = block.block_id().object_id(); - let round = block.round(); - - log::debug!( - "[block vote] local: {:?}, vote hash {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let hash = Self::hash_content(block_id, block.prev_block_id(), round); - - log::debug!( - "[block vote] local: {:?}, vote sign {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let signature = signer - .sign( - hash.as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - block_id: block_id.clone(), - round, - voter: local_device_id, - signature, - prev_block_id: block.prev_block_id().map(|id| id.clone()), - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) - } - - fn hash_content( - block_id: &ObjectId, - prev_block_id: Option<&ObjectId>, - round: u64, - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(block_id.as_slice()); - sha256.input(round.to_le_bytes()); - if let Some(prev_block_id) = prev_block_id { - sha256.input(prev_block_id.as_slice()); - } - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffBlockQCVote { - fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, - round: value.round, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), - None => None, - }, - }) - } -} - -impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { - fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { - let ret = crate::protos::HotstuffBlockQcVote { - block_id: value.block_id.to_vec()?, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(id.to_vec()?), - None => None, - }, - }; - - Ok(ret) - } -} - -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] -pub(crate) struct HotstuffTimeoutVote { - pub high_qc: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffTimeoutVote { - pub async fn new( - high_qc: Option, - round: u64, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let signature = signer - .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - high_qc, - round, - voter: local_device_id, - signature, - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) - } - - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(high_qc_round.to_le_bytes()); - sha256.input(round.to_le_bytes()); - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffTimeoutVote { - fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { - let high_qc = if value.high_qc().len() == 0 { - None - } else { - Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) - }; - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - round: value.round, - high_qc, - }) - } -} - -impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { - fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { - let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc.as_ref() { - Some(qc) => Some(qc.to_vec()?), - None => None, - }, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - }; - - Ok(ret) - } -} - #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs deleted file mode 100644 index 5d1a8b13f..000000000 --- a/src/component/cyfs-group/src/objects/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod group_decide_proposal; -mod group_rpath_status; -mod group_update_proposal; -mod protocol; - -pub use group_decide_proposal::*; -pub use group_rpath_status::*; -pub use group_update_proposal::*; -pub use protocol::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 60a45724f..0d937487c 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -5,16 +5,17 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; +use crate::STATE_PATH_SEPARATOR; #[derive(Clone)] pub struct DecStorageCache { pub state: Option, pub header_block: GroupConsensusBlock, - pub qc_block: GroupConsensusBlock, + pub qc: HotstuffBlockQC, } #[derive(Clone)] @@ -42,7 +43,7 @@ impl DecStorage { pub async fn sync( &self, header_block: &GroupConsensusBlock, - qc_block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index adf11c7e4..63158a865 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_lib::GroupObjectMapProcessor; +use cyfs_group_lib::GroupObjectMapProcessor; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index fa6f4930f..a1a681259 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; +use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, + STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs deleted file mode 100644 index 5d005a726..000000000 --- a/src/component/cyfs-group/src/utils.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cyfs_base::ObjectId; - -pub type Round = u64; - -pub enum IsCreateRPath { - No, - Yes, -} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index d2f02315a..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,7 +4,6 @@ mod base; mod crypto; mod default_app; mod events; -mod group; mod ndn; mod non; mod prelude; @@ -27,7 +26,6 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; -pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; From ae2af4d288c2a290d56d8c49a9a31d7cb849a36c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 12:15:59 +0800 Subject: [PATCH 400/553] Implement the events with post_object --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- .../cyfs-group/src/dec/group_events.rs | 120 +++++++++++++++--- .../cyfs-group/src/dec/group_manager.rs | 50 ++++++-- .../cyfs-group/src/dec/rpath_client.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 19 ++- .../cyfs-stack/src/stack/group_non_driver.rs | 8 +- 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index cc555298b..eaaaed06e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -514,7 +514,7 @@ impl HotstuffRunner { self .event_notifier - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal.clone(), prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -831,14 +831,14 @@ impl HotstuffRunner { self.event_notifier .on_commited( - &proposal_obj, + proposal_obj, pre_state_id, &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, - &new_header, + new_header.clone(), ) .await; @@ -1613,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.event_notifier.on_execute(&proposal, result_state_id).await { + match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 67f79cfdd..fc3d12c63 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,42 +1,132 @@ use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_group_lib::ExecuteResult; +use cyfs_group_lib::{ + ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandVerify, +}; use cyfs_lib::NONObjectInfo; +use crate::NONDriverHelper; + #[derive(Clone)] -pub(crate) struct RPathEventNotifier {} +pub(crate) struct RPathEventNotifier { + non_driver: NONDriverHelper, +} impl RPathEventNotifier { - pub fn new() -> Self { - unimplemented!() + pub fn new(driver: NONDriverHelper) -> Self { + Self { non_driver: driver } } pub async fn on_execute( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, ) -> BuckyResult { - unimplemented!() + let cmd = GroupCommandExecute { + proposal, + prev_state_id, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_some()); + match result.as_ref() { + Some(result) => { + let (cmd, _remain) = GroupCommand::raw_decode(result.object_raw.as_slice())?; + assert_eq!(_remain.len(), 0); + let mut cmd = TryInto::::try_into(cmd)?; + Ok(ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }) + } + None => Err(BuckyError::new( + BuckyErrorCode::Unknown, + "expect some result from dec-app", + )), + } } pub async fn on_verify( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandVerify { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } pub async fn on_commited( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, - block: &GroupConsensusBlock, + block: GroupConsensusBlock, ) { - unimplemented!() + let cmd = GroupCommandCommited { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec().expect( + format!("on_commited {} failed for encode", self.non_driver.dec_id()) + .as_str(), + ), + object: None, + }, + None, + ) + .await + .map_err(|err| log::warn!("on_commited {} failed {:?}", self.non_driver.dec_id(), err)); + + assert!(result.is_err() || result.unwrap().is_none()); } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95bdbcd17..346e75d02 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,11 +2,13 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -32,7 +34,6 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, - event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,7 +55,6 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, - event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { @@ -393,7 +393,6 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -410,8 +409,13 @@ impl GroupManager { if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - self.on_new_rpath_request(group_id, dec_id, rpath, block) - .await?; + self.on_new_rpath_request( + group_id.clone(), + dec_id, + rpath.to_string(), + block.cloned(), + ) + .await?; if !is_auto_create { return Err(e); @@ -457,7 +461,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - event_notifier, + RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, store, @@ -472,11 +476,33 @@ impl GroupManager { async fn on_new_rpath_request( &self, - group_id: &ObjectId, + group_id: ObjectId, dec_id: &ObjectId, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, + rpath: String, + with_block: Option, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandNewRPath { + group_id, + rpath, + with_block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .local_info() + .non_driver + .post_object( + dec_id, + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 08be0f5a0..41db0c25c 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -100,7 +100,7 @@ impl RPathClient { match self .0 .non_driver - .post_object(non_proposal.clone(), ood) + .post_object(non_proposal.clone(), Some(ood)) .await { Ok(r) => post_result = Some(Ok(())), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 979451b79..c7f9e7d93 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, }; @@ -29,8 +29,8 @@ pub trait NONDriver: Send + Sync { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()>; + to: Option<&ObjectId>, + ) -> BuckyResult>; } #[derive(Clone)] @@ -49,6 +49,10 @@ impl NONDriverHelper { } } + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id + } + pub async fn get_object( &self, object_id: &ObjectId, @@ -74,12 +78,17 @@ impl NONDriverHelper { self.driver.put_object(&self.dec_id, obj).await } - pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object( + &self, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { self.driver.post_object(&self.dec_id, obj, to).await } pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { - futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), Some(to)))) + .await; } pub async fn get_block( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fcb0dd6da..f7f305a83 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -88,8 +88,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()> { + to: Option<&ObjectId>, + ) -> BuckyResult> { self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { @@ -107,12 +107,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { level: NONAPILevel::Router, - target: Some(to.clone()), + target: to.cloned(), flags: 0, }, object: obj, }) .await - .map(|_| ()) + .map(|resp| resp.object) } } From 7db18c25cab487a4145d2aa2c496c9785aed34c7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 14:56:29 +0800 Subject: [PATCH 401/553] Rename `control` into `Service` --- .../cyfs-group/src/dec/group_manager.rs | 80 +++++++++---------- src/component/cyfs-group/src/dec/mod.rs | 4 +- .../{rpath_control.rs => rpath_service.rs} | 8 +- src/tests/group-example/src/main.rs | 20 ++--- 4 files changed, 56 insertions(+), 56 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_control.rs => rpath_service.rs} (96%) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 346e75d02..23202fddf 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,19 +12,19 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, + RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, }; -type ControlByRPath = HashMap; -type ControlByDec = HashMap; -type ControlByGroup = HashMap; +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; type ClientByRPath = HashMap; type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - control_by_group: ControlByGroup, + service_by_group: ServiceByGroup, client_by_group: ClientByGroup, } @@ -58,7 +58,7 @@ impl GroupManager { }; let raw = GroupRPathMgrRaw { - control_by_group: ControlByGroup::default(), + service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), }; @@ -69,14 +69,14 @@ impl GroupManager { Ok(mgr) } - pub async fn find_rpath_control( + pub async fn find_rpath_service( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, is_auto_create: bool, - ) -> BuckyResult { - self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + ) -> BuckyResult { + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -155,7 +155,7 @@ impl GroupManager { } // return - pub async fn enum_rpath_control( + pub async fn enum_rpath_service( &self, group_id: &ObjectId, ) -> BuckyResult> { @@ -182,8 +182,8 @@ impl GroupManager { match msg { HotstuffPackage::Block(block) => { let rpath = block.r_path(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -192,14 +192,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Block(block), remote) .await; } HotstuffPackage::BlockVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -208,14 +208,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; } HotstuffPackage::TimeoutVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -224,14 +224,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; } HotstuffPackage::Timeout(target, tc) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -240,14 +240,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Timeout(tc), remote) .await; } HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -256,14 +256,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; } HotstuffPackage::LastStateRequest(target) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -272,7 +272,7 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::LastStateRequest, remote) .await; } @@ -309,8 +309,8 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -320,9 +320,9 @@ impl GroupManager { ) .await; - match control { - Ok(control) => { - control + match service { + Ok(service) => { + service .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } @@ -356,7 +356,7 @@ impl GroupManager { Ok(()) } - async fn find_rpath_control_inner( + async fn find_rpath_service_inner( &self, group_id: &ObjectId, dec_id: &ObjectId, @@ -364,12 +364,12 @@ impl GroupManager { is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, - ) -> BuckyResult { + ) -> BuckyResult { { // read let raw = self.read().await; let found = raw - .control_by_group + .service_by_group .get(group_id) .map_or(None, |by_dec| by_dec.get(dec_id)) .map_or(None, |by_rpath| by_rpath.get(rpath)); @@ -446,7 +446,7 @@ impl GroupManager { }; let found = raw - .control_by_group + .service_by_group .entry(group_id.clone()) .or_insert_with(HashMap::new) .entry(dec_id.clone()) @@ -456,7 +456,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let control = RPathControl::load( + let service = RPathService::load( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -467,8 +467,8 @@ impl GroupManager { store, ) .await?; - entry.insert(control.clone()); - Ok(control) + entry.insert(service.clone()); + Ok(service) } } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 2ad717514..f881db19c 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod group_events; mod group_manager; mod rpath_client; -mod rpath_control; +mod rpath_service; pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; -pub use rpath_control::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_service.rs similarity index 96% rename from src/component/cyfs-group/src/dec/rpath_control.rs rename to src/component/cyfs-group/src/dec/rpath_service.rs index 593d82db4..b4b90972f 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -9,7 +9,7 @@ use crate::{ PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; -struct RPathControlRaw { +struct RPathServiceRaw { local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, @@ -18,9 +18,9 @@ struct RPathControlRaw { } #[derive(Clone)] -pub struct RPathControl(Arc); +pub struct RPathService(Arc); -impl RPathControl { +impl RPathService { pub(crate) async fn load( local_id: ObjectId, local_device_id: ObjectId, @@ -50,7 +50,7 @@ impl RPathControl { rpath.clone(), ); - let raw = RPathControlRaw { + let raw = RPathServiceRaw { network_sender, pending_proposal_handle, local_id, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 42544e51c..88450ac1b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,7 +505,7 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathControl; + use cyfs_group::RPathService; use cyfs_lib::{ DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, @@ -545,7 +545,7 @@ mod GroupDecService { } // pub struct PostProposalRoutine { - // controller: RPathControl, + // service: RPathService, // } // #[async_trait::async_trait] @@ -558,7 +558,7 @@ mod GroupDecService { // ) -> BuckyResult { // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // self.controller.push_proposal(proposal).await?; + // self.service.push_proposal(proposal).await?; // Ok(NONPostObjectInputResponse { object: None }) // } // } @@ -1037,9 +1037,9 @@ async fn main_run() { ) .await; - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1066,9 +1066,9 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1113,9 +1113,9 @@ async fn main_run() { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1125,7 +1125,7 @@ async fn main_run() { .unwrap(); async_std::task::spawn(async move { - control.push_proposal(proposal).await.unwrap(); + service.push_proposal(proposal).await.unwrap(); }); if i % 10 == 0 { From b41129d1eca2e35f74878e7ca07e0b305a17854d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 15:34:34 +0800 Subject: [PATCH 402/553] Interface in client for DecAPP --- src/component/cyfs-group-lib/src/delegate.rs | 6 +-- .../cyfs-group-lib/src/group_manager.rs | 37 ++++++++++++++++--- src/component/cyfs-group-lib/src/lib.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 23 ++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/rpath_service.rs diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 21b1e6346..645cd0656 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,4 @@ -use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, -}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -11,7 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()>; + ) -> BuckyResult>; } pub struct ExecuteResult { diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 8c82bc9e1..103807446 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,20 +1,47 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::DecAppId; +use cyfs_lib::SharedCyfsStack; -use crate::{DelegateFactory, RPathClient}; +use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; #[derive(Clone)] pub struct GroupManager; impl GroupManager { - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn open( + stack: SharedCyfsStack, + delegate_factory: Box, + ) -> BuckyResult { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn start_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + delegate: Box, + ) -> BuckyResult { + Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + } + + pub async fn find_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client( + &self, + group_id: ObjectId, + dec_id: DecAppId, + rpath: String, + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 199307bcc..34473bf07 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -2,8 +2,10 @@ mod delegate; mod group_manager; mod objects; mod rpath_client; +mod rpath_service; pub use delegate::*; pub use group_manager::*; pub use objects::*; pub use rpath_client::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs new file mode 100644 index 000000000..81225ed72 --- /dev/null +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupProposal, GroupRPath}; + +struct RPathServiceRaw {} + +#[derive(Clone)] +pub struct RPathService(Arc); + +impl RPathService { + pub(crate) async fn load() -> BuckyResult { + unimplemented!() + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + unimplemented!() + } +} From f42fb9f77103702ebbb59f8371525044beff2f35 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 21:21:44 +0800 Subject: [PATCH 403/553] Interface in client for DecAPP events --- .../cyfs-base/protos/standard_objects.proto | 4 +- src/component/cyfs-base/src/objects/group.rs | 20 +- .../cyfs-core/protos/core_objects.proto | 8 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 18 +- .../cyfs-core/src/group/group_rpath.rs | 14 +- src/component/cyfs-group-lib/Cargo.toml | 3 +- src/component/cyfs-group-lib/src/delegate.rs | 24 +- .../cyfs-group-lib/src/group_manager.rs | 442 +++++++++++++++++- .../cyfs-group-lib/src/rpath_client.rs | 45 +- .../cyfs-group-lib/src/rpath_service.rs | 122 ++++- .../src/consensus/hotstuff/hotstuff.rs | 4 +- .../cyfs-group/src/dec/group_events.rs | 10 +- .../cyfs-group/src/dec/group_manager.rs | 28 +- .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec_state/state_pusher.rs | 4 +- .../cyfs-group/src/network/protocol.rs | 6 +- .../engine/storage_engine_group_state.rs | 8 +- .../cyfs-group/src/storage/group_storage.rs | 6 +- src/component/cyfs-lib/src/stack/stack.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- 21 files changed, 689 insertions(+), 115 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index cfb722c62..4a9714958 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -72,7 +72,7 @@ message GroupMethodACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; double min_support_percent = 4; string permissions = 5; // ACL-String @@ -83,7 +83,7 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; string method = 4; double right_percent = 5; diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ed7686157..5c8cda714 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -436,7 +436,7 @@ impl TryFrom<&GroupMember> for protos::GroupMember { pub struct GroupMethodACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub min_support_percent: f64, pub permissions: String, // ACL-String } @@ -452,8 +452,8 @@ impl TryFrom for GroupMethodACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -475,8 +475,8 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.min_support_percent = value.min_support_percent; ret.permissions = value.permissions.clone(); @@ -489,7 +489,7 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { pub struct GroupRoleACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub method: String, pub right_percent: f64, @@ -508,8 +508,8 @@ impl TryFrom for GroupRoleACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -533,8 +533,8 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.method = value.method.clone(); ret.right_percent = value.right_percent; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 742c14904..8048b3951 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -333,12 +333,12 @@ message SyncResponseObjectMetaInfo { message GroupRPath { bytes group_id = 1; bytes dec_id = 2; - string r_path = 3; + string rpath = 3; } message GroupProposalDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; @@ -404,7 +404,7 @@ message HotstuffTimeout { message GroupConsensusBlockDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // input bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) @@ -437,7 +437,7 @@ message GroupConsensusBlockBodyContent { /* message GroupActionDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 35c418552..7d447ad15 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -10,7 +10,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path: GroupRPath, + rpath: GroupRPath, body_hash: HashValue, result_state_id: Option, height: u64, @@ -40,7 +40,7 @@ impl DescContent for GroupConsensusBlockDescContent { impl GroupConsensusBlockDescContent { pub fn rpath(&self) -> &GroupRPath { - &self.r_path + &self.rpath } pub fn result_state_id(&self) -> &Option { @@ -236,7 +236,7 @@ impl GroupConsensusBlockBodyContent { pub trait GroupConsensusBlockObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -248,7 +248,7 @@ pub trait GroupConsensusBlockObject { owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; @@ -266,7 +266,7 @@ pub trait GroupConsensusBlockObject { impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -280,7 +280,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { - r_path, + rpath, result_state_id, height, @@ -319,9 +319,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path(&self) -> &GroupRPath { + fn rpath(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path + &desc.rpath } fn proposals(&self) -> &Vec { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index bf28aafb2..508418f7b 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -6,7 +6,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, @@ -123,7 +123,7 @@ pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, meta_block_id: Option, @@ -131,7 +131,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path, + rpath, method, params, meta_block_id, @@ -158,7 +158,7 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -169,7 +169,7 @@ pub trait GroupProposalObject { effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -207,7 +207,7 @@ pub trait GroupProposalObject { #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -218,7 +218,7 @@ impl GroupProposalObject for GroupProposal { effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path, + rpath, method, params, meta_block_id, @@ -237,8 +237,8 @@ impl GroupProposalObject for GroupProposal { .owner(owner) } - fn r_path(&self) -> &GroupRPath { - &self.desc().content().r_path + fn rpath(&self) -> &GroupRPath { + &self.desc().content().rpath } fn method(&self) -> &str { diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 3b86fbc57..f177015bf 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,25 +1,25 @@ use cyfs_base::*; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq, Hash)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, - r_path: String, + rpath: String, } impl std::fmt::Debug for GroupRPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.rpath) } } impl GroupRPath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { Self { group_id, dec_id, - r_path, + rpath, } } @@ -31,7 +31,7 @@ impl GroupRPath { &self.dec_id } - pub fn r_path(&self) -> &str { - self.r_path.as_str() + pub fn rpath(&self) -> &str { + self.rpath.as_str() } } diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index e7cfda851..bad3d3112 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -31,4 +31,5 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 645cd0656..3cc99902b 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,6 @@ -use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SingleOpEnvStub}; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { @@ -23,30 +23,36 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult<()>; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ); } #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { - async fn create_single_op_env(&self) -> BuckyResult; - async fn create_sub_tree_op_env(&self) -> BuckyResult; + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult; + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 103807446..f93be45f0 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,37 +1,132 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::DecAppId; -use cyfs_lib::SharedCyfsStack; +use std::{collections::HashMap, sync::Arc}; -use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RawDecode, +}; +use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, + SharedCyfsStack, +}; +use cyfs_util::EventListenerAsyncRoutine; + +use crate::{ + DelegateFactory, ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandNewRPath, GroupCommandObject, GroupCommandType, + GroupCommandVerify, RPathClient, RPathDelegate, RPathService, +}; + +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupManagerRaw { + stack: SharedCyfsStack, + requestor: HttpRequestorRef, + delegate_factory: Option>, + clients: RwLock, + services: RwLock, + local_zone: Option, +} #[derive(Clone)] -pub struct GroupManager; +pub struct GroupManager(Arc); impl GroupManager { pub async fn open( stack: SharedCyfsStack, delegate_factory: Box, + requestor_type: &CyfsStackRequestorType, ) -> BuckyResult { - unimplemented!() + if stack.dec_id().is_none() { + let msg = "the stack should be opened with dec-id"; + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let dec_id = stack.dec_id().unwrap().clone(); + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + let router_handler_manager = stack.router_handlers().clone(); + + let mgr = Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: Some(delegate_factory), + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + })); + + // TODO: other filters? only local zone + let filter = format!( + "obj_type == {} && dec_id == {}", + CoreObjectType::GroupCommand as u16, + dec_id, + ); + + router_handler_manager + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-cmd-{}", dec_id).as_str(), + 0, + Some(filter), + None, + RouterHandlerAction::Pass, + Some(Box::new(mgr.clone())), + ) + .await?; + + Ok(mgr) } - pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { + pub async fn open_as_client( + stack: SharedCyfsStack, + requestor_type: &CyfsStackRequestorType, + ) -> BuckyResult { + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + + Ok(Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: None, + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + }))) + } + + pub async fn stop(&self) { unimplemented!() } + pub fn stack(&self) -> &SharedCyfsStack { + &self.0.stack + } + pub async fn start_rpath_service( &self, group_id: ObjectId, rpath: String, delegate: Box, ) -> BuckyResult { - Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + unimplemented!() } pub async fn find_rpath_service( &self, - group_id: ObjectId, - rpath: String, + group_id: &ObjectId, + rpath: &str, ) -> BuckyResult { unimplemented!() } @@ -40,8 +135,329 @@ impl GroupManager { &self, group_id: ObjectId, dec_id: DecAppId, - rpath: String, - ) -> BuckyResult { - unimplemented!() + rpath: &str, + ) -> RPathClient { + { + let clients = self.0.clients.read().await; + let found = clients + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id.object_id())) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return found.clone(); + } + } + + { + let client = RPathClient::new( + GroupRPath::new(group_id, dec_id.object_id().clone(), rpath.to_string()), + self.0.stack.dec_id().cloned(), + self.0.stack.non_service().clone(), + ); + + let mut clients = self.0.clients.write().await; + let client = clients + .entry(group_id) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert(client); + client.clone() + } + } + + async fn on_command( + &self, + cmd: GroupCommand, + ) -> BuckyResult> { + match cmd.into_cmd() { + crate::GroupCommandBodyContent::NewRPath(cmd) => { + self.on_new_rpath(cmd).await.map(|_| None) + } + crate::GroupCommandBodyContent::Execute(cmd) => { + self.on_execute(cmd).await.map(|r| Some(r)) + } + crate::GroupCommandBodyContent::ExecuteResult(_) => { + let msg = format!( + "should not get the cmd({:?}) in sdk", + GroupCommandType::ExecuteResult + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)) + } + crate::GroupCommandBodyContent::Verify(cmd) => self.on_verify(cmd).await.map(|_| None), + crate::GroupCommandBodyContent::Commited(cmd) => { + self.on_commited(cmd).await.map(|_| None) + } + } + } + + async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let group_id = &cmd.group_id; + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.rpath.as_str(); + + { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if found.is_some() { + return Ok(()); + } + } + + let delegate = factory + .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) + .await?; + + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(()); + } + }; + + new_service.start().await; + Ok(()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } + } + + async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try execute proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try execute proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let mut result = service + .on_execute(&cmd.proposal, &cmd.prev_state_id) + .await?; + + Ok(GroupCommandExecuteResult { + result_state_id: result.result_state_id.take(), + receipt: result.receipt.take(), + context: result.context.take(), + }) + } + + async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try verify proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try verify proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) + .await + } + + async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try commited proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try commited proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } +} + +#[async_trait::async_trait] +impl EventListenerAsyncRoutine + for GroupManager +{ + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + let req_common = ¶m.request.common; + if req_common.level != NONAPILevel::NOC + || req_common.source.zone.zone != self.0.local_zone + || self.0.local_zone.is_none() + || self.0.stack.dec_id().is_none() + { + log::warn!( + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id() + ); + + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let obj = ¶m.request.object; + match obj.object.as_ref() { + None => { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }) + } + Some(any_obj) => { + assert_eq!(any_obj.obj_type(), CoreObjectType::GroupCommand as u16); + if any_obj.obj_type() != CoreObjectType::GroupCommand as u16 { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let (cmd, remain) = GroupCommand::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + let resp_obj = self.on_command(cmd).await; + + let resp_cmd = resp_obj.map_or_else( + |err| Err(err), + |resp_obj| { + resp_obj.map_or(Ok(None), |resp_cmd| { + let resp_cmd = GroupCommand::from(resp_cmd); + resp_cmd.to_vec().map(|buf| { + Some(NONObjectInfo::new(resp_cmd.desc().object_id(), buf, None)) + }) + }) + }, + ); + + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: Some(resp_cmd.map(|cmd| NONPostObjectInputResponse { object: cmd })), + }) + } + } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 2fea6dcf7..ea032715b 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -1,26 +1,55 @@ use std::sync::Arc; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, - RawConvertTo, +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, }; -use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::NONObjectInfo; -struct RPathClientRaw {} +struct RPathClientRaw { + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, +} #[derive(Clone)] pub struct RPathClient(Arc); impl RPathClient { + pub(crate) fn new( + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, + ) -> Self { + Self(Arc::new(RPathClientRaw { + requestor, + rpath, + local_dec_id, + })) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + self.0 + .requestor + .post_object(NONPostObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: self.0.local_dec_id.clone(), + level: NONAPILevel::Router, + target: Some(proposal.rpath().group_id().clone()), + flags: 0, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), proposal.to_vec()?, None), + }) + .await + .map(|resp| resp.object) } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 81225ed72..cebe445dd 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,23 +1,133 @@ use std::sync::Arc; -use cyfs_base::BuckyResult; -use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, +}; -struct RPathServiceRaw {} +use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + +struct RPathServiceRaw { + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, +} #[derive(Clone)] pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load() -> BuckyResult { + pub fn rpath(&self) -> &GroupRPath { unimplemented!() } - pub fn rpath(&self) -> &GroupRPath { + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + // post http unimplemented!() } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub(crate) fn new( + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, + ) -> Self { + Self(Arc::new(RPathServiceRaw { + rpath, + requestor, + delegate, + stack, + })) + } + + pub(crate) async fn start(&self) -> BuckyResult { + // post create command unimplemented!() } + + pub(crate) async fn on_execute( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + ) -> BuckyResult { + self.0 + .delegate + .on_execute( + proposal, + prev_state_id, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_verify( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + self.0 + .delegate + .on_verify( + proposal, + prev_state_id, + execute_result, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_commited( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + self.0 + .delegate + .on_commited( + proposal, + prev_state_id, + execute_result, + block, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } +} + +struct GroupObjectMapProcessorImpl { + stack: SharedCyfsStack, +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorImpl { + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_single_op_env_with_access(access) + .await + } + + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_isolate_path_op_env_with_access(access) + .await + } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index eaaaed06e..d2dbcc517 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,7 +11,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; @@ -20,7 +20,7 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, }; /** diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index fc3d12c63..9bda7e340 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,6 @@ use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -130,3 +130,9 @@ impl RPathEventNotifier { assert!(result.is_err() || result.unwrap().is_none()); } } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 23202fddf..7a9708ccc 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -181,12 +181,12 @@ impl GroupManager { ) -> BuckyResult<()> { match msg { HotstuffPackage::Block(block) => { - let rpath = block.r_path(); + let rpath = block.rpath(); let service = self .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, Some(&block), Some(&remote), @@ -202,7 +202,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -218,7 +218,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -234,7 +234,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -250,7 +250,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -266,7 +266,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -278,9 +278,9 @@ impl GroupManager { } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { // TODO: unimplemented - // let rpath = header_block.r_path(); + // let rpath = header_block.rpath(); // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) // .await?; // client // .on_message( @@ -292,10 +292,10 @@ impl GroupManager { HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( @@ -313,7 +313,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -328,7 +328,7 @@ impl GroupManager { } _ => { let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) @@ -342,7 +342,7 @@ impl GroupManager { |status| status.block_desc.content().rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 41db0c25c..43fb8e559 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -78,13 +78,13 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.0.rpath); + assert_eq!(proposal.rpath(), &self.0.rpath); // TODO: signature let group = self .0 .non_driver - .get_group(proposal.r_path().group_id(), None, None) + .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 571c1ca13..99c3fed62 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -222,7 +222,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) @@ -248,7 +248,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 7e32fdc4d..1f2a46a73 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -321,16 +321,16 @@ impl std::fmt::Debug for HotstuffPackage { impl HotstuffPackage { pub(crate) fn rpath(&self) -> &GroupRPath { match self { - HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::Block(block) => block.rpath(), HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), - HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::StateChangeNotify(block, _) => block.rpath(), HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( |(_, addr)| addr.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 63158a865..029b09e78 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,12 +5,12 @@ use cyfs_base::{ ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_group_lib::GroupObjectMapProcessor; +use cyfs_core::GroupConsensusBlockObject; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a1a681259..3a762c1b6 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,12 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, - STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 2f162c331..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -94,7 +94,7 @@ pub struct SharedCyfsStack { // uni_stack uni_stack: Arc>, - requestor_holder: RequestorHolder, + requestor_holder: Arc>, } #[derive(Debug, Clone)] @@ -493,14 +493,15 @@ impl SharedCyfsStack { device_info: Arc::new(RwLock::new(None)), uni_stack: Arc::new(OnceCell::new()), - requestor_holder, + requestor_holder: Arc::new(RwLock::new(requestor_holder)), }; Ok(ret) } pub async fn stop(&self) { - self.requestor_holder.stop().await; + let requestor_holder = self.requestor_holder.read().unwrap(); + requestor_holder.stop().await; self.router_handlers.stop().await; @@ -744,6 +745,11 @@ impl SharedCyfsStack { pub fn uni_stack(&self) -> &UniCyfsStackRef { self.uni_stack.get_or_init(|| self.create_uni_stack()) } + + pub fn select_requestor(&self, requestor_type: &CyfsStackRequestorType) -> HttpRequestorRef { + let mut requestor_holder = self.requestor_holder.write().unwrap(); + requestor_holder.select_requestor(&self.param, requestor_type) + } } impl UniCyfsStack for SharedCyfsStack { diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index f7f305a83..431915a96 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: None, flags: 0, @@ -105,7 +105,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, From 0a938ae442833917f22282abfe88c0e8259bfde7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 16:49:16 +0800 Subject: [PATCH 404/553] Interface for client --- src/component/cyfs-group-lib/Cargo.toml | 1 + src/component/cyfs-group-lib/src/delegate.rs | 1 + .../cyfs-group-lib/src/group_manager.rs | 255 ++++++++---------- .../cyfs-group-lib/src/input_request.rs | 0 src/component/cyfs-group-lib/src/lib.rs | 12 + .../cyfs-group-lib/src/output_request.rs | 7 + src/component/cyfs-group-lib/src/processor.rs | 6 + src/component/cyfs-group-lib/src/request.rs | 0 .../cyfs-group-lib/src/request_codec.rs | 21 ++ src/component/cyfs-group-lib/src/requestor.rs | 210 +++++++++++++++ .../cyfs-group-lib/src/rpath_client.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 14 +- .../cyfs-lib/src/non/output_request.rs | 20 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- 14 files changed, 391 insertions(+), 162 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/input_request.rs create mode 100644 src/component/cyfs-group-lib/src/output_request.rs create mode 100644 src/component/cyfs-group-lib/src/processor.rs create mode 100644 src/component/cyfs-group-lib/src/request.rs create mode 100644 src/component/cyfs-group-lib/src/request_codec.rs create mode 100644 src/component/cyfs-group-lib/src/requestor.rs diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index bad3d3112..740b303cd 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' itertools = "0.10.3" +http-types = '2.12' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 3cc99902b..d678438c3 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -9,6 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult>; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f93be45f0..f442d5c55 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,7 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, @@ -195,98 +195,28 @@ impl GroupManager { } async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { - match self.0.delegate_factory.as_ref() { - Some(factory) => { - let group_id = &cmd.group_id; - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.rpath.as_str(); - - { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - if found.is_some() { - return Ok(()); - } - } - - let delegate = factory - .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) - .await?; - - let new_service = { - let mut is_new = false; - - let mut services = self.0.services.write().await; - let service = services - .entry(group_id.clone()) - .or_insert_with(HashMap::new) - .entry(dec_id.clone()) - .or_insert_with(HashMap::new) - .entry(rpath.to_string()) - .or_insert_with(|| { - is_new = true; - - RPathService::new( - GroupRPath::new( - group_id.clone(), - dec_id.clone(), - rpath.to_string(), - ), - self.0.requestor.clone(), - delegate, - self.0.stack.clone(), - ) - }); - - if is_new { - service.clone() - } else { - return Ok(()); - } - }; - - new_service.start().await; - Ok(()) - } - None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), - } + self.find_or_restart_service( + &cmd.group_id, + self.0.stack.dec_id().unwrap(), + cmd.rpath.as_str(), + &cmd.with_block, + true, + ) + .await + .map(|_| ()) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try execute proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try execute proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) @@ -300,36 +230,16 @@ impl GroupManager { } async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try verify proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try verify proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -343,47 +253,102 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; - if cmd.proposal.rpath().dec_id() != dec_id { + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } + + async fn find_or_restart_service( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: &Option, + is_new: bool, + ) -> BuckyResult { + if dec_id != self.0.stack.dec_id().unwrap() { let msg = format!( - "try commited proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id + "try find proposal in different dec {:?}, expected: {:?}", + dec_id, + self.0.stack.dec_id().unwrap() ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - let service = { + { let services = self.0.services.read().await; let found = services .get(group_id) .and_then(|by_dec| by_dec.get(dec_id)) .and_then(|by_rpath| by_rpath.get(rpath)); - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try commited proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } + if let Some(found) = found { + return Ok(found.clone()); } - }; + } - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let delegate = factory + .create_rpath_delegate(group_id, rpath, with_block.as_ref(), is_new) + .await?; - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; - Ok(()) + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(service.clone()); + } + }; + + new_service.start().await; + Ok(new_service.clone()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } } } diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 34473bf07..519a64040 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,11 +1,23 @@ mod delegate; mod group_manager; +mod input_request; mod objects; +mod output_request; +mod processor; +mod request; +mod request_codec; +mod requestor; mod rpath_client; mod rpath_service; pub use delegate::*; pub use group_manager::*; +pub use input_request::*; pub use objects::*; +pub use output_request::*; +pub use processor::*; +pub(crate) use request::*; +pub use request_codec::*; +pub use requestor::*; pub use rpath_client::*; pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs new file mode 100644 index 000000000..c847668df --- /dev/null +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -0,0 +1,7 @@ +use cyfs_base::ObjectId; + +#[derive(Debug)] +pub struct GroupStartServiceOutputRequest { + pub group_id: ObjectId, + pub rpath: String, +} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs new file mode 100644 index 000000000..925061f3e --- /dev/null +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +#[async_trait::async_trait] +pub trait GroupOutputProcessor: Send + Sync {} + +pub type GroupOutputProcessorRef = Arc; diff --git a/src/component/cyfs-group-lib/src/request.rs b/src/component/cyfs-group-lib/src/request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs new file mode 100644 index 000000000..c4f330efc --- /dev/null +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -0,0 +1,21 @@ +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use serde_json::{Map, Value}; + +use crate::output_request::GroupStartServiceOutputRequest; + +impl JsonCodec for GroupStartServiceOutputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs new file mode 100644 index 000000000..437a01184 --- /dev/null +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + CYFS_API_LEVEL, +}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, +}; +use http_types::{Method, Request, Url}; + +use crate::{ + output_request::GroupStartServiceOutputRequest, + processor::{GroupOutputProcessor, GroupOutputProcessorRef}, +}; + +#[derive(Clone)] +pub struct GroupRequestor { + dec_id: ObjectId, + requestor: HttpRequestorRef, + service_url: Url, +} + +impl GroupRequestor { + pub fn new(dec_id: ObjectId, requestor: HttpRequestorRef) -> Self { + let addr = requestor.remote_addr(); + + let url = format!("http://{}/group/", addr); + let url = Url::parse(&url).unwrap(); + + Self { + dec_id, + requestor, + service_url: url, + } + } + + pub fn clone_processor(&self) -> GroupOutputProcessorRef { + Arc::new(self.clone()) + } + + fn encode_common_headers( + &self, + // action: NONAction, + com_req: &NONOutputRequestCommon, + http_req: &mut Request, + ) { + let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); + http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); + + RequestorHelper::encode_opt_header_with_encoding( + http_req, + cyfs_base::CYFS_REQ_PATH, + com_req.req_path.as_deref(), + ); + + // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + + http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); + + if let Some(target) = &com_req.target { + http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); + } + + if let Some(source) = &com_req.source { + http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); + } + + http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); + } + + fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(dec_id), + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, + } + } + + pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + log::info!("will start group service: {:?}", rpath); + + let url = self.service_url.join("start-service").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + let req = GroupStartServiceOutputRequest { + group_id: rpath.group_id().clone(), + rpath: rpath.rpath().to_string(), + }; + + self.encode_common_headers( + &Self::make_default_common(rpath.dec_id().clone()), + &mut http_req, + ); + let body = req.encode_string(); + http_req.set_body(body); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group start service failed, read body string error! req={:?} {}", + req, e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!("group start service success"); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group start service failed: rpath={:?}, status={}, {}", + rpath, + code, + e + ); + Err(e) + } + } + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + let proposal_id = proposal.desc().object_id(); + log::info!( + "will push proposal: {:?}, {}", + proposal.rpath(), + proposal_id + ); + + let url = self.service_url.join("push-proposal").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + self.encode_common_headers( + &Self::make_default_common(proposal.rpath().dec_id().clone()), + &mut http_req, + ); + + NONRequestorHelper::encode_object_info( + &mut http_req, + NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + ); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group push proposal failed, read body string error! req={:?}/{} {}", + proposal.rpath(), + proposal_id, + e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!( + "group push proposal success, req={:?}/{}", + proposal.rpath(), + proposal_id + ); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group push proposal failed: rpath={:?}/{}, status={}, {}", + proposal.rpath(), + proposal_id, + code, + e + ); + Err(e) + } + } + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupRequestor {} diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index ea032715b..7d7c9a613 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -32,6 +32,8 @@ impl RPathClient { &self.0.rpath } + // post proposal to the admins, it's same as calling to non.post_object with default parameters; + // and you can call the non.post_object with more parameters. pub async fn post_proposal( &self, proposal: &GroupProposal, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index cebe445dd..95811e339 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -6,11 +6,11 @@ use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; +use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; struct RPathServiceRaw { rpath: GroupRPath, - requestor: HttpRequestorRef, + requestor: GroupRequestor, delegate: Box, stack: SharedCyfsStack, } @@ -20,12 +20,12 @@ pub struct RPathService(Arc); impl RPathService { pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - unimplemented!() + self.0.requestor.push_proposal(proposal).await } pub(crate) fn new( @@ -35,16 +35,16 @@ impl RPathService { stack: SharedCyfsStack, ) -> Self { Self(Arc::new(RPathServiceRaw { + requestor: GroupRequestor::new(rpath.dec_id().clone(), requestor), rpath, - requestor, delegate, stack, })) } - pub(crate) async fn start(&self) -> BuckyResult { + pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - unimplemented!() + self.0.requestor.start_group_service(self.rpath()).await } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-lib/src/non/output_request.rs b/src/component/cyfs-lib/src/non/output_request.rs index d4950ce33..b6e96dcb3 100644 --- a/src/component/cyfs-lib/src/non/output_request.rs +++ b/src/component/cyfs-lib/src/non/output_request.rs @@ -4,7 +4,7 @@ use cyfs_base::*; use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NONOutputRequestCommon { // 请求路径,可为空 pub req_path: Option, @@ -130,14 +130,22 @@ impl NONUpdateObjectMetaOutputRequest { Self::new(NONAPILevel::NOC, object_id, access) } - pub fn new_non(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_non( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::NON, object_id, access); ret.common.target = target.map(|v| v.into()); ret } - pub fn new_router(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_router( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::Router, object_id, access); ret.common.target = target; @@ -243,7 +251,6 @@ impl NONGetObjectOutputRequest { } } - impl fmt::Display for NONGetObjectOutputRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "common: {}", self.common)?; @@ -338,7 +345,6 @@ impl fmt::Display for NONPostObjectOutputResponse { } } - // select #[derive(Clone)] pub struct NONSelectObjectOutputRequest { @@ -392,7 +398,6 @@ impl fmt::Display for NONSelectObjectOutputRequest { } } - #[derive(Clone)] pub struct NONSelectObjectOutputResponse { pub objects: Vec, @@ -470,7 +475,6 @@ impl fmt::Display for NONDeleteObjectOutputRequest { } } - #[derive(Clone)] pub struct NONDeleteObjectOutputResponse { pub object: Option, @@ -479,7 +483,7 @@ pub struct NONDeleteObjectOutputResponse { impl fmt::Display for NONDeleteObjectOutputResponse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "object: {:?}", self.object)?; - + Ok(()) } } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 431915a96..9333e7981 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::NOC, target: None, flags: 0, From d4e7a9ee069677a7ab5544661724782dcf8be4a1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 21:35:56 +0800 Subject: [PATCH 405/553] Export to SDK --- .../cyfs-group-lib/src/input_request.rs | 10 + .../cyfs-group-lib/src/output_request.rs | 4 + src/component/cyfs-group-lib/src/processor.rs | 24 ++- .../cyfs-group-lib/src/request_codec.rs | 19 +- src/component/cyfs-group-lib/src/requestor.rs | 54 +++-- .../cyfs-group-lib/src/rpath_service.rs | 21 +- src/component/cyfs-stack/Cargo.toml | 1 + src/component/cyfs-stack/src/group/mod.rs | 5 + .../cyfs-stack/src/group/processor.rs | 25 +++ .../cyfs-stack/src/group/transform.rs | 190 ++++++++++++++++++ .../cyfs-stack/src/group_api/acl/group_acl.rs | 61 ++++++ .../cyfs-stack/src/group_api/acl/mod.rs | 3 + src/component/cyfs-stack/src/group_api/mod.rs | 7 + .../group_api/router/group_service_router.rs | 133 ++++++++++++ .../src/group_api/router/local_service.rs | 113 +++++++++++ .../cyfs-stack/src/group_api/router/mod.rs | 5 + .../src/group_api/service/group_handler.rs | 125 ++++++++++++ .../src/group_api/service/group_listener.rs | 77 +++++++ .../src/group_api/service/group_service.rs | 35 ++++ .../cyfs-stack/src/group_api/service/mod.rs | 7 + .../cyfs-stack/src/interface/http_listener.rs | 11 + .../src/interface/listener_manager.rs | 14 +- src/component/cyfs-stack/src/lib.rs | 2 + .../cyfs-stack/src/stack/cyfs_stack.rs | 12 +- 24 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/component/cyfs-stack/src/group/mod.rs create mode 100644 src/component/cyfs-stack/src/group/processor.rs create mode 100644 src/component/cyfs-stack/src/group/transform.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/group_acl.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/group_service_router.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/local_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_handler.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_listener.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/mod.rs diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index e69de29bb..0f861ea3c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -0,0 +1,10 @@ +use cyfs_base::ObjectId; + +pub struct GroupStartServiceInputRequest { + pub group_id: ObjectId, + pub rpath: String, +} + +pub struct GroupStartServiceInputResponse {} + +pub struct GroupPushProposalInputResponse {} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index c847668df..f65e02e3e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -5,3 +5,7 @@ pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, pub rpath: String, } + +pub struct GroupStartServiceOutputResponse {} + +pub struct GroupPushProposalOutputResponse {} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 925061f3e..9aec5a354 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -1,6 +1,26 @@ use std::sync::Arc; +use cyfs_base::BuckyResult; +use cyfs_core::GroupProposal; +use cyfs_lib::NONOutputRequestCommon; + +use crate::{ + GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, +}; + #[async_trait::async_trait] -pub trait GroupOutputProcessor: Send + Sync {} +pub trait GroupOutputProcessor: Send + Sync { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult; + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} -pub type GroupOutputProcessorRef = Arc; +pub type GroupOutputProcessorRef = Arc>; diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index c4f330efc..58404d6b0 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::output_request::GroupStartServiceOutputRequest; +use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { @@ -19,3 +19,20 @@ impl JsonCodec for GroupStartServiceOutputReques }) } } + +impl JsonCodec for GroupStartServiceInputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 437a01184..462b1df85 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -13,6 +13,7 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, + GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -37,7 +38,7 @@ impl GroupRequestor { } pub fn clone_processor(&self) -> GroupOutputProcessorRef { - Arc::new(self.clone()) + Arc::new(Box::new(self.clone())) } fn encode_common_headers( @@ -70,7 +71,7 @@ impl GroupRequestor { http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { NONOutputRequestCommon { req_path: None, source: None, @@ -81,21 +82,23 @@ impl GroupRequestor { } } - pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + pub async fn start_service( + &self, + req_common: NONOutputRequestCommon, + group_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); let url = self.service_url.join("start-service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { - group_id: rpath.group_id().clone(), - rpath: rpath.rpath().to_string(), + group_id: group_id.clone(), + rpath: rpath.to_string(), }; - self.encode_common_headers( - &Self::make_default_common(rpath.dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -123,7 +126,7 @@ impl GroupRequestor { log::debug!("group start service success"); - Ok(()) + Ok(GroupStartServiceOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -138,7 +141,11 @@ impl GroupRequestor { } } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + proposal: &GroupProposal, + ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", @@ -149,10 +156,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers( - &Self::make_default_common(proposal.rpath().dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, @@ -189,7 +193,7 @@ impl GroupRequestor { proposal_id ); - Ok(()) + Ok(GroupPushProposalOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -207,4 +211,20 @@ impl GroupRequestor { } #[async_trait::async_trait] -impl GroupOutputProcessor for GroupRequestor {} +impl GroupOutputProcessor for GroupRequestor { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupRequestor::push_proposal(self, req_common, &req).await + } +} diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 95811e339..66d0d83f4 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; @@ -25,7 +25,14 @@ impl RPathService { pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - self.0.requestor.push_proposal(proposal).await + self.0 + .requestor + .push_proposal( + GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal, + ) + .await + .map(|_| {}) } pub(crate) fn new( @@ -44,7 +51,15 @@ impl RPathService { pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - self.0.requestor.start_group_service(self.rpath()).await + self.0 + .requestor + .start_service( + GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + self.rpath().group_id(), + self.rpath().rpath(), + ) + .await + .map(|_| {}) } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 76148a72e..12e2b186f 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -16,6 +16,7 @@ cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-group = { path = "../../component/cyfs-group" } +cyfs-group-lib = { path = "../../component/cyfs-group-lib" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } diff --git a/src/component/cyfs-stack/src/group/mod.rs b/src/component/cyfs-stack/src/group/mod.rs new file mode 100644 index 000000000..da7603e40 --- /dev/null +++ b/src/component/cyfs-stack/src/group/mod.rs @@ -0,0 +1,5 @@ +mod processor; +mod transform; + +pub(crate) use processor::*; +pub(crate) use transform::*; \ No newline at end of file diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs new file mode 100644 index 000000000..b6fe1544b --- /dev/null +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -0,0 +1,25 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +#[async_trait::async_trait] +pub(crate) trait GroupInputProcessor: Sync + Send { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult; + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} + +pub(crate) type GroupInputProcessorRef = Arc; diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs new file mode 100644 index 000000000..50abe1afb --- /dev/null +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -0,0 +1,190 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, + GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +use super::{GroupInputProcessor, GroupInputProcessorRef}; + +// 实现从input到output的转换 +pub(crate) struct GroupInputTransformer { + processor: GroupOutputProcessorRef, +} + +impl GroupInputTransformer { + pub fn new(processor: GroupOutputProcessorRef) -> GroupInputProcessorRef { + let ret = Self { processor }; + Arc::new(ret) + } + + fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { + NONOutputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 来源DEC + dec_id: common.source.get_opt_dec().cloned(), + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source: common.source.zone.device, + } + } + + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let out_req = GroupStartServiceOutputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let out_resp = self + .processor + .start_service(Self::convert_common(req_common), out_req) + .await?; + + let resp = GroupStartServiceInputResponse {}; + + Ok(resp) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let out_resp = self + .processor + .push_proposal(Self::convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalInputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupInputTransformer { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + GroupInputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupInputTransformer::push_proposal(self, req_common, req).await + } +} + +// 实现从output到input的转换 +pub(crate) struct GroupOutputTransformer { + processor: GroupInputProcessorRef, + source: RequestSourceInfo, +} + +impl GroupOutputTransformer { + fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + let mut source = self.source.clone(); + if let Some(dec_id) = common.dec_id { + source.set_dec(dec_id); + } + + NONInputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source, + } + } + + pub fn new( + processor: GroupInputProcessorRef, + source: RequestSourceInfo, + ) -> GroupOutputProcessorRef { + let ret = Self { processor, source }; + Arc::new(Box::new(ret)) + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let in_resp = self + .processor + .push_proposal(self.convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalOutputResponse {}; + + Ok(resp) + } + + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + let in_req = GroupStartServiceInputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let in_resp = self + .processor + .start_service(self.convert_common(req_common), in_req) + .await?; + + let resp = GroupStartServiceOutputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupOutputTransformer { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupOutputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupOutputTransformer::push_proposal(self, req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs new file mode 100644 index 000000000..0e789c023 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -0,0 +1,61 @@ +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +pub struct GroupAclInnerInputProcessor { + next: GroupInputProcessorRef, +} + +impl GroupAclInnerInputProcessor { + pub(crate) fn new(next: GroupInputProcessorRef) -> GroupInputProcessorRef { + Arc::new(Self { next }) + } + + fn check_local_zone_permit( + &self, + service: &str, + source: &RequestSourceInfo, + ) -> BuckyResult<()> { + // TODO + // if !source.is_current_zone() { + // let msg = format!( + // "{} service valid only in current zone! source={:?}, category={}", + // service, + // source.zone.device, + // source.zone.zone_category.as_str() + // ); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, msg)); + // } + + Ok(()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupAclInnerInputProcessor { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.next.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.next.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/mod.rs b/src/component/cyfs-stack/src/group_api/acl/mod.rs new file mode 100644 index 000000000..53dad00b3 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/mod.rs @@ -0,0 +1,3 @@ +mod group_acl; + +pub use group_acl::*; diff --git a/src/component/cyfs-stack/src/group_api/mod.rs b/src/component/cyfs-stack/src/group_api/mod.rs new file mode 100644 index 000000000..29e257330 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/mod.rs @@ -0,0 +1,7 @@ +mod acl; +mod router; +mod service; + +pub(crate) use acl::*; +pub(crate) use router::*; +pub(crate) use service::*; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs new file mode 100644 index 000000000..2c1a2841f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyResult, DeviceId, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::{ + forward::ForwardProcessorManager, + group::{GroupInputProcessor, GroupInputProcessorRef, GroupInputTransformer}, + group_api::GroupAclInnerInputProcessor, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupServiceRouter { + processor: GroupInputProcessorRef, + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, +} + +impl GroupServiceRouter { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + processor: GroupInputProcessorRef, + ) -> GroupInputProcessorRef { + let processor = GroupAclInnerInputProcessor::new(processor); + let ret = Self { + processor, + zone_manager, + forward, + }; + Arc::new(ret) + } + + async fn get_forward( + &self, + dec_id: ObjectId, + target: DeviceId, + ) -> BuckyResult { + let requestor = self.forward.get(&target).await?; + let group_requestor = GroupRequestor::new(dec_id, requestor); + Ok(GroupInputTransformer::new( + group_requestor.clone_processor(), + )) + } + + // 不同于non/ndn的router,如果target为空,那么表示本地device + async fn get_target(&self, target: Option<&ObjectId>) -> BuckyResult> { + let ret = match target { + Some(object_id) => { + let info = self + .zone_manager + .target_zone_manager() + .resolve_target(Some(object_id)) + .await?; + if info.target_device == *self.zone_manager.get_current_device_id() { + None + } else { + Some(info.target_device) + } + } + None => None, + }; + + Ok(ret) + } + + async fn get_processor( + &self, + dec_id: ObjectId, + target: Option<&ObjectId>, + ) -> BuckyResult { + if let Some(device_id) = self.get_target(target).await? { + debug!("group target resolved: {:?} -> {}", target, device_id); + let processor = self.get_forward(dec_id, device_id).await?; + Ok(processor) + } else { + Ok(self.processor.clone()) + } + } + + pub async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + pub async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupServiceRouter { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs new file mode 100644 index 000000000..e14691b5e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc}; +use cyfs_core::{GroupProposal, GroupProposalObject}; +use cyfs_group::GroupManager; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; + +#[derive(Clone)] +pub(crate) struct LocalGroupService { + group_manager: GroupManager, +} + +impl LocalGroupService { + pub(crate) fn new(group_manager: GroupManager) -> Self { + Self { group_manager } + } + + pub fn clone_processor(&self) -> GroupInputProcessorRef { + Arc::new(self.clone()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for LocalGroupService { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.group_manager + .find_rpath_service( + &req.group_id, + &req_common.source.dec, + req.rpath.as_str(), + true, + ) + .await + .map(|_| GroupStartServiceInputResponse {}) + .map_err(|err| { + log::error!( + "group start service {}-{}-{} failed {:?}", + req.group_id, + req_common.source.dec, + req.rpath, + err + ); + err + }) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let proposal_id = req.desc().object_id(); + let rpath = req.rpath().clone(); + if &req_common.source.dec != rpath.dec_id() { + let msg = format!( + "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + req_common.source.dec + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let service = self + .group_manager + .find_rpath_service( + req.rpath().group_id(), + &req_common.source.dec, + rpath.rpath(), + true, + ) + .await + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed when find the service {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + })?; + + service + .push_proposal(req) + .await + .map(|_| GroupPushProposalInputResponse {}) + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + }) + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/mod.rs b/src/component/cyfs-stack/src/group_api/router/mod.rs new file mode 100644 index 000000000..877b4eff6 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/mod.rs @@ -0,0 +1,5 @@ +mod group_service_router; +mod local_service; + +pub use group_service_router::*; +pub(crate) use local_service::*; diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs new file mode 100644 index 000000000..f01f2eaa5 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -0,0 +1,125 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; + +use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; + +#[derive(Clone)] +pub(crate) struct GroupRequestHandler { + processor: GroupInputProcessorRef, +} + +impl GroupRequestHandler { + pub fn new(processor: GroupInputProcessorRef) -> Self { + Self { processor } + } + + // 解析通用header字段 + fn decode_common_headers( + req: &NONInputHttpRequest, + ) -> BuckyResult { + // req_path + let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( + &req.request, + cyfs_base::CYFS_REQ_PATH, + )?; + + // 尝试提取flags + let flags: Option = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; + + // 尝试提取default_action字段 + let level = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; + + // 尝试提取target字段 + let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; + + let ret = NONInputRequestCommon { + req_path, + source: req.source.clone(), + level: level.unwrap_or_default(), + target, + flags: flags.unwrap_or(0), + }; + + Ok(ret) + } + + // group/start-service + pub async fn process_start_service( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_start_service(req).await { + Ok(_resp) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_start_service( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + let common = Self::decode_common_headers(&req)?; + + // 提取body里面的object对象,如果有的话 + let body = req.request.body_json().await.map_err(|e| { + let msg = format!("group start service failed, read body bytes error! {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidParam, msg) + })?; + + let req = GroupStartServiceInputRequest::decode_json(&body)?; + + self.processor.start_service(common, req).await + } + + pub async fn process_push_proposal( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_push_proposal(req).await { + Ok(_) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_push_proposal( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + // 检查action + // let action = Self::decode_action(&req, NONAction::PutObject)?; + // if action != NONAction::PutObject { + // let msg = format!("invalid non put_object action! {:?}", action); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + // } + + let common = Self::decode_common_headers(&req)?; + let object = NONRequestorHelper::decode_object_info(&mut req.request).await?; + let (proposal, remain) = GroupProposal::raw_decode(object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + // let access: Option = + // RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_ACCESS)?; + // let access = access.map(|v| AccessString::new(v)); + + info!("recv push proposal: {}", object.object_id); + + self.processor.push_proposal(common, proposal).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs new file mode 100644 index 000000000..163228d1f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -0,0 +1,77 @@ +use cyfs_lib::RequestProtocol; +use tide::Response; + +use crate::{non::NONInputHttpRequest, ZoneManagerRef}; + +use super::GroupRequestHandler; + +enum GroupRequestType { + StartService, + PushProposal, +} + +pub(crate) struct GroupRequestHandlerEndpoint { + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, +} + +impl GroupRequestHandlerEndpoint { + fn new( + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, + ) -> Self { + Self { + zone_manager, + protocol, + req_type, + handler, + } + } + + async fn process_request(&self, req: tide::Request) -> Response { + let req = match NONInputHttpRequest::new(&self.zone_manager, &self.protocol, req).await { + Ok(v) => v, + Err(resp) => return resp, + }; + match self.req_type { + GroupRequestType::StartService => self.handler.process_start_service(req).await, + GroupRequestType::PushProposal => self.handler.process_push_proposal(req).await, + } + } + + pub fn register_server( + zone_manager: &ZoneManagerRef, + protocol: &RequestProtocol, + handler: &GroupRequestHandler, + server: &mut tide::Server<()>, + ) { + server.at("/group/start-service").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::StartService, + handler.clone(), + )); + + server.at("group/push-proposal").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::PushProposal, + handler.clone(), + )); + } +} + +#[async_trait::async_trait] +impl tide::Endpoint for GroupRequestHandlerEndpoint +where + State: Clone + Send + Sync + 'static, +{ + async fn call(&self, req: tide::Request) -> tide::Result { + let resp = self.process_request(req).await; + Ok(resp) + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_service.rs b/src/component/cyfs-stack/src/group_api/service/group_service.rs new file mode 100644 index 000000000..3a25e282e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_service.rs @@ -0,0 +1,35 @@ +use cyfs_group::GroupManager; + +use crate::{ + forward::ForwardProcessorManager, + group::GroupInputProcessorRef, + group_api::{GroupServiceRouter, LocalGroupService}, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupService { + router: GroupInputProcessorRef, + local_service: LocalGroupService, +} + +impl GroupService { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + group_manager: GroupManager, + ) -> Self { + let local_service = LocalGroupService::new(group_manager); + let router = + GroupServiceRouter::new(forward, zone_manager, local_service.clone_processor()); + + Self { + router, + local_service, + } + } + + pub(crate) fn clone_processor(&self) -> GroupInputProcessorRef { + self.router.clone() + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/mod.rs b/src/component/cyfs-stack/src/group_api/service/mod.rs new file mode 100644 index 000000000..1140a741d --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/mod.rs @@ -0,0 +1,7 @@ +mod group_service; +mod group_listener; +mod group_handler; + +pub(crate) use group_service::*; +pub(crate) use group_listener::*; +pub(crate) use group_handler::*; diff --git a/src/component/cyfs-stack/src/interface/http_listener.rs b/src/component/cyfs-stack/src/interface/http_listener.rs index 21b6e86e3..e9ef12523 100644 --- a/src/component/cyfs-stack/src/interface/http_listener.rs +++ b/src/component/cyfs-stack/src/interface/http_listener.rs @@ -1,6 +1,7 @@ use crate::acl::AclManagerRef; use crate::crypto_api::*; use crate::front::{FrontProtocolHandler, FrontRequestHandlerEndpoint}; +use crate::group_api::{GroupRequestHandler, GroupRequestHandlerEndpoint, GroupService}; use crate::name::NameResolver; use crate::ndn_api::*; use crate::non_api::*; @@ -75,6 +76,7 @@ impl ObjectHttpListener { global_state_meta: &GlobalStateMetaService, name_resolver: &NameResolver, zone_manager: &ZoneManagerRef, + group_service: &GroupService, ) -> Self { let mut server = new_server(); @@ -225,6 +227,15 @@ impl ObjectHttpListener { &mut server, ); + // group manager + let handler = GroupRequestHandler::new(group_service.clone_processor()); + GroupRequestHandlerEndpoint::register_server( + zone_manager, + &protocol, + &handler, + &mut server, + ); + Self { server } } diff --git a/src/component/cyfs-stack/src/interface/listener_manager.rs b/src/component/cyfs-stack/src/interface/listener_manager.rs index c6b5510be..76d3c4e9d 100644 --- a/src/component/cyfs-stack/src/interface/listener_manager.rs +++ b/src/component/cyfs-stack/src/interface/listener_manager.rs @@ -9,6 +9,7 @@ use crate::acl::AclManagerRef; use crate::app::AuthenticatedAppList; use crate::config::StackGlobalConfig; use crate::events::RouterEventsManager; +use crate::group_api::GroupService; use crate::interface::http_ws_listener::ObjectHttpWSService; use crate::name::NameResolver; use crate::rmeta_api::GlobalStateMetaService; @@ -18,7 +19,7 @@ use crate::stack::ObjectServices; use crate::zone::ZoneRoleManager; use cyfs_base::*; use cyfs_bdt::StackGuard; -use cyfs_lib::{RequestProtocol, BrowserSanboxMode}; +use cyfs_lib::{BrowserSanboxMode, RequestProtocol}; use cyfs_debug::Mutex; use std::net::SocketAddr; @@ -131,6 +132,7 @@ impl ObjectListenerManager { root_state: &GlobalStateService, local_cache: &GlobalStateLocalService, global_state_meta: &GlobalStateMetaService, + group_service: &GroupService, ) { assert!(self.listeners.is_empty()); @@ -151,6 +153,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); @@ -172,18 +175,14 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); let http_server = DefaultHttpServer::new(raw_handler.into(), default_handler.clone()); let http_server = match config.get_stack_params().front.browser_mode { BrowserSanboxMode::None => http_server.into(), - mode @ _ => { - BrowserSanboxHttpServer::new( - http_server.into(), - mode, - ).into() - } + mode @ _ => BrowserSanboxHttpServer::new(http_server.into(), mode).into(), }; self.http_tcp_server = Some(http_server); } @@ -202,6 +201,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); diff --git a/src/component/cyfs-stack/src/lib.rs b/src/component/cyfs-stack/src/lib.rs index c180fe861..832029d33 100644 --- a/src/component/cyfs-stack/src/lib.rs +++ b/src/component/cyfs-stack/src/lib.rs @@ -29,6 +29,8 @@ mod config; mod front; mod rmeta_api; mod rmeta; +mod group; +mod group_api; pub use stack::*; pub use storage::*; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 8cf9bcad0..493f6ace8 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -10,6 +10,7 @@ use crate::crypto_api::{CryptoService, ObjectCrypto, ObjectVerifier}; use crate::events::RouterEventsManager; use crate::forward::ForwardProcessorManager; use crate::front::FrontService; +use crate::group_api::GroupService; use crate::interface::{ ObjectListenerManager, ObjectListenerManagerParams, ObjectListenerManagerRef, }; @@ -105,7 +106,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupManager, + group_service: GroupService, } impl CyfsStackImpl { @@ -437,6 +438,8 @@ impl CyfsStackImpl { bdt_stack.clone(), global_state_manager.clone_processor(), )?; + let group_service = + GroupService::new(forward_manager.clone(), zone_manager.clone(), group_manager); let mut stack = Self { config, @@ -474,7 +477,7 @@ impl CyfsStackImpl { acl_manager, - group_manager, + group_service, }; // init an system-dec router-handler processor for later use @@ -564,6 +567,7 @@ impl CyfsStackImpl { &stack.root_state, &stack.local_cache, &stack.global_state_meta, + &stack.group_service, ); let interface = Arc::new(interface); @@ -1163,8 +1167,8 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupManager { - &self.stack.group_manager + pub fn group_service(&self) -> &GroupService { + &self.stack.group_service } // use system dec as default dec From 5707639312abb1f287723be405922fc2b72bc018 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Mar 2023 17:39:29 +0800 Subject: [PATCH 406/553] Remove several unused import --- src/component/cyfs-group-lib/src/request_codec.rs | 2 +- src/component/cyfs-group-lib/src/requestor.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 58404d6b0..4c7ddfe88 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 462b1df85..341bff3e3 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -4,7 +4,7 @@ use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, CYFS_API_LEVEL, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, }; @@ -116,7 +116,7 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupStartServiceOutputResponse::decode_string(&body).map_err(|e| { // error!( // "decode group start service resp from body string error: body={} {}", // body, e, @@ -179,9 +179,9 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { // error!( - // "decode group start service resp from body string error: body={} {}", + // "decode group push proposal resp from body string error: body={} {}", // body, e, // ); // e From bea4e0d2ecce1198f55e6d349e677ef52c95734e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 19:19:00 +0800 Subject: [PATCH 407/553] Debug --- src/component/cyfs-group-lib/Cargo.toml | 1 - .../cyfs-group-lib/src/group_manager.rs | 138 +++++- src/component/cyfs-group-lib/src/requestor.rs | 11 +- .../cyfs-group/src/dec/group_events.rs | 43 +- .../cyfs-group/src/dec/group_manager.rs | 10 +- .../cyfs-group/src/dec/rpath_service.rs | 7 +- .../src/group_api/service/group_listener.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 21 +- .../cyfs-stack/src/zone/zone_manager.rs | 20 +- src/tests/group-example/Cargo.toml | 4 +- src/tests/group-example/src/main.rs | 436 ++++++++---------- 11 files changed, 407 insertions(+), 288 deletions(-) diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index 740b303cd..68931728c 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -32,5 +32,4 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f442d5c55..61a11698d 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -7,7 +7,7 @@ use cyfs_base::{ }; use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -68,11 +68,14 @@ impl GroupManager { // TODO: other filters? only local zone let filter = format!( - "obj_type == {} && dec_id == {}", + "obj_type == {} && source.dec_id == {} && source.zone_category == {}", CoreObjectType::GroupCommand as u16, dec_id, + DeviceZoneCategory::CurrentZone.to_string(), ); + // let filter = "*".to_string(); + router_handler_manager .post_object() .add_handler( @@ -80,7 +83,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - None, + Some("group-inner".to_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) @@ -120,7 +123,38 @@ impl GroupManager { rpath: String, delegate: Box, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap().clone(); + + { + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(&dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath.as_str())); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + RPathService::new( + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + Ok(service.clone()) + } } pub async fn find_rpath_service( @@ -128,7 +162,20 @@ impl GroupManager { group_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap(); + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + found.map_or( + Err(BuckyError::new( + BuckyErrorCode::NotFound, + "please start the service first", + )), + |service| Ok(service.clone()), + ) } pub async fn rpath_client( @@ -204,6 +251,16 @@ impl GroupManager { ) .await .map(|_| ()) + .map_err(|err| { + log::warn!( + "group on_new_rpath {}-{:?}-{} failed, err: {:?}", + cmd.group_id, + self.0.stack.dec_id(), + cmd.rpath, + err + ); + err + }) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { @@ -216,11 +273,27 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; Ok(GroupCommandExecuteResult { result_state_id: result.result_state_id.take(), @@ -239,7 +312,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_verify find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -250,6 +331,14 @@ impl GroupManager { service .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) .await + .map_err(|err| { + log::warn!( + "group on_verify {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + }) } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { @@ -262,7 +351,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_commited find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -361,27 +458,38 @@ impl EventListenerAsyncRoutine BuckyResult { let req_common = ¶m.request.common; - if req_common.level != NONAPILevel::NOC - || req_common.source.zone.zone != self.0.local_zone + let obj = ¶m.request.object; + + log::debug!( + "group-command handle, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) + ); + + if !req_common.source.zone.is_current_zone() || self.0.local_zone.is_none() + // || req_common.source.zone.zone != self.0.local_zone || self.0.stack.dec_id().is_none() { log::warn!( - "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", req_common.level, req_common.source.zone, self.0.local_zone, - self.0.stack.dec_id() + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) ); return Ok(RouterHandlerPostObjectResult { - action: RouterHandlerAction::Reject, + action: RouterHandlerAction::Pass, request: None, response: None, }); } - let obj = ¶m.request.object; match obj.object.as_ref() { None => { return Ok(RouterHandlerPostObjectResult { diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 341bff3e3..b77f93dad 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -6,7 +6,8 @@ use cyfs_base::{ }; use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ - HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, + HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, + RequestorHelper, }; use http_types::{Method, Request, Url}; @@ -43,7 +44,7 @@ impl GroupRequestor { fn encode_common_headers( &self, - // action: NONAction, + action: NONAction, com_req: &NONOutputRequestCommon, http_req: &mut Request, ) { @@ -56,7 +57,7 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); @@ -98,7 +99,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -156,7 +157,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 9bda7e340..a25accb19 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,9 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -32,13 +35,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -78,13 +86,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -111,16 +124,26 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd + .to_vec() + .expect(format!("on_commited {} failed for encode", self.non_driver.dec_id()).as_str()); + let any_obj = cyfs_base::AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(object_raw_buf.as_slice()).expect( + format!( + "on_commited {} failed for convert to any", + self.non_driver.dec_id() + ) + .as_str(), + ), + ); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec().expect( - format!("on_commited {} failed for encode", self.non_driver.dec_id()) - .as_str(), - ), - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7a9708ccc..579f63831 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawConvertTo, RsaCPUObjectSigner, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; @@ -488,6 +488,10 @@ impl GroupManager { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); let result = self .local_info() .non_driver @@ -495,8 +499,8 @@ impl GroupManager { dec_id, NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index b4b90972f..1f2e836a1 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -66,6 +66,11 @@ impl RPathService { } pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + log::info!( + "group({:?}) push proposal {}", + self.rpath(), + proposal.desc().object_id() + ); self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 163228d1f..47be52927 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").post(Self::new( + server.at("/group/start-service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").post(Self::new( + server.at("group/push-proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9333e7981..fa136b3fa 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::NOC, + level: NONAPILevel::Router, target: None, flags: 0, @@ -90,10 +90,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { obj: NONObjectInfo, to: Option<&ObjectId>, ) -> BuckyResult> { + let obj_type_code = obj.object_id.obj_type_code(); + let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some("group-inner".to_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -105,7 +108,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, @@ -114,5 +117,15 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) .await .map(|resp| resp.object) + .map_err(|err| { + log::warn!( + "group post object(type={:?}/{:?}) to {:?} failed {:?}", + obj_type_code, + obj_type, + to, + err + ); + err + }) } } diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 6819b991d..61f284bc4 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -652,7 +652,25 @@ impl ZoneManager { owner_id, work_mode, list ); - return Ok((work_mode, list.to_owned())); + if obj_type == ObjectTypeCode::People { + return Ok((work_mode, list.to_owned())); + } else if obj_type == ObjectTypeCode::Group { + let group = owner_object.into_group(); + // TODO: 先简单处理,找最近的OOD,后面可能要依据具体操作向不同身份发起请求; + // 比如:读操作向任意member请求即可 + let list = group + .ood_list_with_distance( + self.get_current_device_id().object_id(), + ) + .into_iter() + .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) + .map(|id| DeviceId::try_from(id).unwrap()) + .collect(); + return Ok((work_mode, list)); + } else { + unreachable!() + } + /* let ood_device_id = list[0].clone(); let obj_type = ood_device_id.object_id().obj_type_code(); diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 01094f12a..2cf31aba9 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -23,9 +23,9 @@ cyfs-core = { path = '../../component/cyfs-core' } cyfs-bdt = { path = '../../component/cyfs-bdt' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } -cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 88450ac1b..e74f3c5d6 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,36 +1,43 @@ -use std::{clone, sync::Arc, time::Duration}; +use std::{clone, collections::HashSet, sync::Arc, time::Duration}; +use async_std::sync::Mutex; use cyfs_base::{ AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_group::IsCreateRPath; +use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, - NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, + NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, + RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; +use crate::{ + Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}, + GroupDecService::MyRPathDelegate, +}; mod Common { - use std::{fmt::format, io::ErrorKind, sync::Arc}; + use std::{ + fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, + }; - use async_std::{fs, stream::StreamExt}; + use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId, DecAppObj}; - use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_core::{DecApp, DecAppId}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, @@ -348,6 +355,8 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, + rpc_port: u16, + ws_port: u16, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -369,13 +378,19 @@ mod Common { config: CyfsStackConfigParams { isolate: Some(device.desc().object_id().to_string()), sync_service: false, - shared_stack: false, + shared_stack: true, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], - tcp_listeners: vec![], - ws_listener: None, + tcp_listeners: vec![SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + rpc_port, + ))], + ws_listener: Some(SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + ws_port, + ))), }, meta: CyfsStackMetaParams { target: MetaMinerTarget::Dev, @@ -454,9 +469,20 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, - ) -> CyfsStack { - let params = - init_stack_params(people, private_key, device, admins, members, group, dec_app); + rpc_port: u16, + ws_port: u16, + ) -> (CyfsStack, SharedCyfsStack) { + let params = init_stack_params( + people, + private_key, + device, + admins, + members, + group, + dec_app, + rpc_port, + ws_port, + ); log::info!("cyfs-stack.open"); @@ -468,14 +494,23 @@ mod Common { }) .unwrap(); - stack + async_std::task::sleep(Duration::from_millis(1000)).await; + + let shared_stack = + SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) + .await + .unwrap(); + + shared_stack.wait_online(None).await.unwrap(); + + (stack, shared_stack) } } mod Client { // use cyfs_base::ObjectId; // use cyfs_core::GroupProposal; - // use cyfs_group::RPathClient; + // use cyfs_group_lib::RPathClient; // pub struct DecClient {} @@ -505,12 +540,14 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathService; + use cyfs_group_lib::{ + DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, + RPathService, + }; use cyfs_lib::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, - NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, SharedCyfsStack, }; - use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -518,16 +555,18 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { - let group_mgr = cyfs_stack.group_mgr(); - - group_mgr - .register( - dec_app_id.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), - ) - .await - .unwrap(); + pub async fn run( + cyfs_stack: &SharedCyfsStack, + local_name: String, + dec_app_id: DecAppId, + ) -> GroupManager { + let group_mgr = GroupManager::open( + cyfs_stack.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + &cyfs_lib::CyfsStackRequestorType::Http, + ) + .await + .unwrap(); // let source = RequestSourceInfo { // protocol: todo!(), @@ -541,6 +580,8 @@ mod GroupDecService { // .handlers(&RouterHandlerChain::PostRouter) // .post_object() // .add_handler(RouterHandler::new()); + + group_mgr } } @@ -570,7 +611,7 @@ mod GroupDecService { impl GroupRPathDelegateFactory { pub fn is_accept( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, ) -> bool { @@ -583,27 +624,18 @@ mod GroupDecService { impl DelegateFactory for GroupRPathDelegateFactory { async fn create_rpath_delegate( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { + if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } } pub struct MyRPathDelegate { @@ -621,73 +653,19 @@ mod GroupDecService { } impl MyRPathDelegate { - // pub async fn get_value_from_state_tree_with_single_op_envs( - // pre_state_id: Option, - // object_map_processor: &dyn GroupObjectMapProcessor, - // ) -> BuckyResult<( - // Option, - // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - // )> { - // let mut single_op_envs = vec![]; - // let mut parent_map_id = pre_state_id; - // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - // let single_op_env = object_map_processor.create_single_op_env().await.expect( - // format!( - // "create_single_op_env load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // parent_map_id = match parent_map_id { - // Some(parent_map_id) => { - // single_op_env.load(&parent_map_id).await.expect( - // format!( - // "load folder {} parent with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // single_op_env.get_by_key(folder).await.expect( - // format!( - // "load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ) - // } - // None => { - // single_op_env - // .create_new(ObjectMapSimpleContentType::Map) - // .await - // .expect( - // format!( - // "create folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // None - // } - // }; - // single_op_envs.push((single_op_env, folder, parent_map_id)); - // } - - // Ok((parent_map_id, single_op_envs)) - // } - pub async fn execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); - let pre_value = match pre_state_id { - Some(pre_state_id) => { - state_op_env.load(&pre_state_id).await?; + let prev_value = match prev_state_id { + Some(prev_state_id) => { + state_op_env.load(prev_state_id.to_owned()).await?; state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -708,13 +686,13 @@ mod GroupDecService { let result_value = { /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_value.map_or(0, |pre_value| { - let buf = pre_value.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + let prev_value = prev_value.map_or(0, |prev_value| { + let buf = prev_value.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let delta_buf = proposal.params().as_ref().unwrap().as_slice(); @@ -722,7 +700,7 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let value = pre_value + delta; + let value = prev_value + delta; ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() @@ -731,13 +709,13 @@ mod GroupDecService { let result_state_id = { state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) .await .expect( format!( "set_with_path {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), @@ -746,34 +724,11 @@ mod GroupDecService { format!( "commit {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), ) - // let mut sub_folder_value = result_value; - // for (parent_single_op_env, folder, sub_folder_prev_value) in - // single_op_envs.into_iter().rev() - // { - // parent_single_op_env - // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - // .await - // .expect( - // format!( - // "update folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // sub_folder_value = parent_single_op_env.commit().await.expect( - // format!( - // "commit folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // } - // sub_folder_value }; let receipt = { @@ -791,11 +746,11 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_value + proposal + context + * (result_state_id, return_object) = prev_value + proposal + context */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id), + result_state_id: Some(result_state_id.root), receipt, }) } @@ -803,21 +758,21 @@ mod GroupDecService { pub async fn verify( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult { + ) -> BuckyResult<()> { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context + * == prev_state_id + proposal + execute_result.context */ let result = self - .execute(proposal, pre_state_id, object_map_processor) + .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", - pre_state_id, + prev_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), @@ -830,7 +785,11 @@ mod GroupDecService { && execute_result.context.is_none() && execute_result.receipt.is_none(); - Ok(is_ok) + if is_ok { + Ok(()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "result unmatch")) + } } } @@ -839,31 +798,36 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id, object_map_processor) + self.execute(proposal, prev_state_id, object_map_processor) .await } async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, object_map_processor, execute_result) - .await + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<()> { + self.verify( + proposal, + prev_state_id, + object_map_processor, + execute_result, + ) + .await } async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 @@ -872,16 +836,16 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = match pre_state_id { - Some(pre_state_id) => { + let prev_value = match prev_state_id { + Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&pre_state_id) + .load(*prev_state_id) .await - .expect(format!("load {} failed", pre_state_id).as_str()); + .expect(format!("load {} failed", prev_state_id).as_str()); state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -892,21 +856,21 @@ mod GroupDecService { } None => None, } - .map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + .map_or(0, |prev_state_id| { + let buf = prev_state_id.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let result_value = match execute_result.result_state_id { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&result_state_id) + .load(result_state_id) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -932,7 +896,7 @@ mod GroupDecService { "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, - pre_value, + prev_value, result_value, proposal_id, block.block_id(), @@ -942,10 +906,6 @@ mod GroupDecService { let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); assert!(is_new_finished); } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() - } } } @@ -982,6 +942,7 @@ async fn main_run() { cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) .exit_on_panic(true) + .dingtalk_bug_report("any value to disable") .build() .start(); @@ -1004,9 +965,12 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec = vec![]; + let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; + let mut group_mgrs: Vec = vec![]; + let mut rpc_port = 32217_u16; + let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { - let cyfs_stack = create_stack( + let (cyfs_stack, shared_stack) = create_stack( admin, private_key, device, @@ -1020,33 +984,34 @@ async fn main_run() { .collect(), &group, &dec_app, + rpc_port, + ws_port, ) .await; - admin_stacks.push(cyfs_stack); + admin_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; } async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { - let stack = admin_stacks.get(i).unwrap(); + let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); - DecService::run( - &stack, - admin.name().unwrap().to_string(), - dec_app_id.clone(), - ) - .await; - - let service = stack - .group_mgr() - .find_rpath_service( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, + let local_name = admin.name().unwrap(); + let group_mgr = + DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; + + let service = group_mgr + .start_rpath_service( + group.desc().object_id(), + EXAMPLE_RPATH.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), ) .await .unwrap(); + + group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1057,7 +1022,8 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, @@ -1066,42 +1032,31 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); - let noc = stack.noc_manager().clone(); + let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); let proposal_any = Arc::new(AnyNamedObject::Core( TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), )); - let req = NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: dec_app_id.object_id().clone(), - verified: None, + let req = NONPutObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: None, + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: Some(AccessString::full().value()), + access: Some(AccessString::full()), }; - noc.put_object(&req).await; + noc.put_object(req).await; proposals.push(proposal); } @@ -1112,20 +1067,15 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); async_std::task::spawn(async move { - service.push_proposal(proposal).await.unwrap(); + service.push_proposal(&proposal).await.unwrap(); }); if i % 10 == 0 { @@ -1136,27 +1086,25 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - let client = admin_stacks - .get(0) - .unwrap() - .group_mgr() - .rpath_client( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - ) - .await - .unwrap(); - - let value_obj = client - .get_by_path(EXAMPLE_VALUE_PATH.as_str()) - .await - .unwrap(); - let buf = value_obj.as_ref().unwrap().object_id.data(); - let mut value = [0u8; 8]; - value.copy_from_slice(&buf[..8]); - - log::info!("value from client is: {}", u64::from_be_bytes(value)); + // let client = group_mgrs + // .get(0) + // .unwrap() + // .rpath_client( + // &group.desc().object_id(), + // dec_app_id.object_id(), + // &EXAMPLE_RPATH, + // ) + // .await; + + // let value_obj = client + // .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + // .await + // .unwrap(); + // let buf = value_obj.as_ref().unwrap().object_id.data(); + // let mut value = [0u8; 8]; + // value.copy_from_slice(&buf[..8]); + + // log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From a0e2a1e639c6514b239ce5b5e7da707a3b760995 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 408/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/service/ood-daemon/src/config/system_config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index ceb3344e9..670ea5832 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -62,6 +62,13 @@ impl SystemConfig { let node = Self::load_as_toml(&config_file)?; + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) + } + self.parse_config(node).await } @@ -206,4 +213,3 @@ pub async fn reload_system_config() -> BuckyResult { pub fn get_system_config() -> Arc { SYSTEM_CONFIG.lock().unwrap().clone().unwrap() -} \ No newline at end of file From 2b4925acf64788b20b6ada98f439a6836e3364e0 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 409/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/service/ood-daemon/src/config/system_config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 670ea5832..e27890656 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -3,6 +3,7 @@ use super::version::{ServiceListVersion, ServiceVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -64,8 +65,6 @@ impl SystemConfig { self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } From 07cd55e9c4fb237fa39a9b3b8a513c6a41f060c5 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 410/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index e11695ad5..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1811,6 +1811,7 @@ dependencies = [ "cyfs-base", "cyfs-bdt", "cyfs-util", + "generic-array 0.12.4", "hex", "int-enum", "log 0.4.17", @@ -1824,6 +1825,7 @@ dependencies = [ "semver 1.0.16", "serde", "serde_json", + "sha2 0.8.2", ] [[package]] @@ -1873,6 +1875,65 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "cyfs-group" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "http-types", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "cyfs-lib" version = "0.8.1" @@ -2226,6 +2287,8 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", @@ -3314,6 +3377,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group-example" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-bdt-ext", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-stack", + "cyfs-util", + "futures", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "protobuf", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + [[package]] name = "h2" version = "0.3.15" From 107917c83ac9f065f30dd8f0bf96c0f74d6d1a13 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 411/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From c4626c5c2e9fbb5a56367ed0df2dbf8e50cc750c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 14:48:12 +0800 Subject: [PATCH 412/553] Adapte to the buckyos --- .../engine/storage_engine_group_state.rs | 44 ++++++++++++++++--- .../cyfs-group/src/storage/group_storage.rs | 9 +++- src/meta/cyfs-meta/src/executor/view.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 029b09e78..cf04e93ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -19,6 +19,8 @@ const ACCESS: Option = None; #[derive(Clone)] pub struct StorageEngineGroupState { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, state_path: Arc, } @@ -183,18 +185,28 @@ impl StorageEngineGroupState { Ok(cache) } - pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + pub fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: GroupStatePath, + group_id: ObjectId, + dec_id: ObjectId, + ) -> Self { Self { state_mgr, state_path: Arc::new(state_path), + group_id, + dec_id, } } pub async fn create_writer(&self) -> BuckyResult { - Ok( - StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) - .await?, + Ok(StorageEngineGroupStateWriter::new( + self.state_mgr.clone(), + self.state_path.clone(), + self.group_id, + self.dec_id, ) + .await?) } pub fn root_cache(&self) -> &ObjectMapRootCacheRef { @@ -218,6 +230,8 @@ impl StorageEngine for StorageEngineGroupState { #[derive(Clone)] pub struct StorageEngineGroupStateWriter { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, op_env: ObjectMapPathOpEnvRef, prepare_op_env: ObjectMapSingleOpEnvRef, @@ -230,6 +244,8 @@ impl StorageEngineGroupStateWriter { async fn new( state_mgr: ObjectMapRootManagerRef, state_path: Arc, + group_id: ObjectId, + dec_id: ObjectId, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; @@ -237,7 +253,11 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(group_id), + Some(dec_id), + ) .await?; None } else { @@ -254,6 +274,8 @@ impl StorageEngineGroupStateWriter { state_mgr, prepare_map_id, write_result: Ok(()), + group_id, + dec_id, }) } @@ -264,7 +286,11 @@ impl StorageEngineGroupStateWriter { ) -> BuckyResult { let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; single_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(self.group_id), + Some(self.dec_id), + ) .await?; single_op_env .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) @@ -463,7 +489,11 @@ impl StorageEngineGroupStateWriter { } add_single_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new( + ObjectMapSimpleContentType::Set, + Some(self.group_id), + Some(self.dec_id), + ) .await?; } else { add_single_op_env diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a762c1b6..78af14c4b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -81,6 +81,8 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), + group_id.clone(), + dec_id.clone(), ), local_device_id, cache: StorageCacheInfo::new(None), @@ -138,7 +140,12 @@ impl GroupStorage { rpath: rpath.to_string(), non_driver, group_chunk_id: group_chunk_id.object_id(), - storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + state_path, + group_id.clone(), + dec_id.clone(), + ), local_device_id, cache, object_map_processor, diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 7d76e9fcc..47e3c8a7d 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -5,7 +5,7 @@ use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; use crate::stat::Stat; use crate::state_storage::{StateRef, StateWeakRef}; -use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base::{BuckyResult, RawConvertTo, ObjectId}; use cyfs_base_meta::*; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; From 17e47c516738bf4133bdedc994ecce40b37dedc5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 18:53:20 +0800 Subject: [PATCH 413/553] Adapt interface of RootState, add param(owner) --- src/tests/group-example/src/main.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 361bfd35a..01d57996b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -547,8 +547,8 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, SharedCyfsStack, + CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, + RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -677,7 +677,12 @@ mod GroupDecService { } None => { state_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new_with_option( + ObjectMapSimpleContentType::Map, + &CreateObjectMapOption::new_with_owner( + proposal.rpath().group_id().clone(), + ), + ) .await .expect( format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), From 23d567776d2cdafae5657be3a8ea2b164aa48e73 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 15:13:47 +0800 Subject: [PATCH 414/553] Testcase for client --- .../cyfs-core/src/group/group_proposal.rs | 1 - .../cyfs-group/src/dec/rpath_service.rs | 20 +- src/tests/group-example/src/main.rs | 231 ++++++++++++------ 3 files changed, 175 insertions(+), 77 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 508418f7b..e011afdf7 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,7 +1,6 @@ use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; -use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index 1f2e836a1..47bd1ffd7 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,8 +1,12 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{ + AnyNamedObject, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + RsaCPUObjectSigner, TypelessCoreObject, +}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; +use cyfs_lib::NONObjectInfo; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, @@ -15,6 +19,7 @@ struct RPathServiceRaw { network_sender: crate::network::Sender, pending_proposal_handle: PendingProposalHandler, hotstuff: Hotstuff, + non_driver: NONDriverHelper, } #[derive(Clone)] @@ -44,7 +49,7 @@ impl RPathService { store, signer, network_sender.clone(), - non_driver, + non_driver.clone(), pending_proposal_consumer, event_notifier, rpath.clone(), @@ -56,6 +61,7 @@ impl RPathService { local_id, rpath, hotstuff, + non_driver, }; Ok(Self(Arc::new(raw))) @@ -71,6 +77,16 @@ impl RPathService { self.rpath(), proposal.desc().object_id() ); + + let object_raw = proposal.to_vec()?; + let any_obj = + AnyNamedObject::Core(TypelessCoreObject::clone_from_slice(object_raw.as_slice())?); + let non_obj = NONObjectInfo::new( + proposal.desc().object_id(), + object_raw, + Some(Arc::new(any_obj)), + ); + self.0.non_driver.put_object(non_obj).await?; self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 01d57996b..b913490f2 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -8,9 +8,9 @@ use cyfs_base::{ use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, - NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, - RequestProtocol, RequestSourceInfo, SharedCyfsStack, + CyfsStackRequestorType, DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, + NONOutputRequestCommon, NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, + NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; @@ -473,7 +473,7 @@ mod Common { dec_app: &DecApp, rpc_port: u16, ws_port: u16, - ) -> (CyfsStack, SharedCyfsStack) { + ) -> (Box, Box) { let params = init_stack_params( people, private_key, @@ -488,20 +488,23 @@ mod Common { log::info!("cyfs-stack.open"); - let stack = CyfsStack::open(params.0, params.1, params.2) - .await - .map_err(|e| { - log::error!("stack start failed: {}", e); - e - }) - .unwrap(); + let stack = Box::new( + CyfsStack::open(params.0, params.1, params.2) + .await + .map_err(|e| { + log::error!("stack start failed: {}", e); + e + }) + .unwrap(), + ); async_std::task::sleep(Duration::from_millis(1000)).await; - let shared_stack = + let shared_stack = Box::new( SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) .await - .unwrap(); + .unwrap(), + ); shared_stack.wait_online(None).await.unwrap(); @@ -539,7 +542,7 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; use cyfs_group_lib::{ @@ -548,7 +551,8 @@ mod GroupDecService { }; use cyfs_lib::{ CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, - RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, + RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, + RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -561,50 +565,82 @@ mod GroupDecService { cyfs_stack: &SharedCyfsStack, local_name: String, dec_app_id: DecAppId, + group_id: ObjectId, + rpath: &str, ) -> GroupManager { let group_mgr = GroupManager::open( cyfs_stack.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), + Box::new(GroupRPathDelegateFactory { + local_name: local_name.clone(), + }), &cyfs_lib::CyfsStackRequestorType::Http, ) .await .unwrap(); - // let source = RequestSourceInfo { - // protocol: todo!(), - // zone: todo!(), - // dec: todo!(), - // verified: todo!(), - // }; + let filter = format!("obj_type == {}", CoreObjectType::GroupProposal as u16,); + let routine = ProposalListener { + service: group_mgr + .start_rpath_service( + group_id, + rpath.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), + ) + .await + .unwrap(), + local_name, + }; - // cyfs_stack - // .router_handlers() - // .handlers(&RouterHandlerChain::PostRouter) - // .post_object() - // .add_handler(RouterHandler::new()); + cyfs_stack + .router_handlers() + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-proposal-listener-{}", dec_app_id).as_str(), + 0, + Some(filter), + Some("group-proposal".to_string()), + RouterHandlerAction::Pass, + Some(Box::new(routine)), + ) + .await + .unwrap(); group_mgr } } - // pub struct PostProposalRoutine { - // service: RPathService, - // } + pub struct ProposalListener { + service: RPathService, + local_name: String, + } - // #[async_trait::async_trait] - // impl EventListenerAsyncRoutine - // for PostProposalRoutine - // { - // async fn call( - // &self, - // param: &NONPostObjectInputRequest, - // ) -> BuckyResult { - // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; - // assert_eq!(remain.len(), 0); - // self.service.push_proposal(proposal).await?; - // Ok(NONPostObjectInputResponse { object: None }) - // } - // } + #[async_trait::async_trait] + impl EventListenerAsyncRoutine + for ProposalListener + { + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + log::info!( + "recv proposal {} from {:?}, local: {}", + param.request.object.object_id, + param.request.common.source.zone, + self.local_name + ); + + let (proposal, remain) = + GroupProposal::raw_decode(param.request.object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + self.service.push_proposal(&proposal).await.unwrap(); + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: None, + }) + } + } pub struct GroupRPathDelegateFactory { local_name: String, @@ -939,6 +975,8 @@ fn create_proposal( async fn main_run() { log::info!("main_run"); + async_std::task::sleep(Duration::from_millis(10000)).await; + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -972,8 +1010,10 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; - let mut group_mgrs: Vec = vec![]; + let mut admin_stacks: Vec<(Box, Box)> = vec![]; + let mut admin_group_mgrs: Vec = vec![]; + let mut member_stacks: Vec<(Box, Box)> = vec![]; + let mut member_group_mgrs: Vec = vec![]; let mut rpc_port = 32217_u16; let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { @@ -1000,25 +1040,60 @@ async fn main_run() { ws_port += 1; } + for ((member, _), (device, private_key)) in members.iter() { + let (cyfs_stack, shared_stack) = create_stack( + member, + private_key, + device, + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + &group, + &dec_app, + rpc_port, + ws_port, + ) + .await; + member_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; + } + async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); let local_name = admin.name().unwrap(); - let group_mgr = - DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; - - let service = group_mgr - .start_rpath_service( - group.desc().object_id(), - EXAMPLE_RPATH.to_string(), - Box::new(MyRPathDelegate::new(local_name.to_string())), - ) - .await - .unwrap(); - group_mgrs.push(group_mgr); + let group_mgr = DecService::run( + &shared_stack, + local_name.to_string(), + dec_app_id.clone(), + group_id, + EXAMPLE_RPATH.as_str(), + ) + .await; + + admin_group_mgrs.push(group_mgr); + } + + for i in 0..member_stacks.len() { + let (_, shared_stack) = member_stacks.get(i).unwrap(); + let ((member, _), _) = members.get(i).unwrap(); + let group_mgr = GroupManager::open_as_client( + shared_stack.as_ref().clone(), + &CyfsStackRequestorType::WebSocket, + ) + .await + .unwrap(); + + member_group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1029,9 +1104,9 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let owner = &members.get(i % members.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, owner.desc().object_id(), @@ -1039,11 +1114,6 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); - let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); @@ -1073,16 +1143,29 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); + let stack = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let ((member, _), _) = members.get(i % members.len()).unwrap(); + let local_name = member.name().map(|n| n.to_string()); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); + let client = group_mgr + .rpath_client(group_id, dec_app_id.clone(), &EXAMPLE_RPATH) + .await; async_std::task::spawn(async move { - service.push_proposal(&proposal).await.unwrap(); + log::info!( + "client {:?} will post proposal {}", + local_name, + proposal.desc().object_id(), + ); + + let result = client.post_proposal(&proposal).await; + log::info!( + "client {:?} post proposal {}, result: {:?}", + local_name, + proposal.desc().object_id(), + result.map(|o| o.map(|o| o.object_id)) + ); }); if i % 10 == 0 { @@ -1093,7 +1176,7 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - // let client = group_mgrs + // let client = admin_group_mgrs // .get(0) // .unwrap() // .rpath_client( From f925d805732c7e6638b36608557e6eac0032948f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 21:16:25 +0800 Subject: [PATCH 415/553] Complete the signature for group --- .../cyfs-group-lib/src/rpath_client.rs | 2 +- .../cyfs-stack/src/resolver/device_manager.rs | 106 +++++++++++++++++- .../cyfs-stack/src/zone/zone_manager.rs | 14 +-- src/tests/group-example/src/main.rs | 51 ++++++--- 4 files changed, 149 insertions(+), 24 deletions(-) diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 7d7c9a613..6474fce9d 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -42,7 +42,7 @@ impl RPathClient { .requestor .post_object(NONPostObjectOutputRequest { common: NONOutputRequestCommon { - req_path: None, + req_path: Some("post-proposal".to_string()), source: None, dec_id: self.0.local_dec_id.clone(), level: NONAPILevel::Router, diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 2a9aa3d56..97e822c31 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -5,6 +5,7 @@ use cyfs_bdt::DeviceCache; use cyfs_lib::*; use async_trait::async_trait; +use std::collections::HashSet; use std::collections::{hash_map::Entry, HashMap}; use std::sync::{Arc, RwLock}; @@ -87,7 +88,7 @@ impl DeviceInfoManagerImpl { self.list.read().unwrap().get(device_id).map(|d| d.clone()) } - async fn verfiy_own_signs( + async fn verfiy_single_own_signs( &self, object_id: &ObjectId, object: &Arc, @@ -122,6 +123,103 @@ impl DeviceInfoManagerImpl { } } + async fn verfiy_group_own_signs( + &self, + object_id: &ObjectId, + object: &Arc, + ) -> BuckyResult<()> { + if object_id.obj_type_code() != ObjectTypeCode::Group { + let msg = format!( + "verify object own's body sign by owner failed for expect group, id = {}", + object_id + ); + warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let group = object.as_group(); + let sign_object_ids = HashSet::::from_iter( + [ + group.admins().iter().map(|m| m.id).collect::>(), + group.members().iter().map(|m| m.id).collect::>(), + ] + .concat() + .into_iter(), + ); + + // all singatures + let results = futures::future::join_all( + sign_object_ids + .into_iter() + .map(|id| self.verify_with_object(object_id.clone(), object.clone(), id)), + ) + .await; + + results + .into_iter() + .find(|r| r.is_err()) + .map_or(Ok(()), |r| r) + } + + async fn verify_with_object( + &self, + object_id: ObjectId, + object: Arc, + signer_id: ObjectId, + ) -> BuckyResult<()> { + let mut signer_obj = self + .obj_searcher + .search_ex(None, &signer_id, ObjectSearcherFlags::full()) + .await + .map_err(|err| { + error!( + "verify object(group) own's body sign find signer failed! id={}, err={:?}", + object_id, err + ); + err + })?; + + let singer_obj_any = signer_obj.object.take(); + let req = VerifyObjectInnerRequest { + sign_type: VerifySignType::Body, + object: ObjectInfo { + object_id: object_id.clone(), + object: object.clone(), + }, + sign_object: VerifyObjectType::Object(NONSlimObjectInfo::new( + signer_id, + Some(signer_obj.object_raw), + singer_obj_any, + )), + }; + + match self.obj_verifier.verify_object_inner(req).await { + Ok(ret) => { + if ret.valid { + info!( + "verify object(group) own's body sign success! id={}", + object_id, + ); + Ok(()) + } else { + let msg = format!( + "verify object(group) own's body sign unmatch! id={}", + object_id, + ); + error!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)) + } + } + Err(e) => { + error!( + "verify object(group) own's body sign by owner error! id={}, {}", + object_id, e + ); + Err(e) + } + } + } + async fn verfiy_owner(&self, device_id: &DeviceId, device: Option<&Device>) -> BuckyResult<()> { let d; let device = match device { @@ -427,7 +525,11 @@ impl DeviceCache for DeviceInfoManager { object_id: &ObjectId, object: &Arc, ) -> BuckyResult<()> { - self.0.verfiy_own_signs(object_id, object).await + if ObjectTypeCode::Group == object_id.obj_type_code() { + self.0.verfiy_group_own_signs(object_id, object).await + } else { + self.0.verfiy_single_own_signs(object_id, object).await + } } fn clone_cache(&self) -> Box { diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 61f284bc4..b96884306 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -646,13 +646,13 @@ impl ZoneManager { match owner_object.ood_list() { Ok(list) => { if list.len() > 0 { - let work_mode = owner_object.ood_work_mode().unwrap().to_owned(); - debug!( - "get ood list from owner object ood_list: owner={}, work_mode={:?}, list={:?}", - owner_id, work_mode, list - ); - if obj_type == ObjectTypeCode::People { + let work_mode = owner_object.ood_work_mode().unwrap().to_owned(); + debug!( + "get ood list from owner object ood_list: owner={}, work_mode={:?}, list={:?}", + owner_id, work_mode, list + ); + return Ok((work_mode, list.to_owned())); } else if obj_type == ObjectTypeCode::Group { let group = owner_object.into_group(); @@ -666,7 +666,7 @@ impl ZoneManager { .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) .map(|id| DeviceId::try_from(id).unwrap()) .collect(); - return Ok((work_mode, list)); + return Ok((OODWorkMode::Standalone, list)); } else { unreachable!() } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b913490f2..d3999ea0a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -29,10 +29,10 @@ mod Common { use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, - GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, - TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, - SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + GroupMember, IpAddr, NamedObject, ObjectDesc, ObjectLink, People, PrivateKey, Protocol, + RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, + StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, + NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; @@ -166,8 +166,8 @@ mod Common { fn create_group( founder: &People, - admins: Vec<&People>, - members: Vec<&People>, + admins: Vec<(&People, &PrivateKey)>, + members: Vec<(&People, &PrivateKey)>, oods: Vec<&Device>, ) -> Group { log::info!("create group"); @@ -176,13 +176,13 @@ mod Common { group.check_org_body_content_mut().set_admins( admins .iter() - .map(|m| GroupMember::from_member_id(m.desc().object_id())) + .map(|m| GroupMember::from_member_id(m.0.desc().object_id())) .collect(), ); group.set_members( members .iter() - .map(|m| GroupMember::from_member_id(m.desc().object_id())) + .map(|m| GroupMember::from_member_id(m.0.desc().object_id())) .collect(), ); group.set_ood_list( @@ -195,6 +195,29 @@ mod Common { log::info!("create group: {:?}", group.desc().object_id()); + let body_hash = group.body().as_ref().unwrap().raw_hash_value().unwrap(); + let signers = [admins, members].concat(); + signers + .into_iter() + .map(|(owner, private_key)| { + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + async_std::task::block_on(async move { + let body_signature = signer + .sign( + body_hash.as_slice(), + &cyfs_base::SignatureSource::Object(ObjectLink { + obj_id: owner.desc().object_id(), + obj_owner: None, + }), + ) + .await + .unwrap(); + body_signature + }) + }) + .for_each(|signature| group.signs_mut().push_body_sign(signature)); + group } @@ -315,8 +338,8 @@ mod Common { } pub async fn init_group( - admins: Vec<&People>, - members: Vec<&People>, + admins: Vec<(&People, &PrivateKey)>, + members: Vec<(&People, &PrivateKey)>, oods: Vec<&Device>, ) -> Group { fs::create_dir_all("./test-group") @@ -340,7 +363,7 @@ mod Common { } } - let group = create_group(admins.get(0).unwrap(), admins, members, oods); + let group = create_group(admins.get(0).unwrap().0, admins, members, oods); fs::write("./test-group/group.desc", group.to_vec().unwrap()) .await .expect("save file ./test-group/group.desc failed"); @@ -976,7 +999,7 @@ async fn main_run() { log::info!("main_run"); async_std::task::sleep(Duration::from_millis(10000)).await; - + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -998,8 +1021,8 @@ async fn main_run() { let admins = init_admins().await; let members = init_members().await; let group = init_group( - admins.iter().map(|m| &m.0 .0).collect(), - members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| (&m.0 .0, &m.0 .1)).collect(), + members.iter().map(|m| (&m.0 .0, &m.0 .1)).collect(), admins.iter().map(|m| &m.1 .0).collect(), ) .await; From e8abf5f7bbad598da2d4129e2c4c0b23632c2240 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Mar 2023 16:49:36 +0800 Subject: [PATCH 416/553] Response for proposal from RPathService --- .../cyfs-group-lib/src/group_manager.rs | 5 +- .../cyfs-group-lib/src/input_request.rs | 5 +- .../cyfs-group-lib/src/output_request.rs | 5 +- src/component/cyfs-group-lib/src/requestor.rs | 56 ++---- .../cyfs-group-lib/src/rpath_client.rs | 7 +- .../cyfs-group-lib/src/rpath_service.rs | 10 +- .../cyfs-group/examples/app_example.rs | 179 ------------------ .../src/consensus/hotstuff/hotstuff.rs | 167 +++++++++------- .../cyfs-group/src/dec/rpath_service.rs | 32 ++-- .../cyfs-stack/src/group/transform.rs | 8 +- .../src/group_api/router/local_service.rs | 2 +- .../src/group_api/service/group_handler.rs | 16 +- .../cyfs-stack/src/stack/group_non_driver.rs | 15 +- src/tests/group-example/src/main.rs | 34 +++- 14 files changed, 215 insertions(+), 326 deletions(-) delete mode 100644 src/component/cyfs-group/examples/app_example.rs diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 61a11698d..07bae1f7a 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -8,7 +8,7 @@ use cyfs_base::{ use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, - NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + NONPostObjectInputResponse, RequestGlobalStatePath, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; @@ -75,6 +75,7 @@ impl GroupManager { ); // let filter = "*".to_string(); + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Some("group/inner-cmd")); router_handler_manager .post_object() @@ -83,7 +84,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - Some("group-inner".to_string()), + Some(req_path.format_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index 0f861ea3c..54df4dda9 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -1,4 +1,5 @@ use cyfs_base::ObjectId; +use cyfs_lib::NONObjectInfo; pub struct GroupStartServiceInputRequest { pub group_id: ObjectId, @@ -7,4 +8,6 @@ pub struct GroupStartServiceInputRequest { pub struct GroupStartServiceInputResponse {} -pub struct GroupPushProposalInputResponse {} +pub struct GroupPushProposalInputResponse { + pub object: Option, +} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index f65e02e3e..964abcc4b 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -1,4 +1,5 @@ use cyfs_base::ObjectId; +use cyfs_lib::NONObjectInfo; #[derive(Debug)] pub struct GroupStartServiceOutputRequest { @@ -8,4 +9,6 @@ pub struct GroupStartServiceOutputRequest { pub struct GroupStartServiceOutputResponse {} -pub struct GroupPushProposalOutputResponse {} +pub struct GroupPushProposalOutputResponse { + pub object: Option, +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index b77f93dad..af17be0c6 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -166,47 +166,29 @@ impl GroupRequestor { let mut resp = self.requestor.request(http_req).await?; - match resp.status() { - code if code.is_success() => { - let body = resp.body_string().await.map_err(|e| { - let msg = format!( - "group push proposal failed, read body string error! req={:?}/{} {}", - proposal.rpath(), + let status = resp.status(); + if status.is_success() { + match status { + http_types::StatusCode::NoContent => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::info!( + "push proposal but empty response! obj={}, {}", proposal_id, e ); - log::error!("{}", msg); - - BuckyError::from(msg) - })?; - - // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { - // error!( - // "decode group push proposal resp from body string error: body={} {}", - // body, e, - // ); - // e - // })?; - - log::debug!( - "group push proposal success, req={:?}/{}", - proposal.rpath(), - proposal_id - ); - - Ok(GroupPushProposalOutputResponse {}) - } - code @ _ => { - let e = RequestorHelper::error_from_resp(&mut resp).await; - log::error!( - "group push proposal failed: rpath={:?}/{}, status={}, {}", - proposal.rpath(), - proposal_id, - code, - e - ); - Err(e) + Err(e) + } + _ => { + log::info!("push proposal success: {}", proposal_id); + let object = NONRequestorHelper::decode_option_object_info(&mut resp).await?; + let ret = GroupPushProposalOutputResponse { object }; + Ok(ret) + } } + } else { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!("push proposal error! object={}, {}", proposal_id, e); + Err(e) } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 6474fce9d..2eaf71315 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -4,6 +4,7 @@ use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, + RequestGlobalStatePath, }; struct RPathClientRaw { @@ -38,11 +39,15 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { + let req_path = RequestGlobalStatePath::new( + Some(proposal.rpath().dec_id().clone()), + Some("group/proposal"), + ); self.0 .requestor .post_object(NONPostObjectOutputRequest { common: NONOutputRequestCommon { - req_path: Some("post-proposal".to_string()), + req_path: Some(req_path.format_string()), source: None, dec_id: self.0.local_dec_id.clone(), level: NONAPILevel::Router, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 66d0d83f4..d6aa6972d 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -3,7 +3,8 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, + HttpRequestorRef, IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SharedCyfsStack, + SingleOpEnvStub, }; use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; @@ -23,7 +24,10 @@ impl RPathService { &self.0.rpath } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { // post http self.0 .requestor @@ -32,7 +36,7 @@ impl RPathService { proposal, ) .await - .map(|_| {}) + .map(|resp| resp.object) } pub(crate) fn new( diff --git a/src/component/cyfs-group/examples/app_example.rs b/src/component/cyfs-group/examples/app_example.rs deleted file mode 100644 index aff70c6d6..000000000 --- a/src/component/cyfs-group/examples/app_example.rs +++ /dev/null @@ -1,179 +0,0 @@ -mod Client { - use cyfs_base::ObjectId; - use cyfs_core::GroupProposal; - use cyfs_group::RPathClient; - - pub struct DecClient {} - - impl DecClient { - async fn do_something(&self, stack: &CyfsStack) { - let rpath_mgr = stack.group_mgr(); - - let rpath_client = rpath_mgr.rpath_client(); - - let field_path = "/xxx/yyy"; - let old_value = rpath_client.get_field(field_path).await; - let param = ObjectId::default(); // param = old_value.value - let proposal = self.make_proposal(param); - rpath_client.post_proposal(proposal).await; - } - - fn make_proposal(&self, param: ObjectId) -> GroupProposal { - unimplemented!() - } - } -} - -mod GroupDecService { - use cyfs_base::*; - use cyfs_core::{DecAppId, GroupConsensusBlock, GroupProposal}; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; - - pub struct DecService {} - - impl DecService { - pub async fn run(stack: &CyfsStack) { - let rpath_mgr = stack.group_mgr(); - - let appid = DecAppId::default(); - let delegate_factory = GroupRPathDelegateFactory {}; - - rpath_mgr.register(appid, delegate_factory) - } - } - - pub struct GroupRPathDelegateFactory {} - - impl GroupRPathDelegateFactory { - pub fn is_accept( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> bool { - // 由应用定义是否接收该rpath,并启动共识过程,参与该rpath的信息维护 - true - } - } - - #[async_trait::async_trait] - impl DelegateFactory for GroupRPathDelegateFactory { - async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { - // 如果接受,就提供该rpath的处理响应对象 - Ok(Box::new(MyRPathDelegate::new())) - } else { - Err(BuckyError::new(BuckyErrorCode::Reject, "")) - } - } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } - } - - pub struct MyRPathDelegate {} - - impl MyRPathDelegate { - pub fn new() -> Self { - MyRPathDelegate {} - } - } - - impl MyRPathDelegate { - pub fn execute( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - ) -> BuckyResult { - let result_state_id = { - /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 - */ - ObjectId::default() - }; - - let receipt = { - /** - * 返回给Client的对象,相当于这个请求的结果或者叫回执? - */ - None - }; - - let context = { - /** - * 执行请求的上下文,运算过程中可能有验证节点无法得到的上下文信息(比如时间戳,随机数) - */ - Some(vec![]) - }; - - /** - * (result_state_id, return_object) = pre_state_id + proposal + context - */ - Ok(ExecuteResult { - context, - result_state_id: Some(result_state_id), - receipt, - }) - } - - pub fn verify( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - execute_result: &ExecuteResult, - ) -> BuckyResult { - /** - * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context - */ - Ok(true) - } - } - - #[async_trait::async_trait] - impl RPathDelegate for MyRPathDelegate { - async fn on_execute( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - ) -> BuckyResult { - self.execute(proposal, pre_state_id) - } - - async fn on_verify( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) - } - - async fn on_commited( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - execute_result: &ExecuteResult, - ) { - // 提交到共识链上了,可能有些善后事宜 - unimplemented!() - } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - // 自定义同步Group版本策略 - unimplemented!() - } - } -} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d2dbcc517..23e2152f1 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -17,7 +17,7 @@ use futures::FutureExt; use itertools::Itertools; use crate::{ - consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::{StatePusher, CallReplyNotifier, CallReplyWaiter}, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, @@ -34,6 +34,7 @@ pub(crate) struct Hotstuff { local_device_id: ObjectId, tx_message: Sender<(HotstuffMessage, ObjectId)>, state_pusher: StatePusher, + proposal_result_notifier: CallReplyNotifier>>, } impl std::fmt::Debug for Hotstuff { @@ -56,6 +57,7 @@ impl Hotstuff { rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); + let proposal_result_notifier = CallReplyNotifier::new(); let state_pusher = StatePusher::new( local_id, @@ -64,40 +66,44 @@ impl Hotstuff { non_driver.clone(), ); - let tx_message_runner = tx_message.clone(); - let state_pusher_runner = state_pusher.clone(); + let mut runner = HotstuffRunner::new( + local_id, + local_device_id, + committee, + store, + signer, + network_sender, + non_driver, + tx_message.clone(), + rx_message, + proposal_consumer, + state_pusher.clone(), + event_notifier, + rpath.clone(), + proposal_result_notifier.clone() + ); - { - let rpath2 = rpath.clone(); - async_std::task::spawn(async move { - HotstuffRunner::new( - local_id, - local_device_id, - committee, - store, - signer, - network_sender, - non_driver, - tx_message_runner, - rx_message, - proposal_consumer, - state_pusher_runner, - event_notifier, - rpath2, - ) - .run() - .await - }); - } + async_std::task::spawn(async move { + runner.run() + .await + }); Self { local_device_id, tx_message, state_pusher, - rpath + rpath, + proposal_result_notifier } } + pub async fn wait_proposal_result( + &self, + proposal_id: ObjectId, + ) -> CallReplyWaiter>> { + self.proposal_result_notifier.prepare(proposal_id).await + } + pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { log::debug!("[hotstuff] local: {:?}, on_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", self, @@ -230,6 +236,7 @@ struct HotstuffRunner { rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, state_pusher: StatePusher, + proposal_result_notifier: CallReplyNotifier>>, } impl std::fmt::Debug for HotstuffRunner { @@ -254,6 +261,7 @@ impl HotstuffRunner { state_pusher: StatePusher, event_notifier: RPathEventNotifier, rpath: GroupRPath, + proposal_result_notifier: CallReplyNotifier>>, ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); @@ -319,6 +327,7 @@ impl HotstuffRunner { state_pusher, tx_block_gen, rx_block_gen, + proposal_result_notifier, } } @@ -687,48 +696,9 @@ impl HotstuffRunner { err })?; - if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { - log::info!( - "[hotstuff] local: {:?}, new header-block {:?} committed", - self, header_block.block_id() - ); - - /** - * 这里只清理已经提交的block包含的proposal - * 已经执行过的待提交block包含的proposal在下次打包时候去重 - * */ - self.cleanup_proposal(&header_block).await; - - log::debug!( - "[hotstuff] local: {:?}, process_block-step1 {:?}", - self, block.block_id() - ); - - let (_, qc_block) = self - .store - .pre_commits() - .iter() - .next() - .expect("the pre-commit block must exist."); - - self.notify_block_committed(&header_block, &old_header_block, qc_block).await; - - log::debug!( - "[hotstuff] local: {:?}, process_block-step2 {:?}", - self, block.block_id() - ); - - // notify by leader - if &self.local_id == header_block.owner() { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } - - log::debug!( - "[hotstuff] local: {:?}, process_block-step3 {:?}", - self, block.block_id() - ); + if let Some((header_block, old_header_block, _discard_blocks)) = new_header_block { + let header_block = header_block.clone(); + self.on_new_block_commit(&header_block, &old_header_block, block).await; } match self.vote_mgr.add_voting_block(block).await { @@ -795,6 +765,65 @@ impl HotstuffRunner { Ok(()) } + async fn on_new_block_commit(&mut self, new_header_block: &GroupConsensusBlock, old_header_block: &Option, qc_qc_block: &GroupConsensusBlock) { + log::info!( + "[hotstuff] local: {:?}, new header-block {:?} committed, old: {:?}, qc-qc: {}", + self, new_header_block.block_id(), old_header_block.as_ref().map(|b| b.block_id()), qc_qc_block.block_id() + ); + + /** + * 这里只清理已经提交的block包含的proposal + * 已经执行过的待提交block包含的proposal在下次打包时候去重 + * */ + self.cleanup_proposal(new_header_block).await; + + log::debug!( + "[hotstuff] local: {:?}, process_block-step1 {:?}", + self, qc_qc_block.block_id() + ); + + let (_, qc_block) = self + .store + .pre_commits() + .iter() + .next() + .expect("the pre-commit block must exist."); + + self.notify_block_committed(new_header_block, old_header_block, qc_block).await; + + log::debug!( + "[hotstuff] local: {:?}, process_block-step2 {:?}", + self, qc_qc_block.block_id() + ); + + // notify by the block generator + if &self.local_id == new_header_block.owner() { + // push to member + self.state_pusher + .notify_block_commit(new_header_block.clone(), qc_block.clone()) + .await; + + // reply + let futs = new_header_block.proposals().iter().map(|proposal_info| { + let receipt = match proposal_info.receipt.as_ref() { + Some(receipt) => NONObjectInfo::raw_decode(receipt.as_slice()).map(|(receipt, remain)| { + assert_eq!(remain.len(), 0); + Some(receipt) + }), + None => Ok(None), + }; + self.proposal_result_notifier.reply(&proposal_info.proposal, receipt) + }); + + futures::future::join_all(futs).await; + } + + log::debug!( + "[hotstuff] local: {:?}, process_block-step3 {:?}", + self, qc_qc_block.block_id() + ); + } + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); @@ -916,6 +945,8 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, proposal {} failed {:?}", self, proposal.desc().object_id(), err); + self.proposal_result_notifier.reply(&proposal.desc().object_id(), Err(err.clone())).await; + self.state_pusher .notify_proposal_err(proposal.clone(), err) .await; diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index 47bd1ffd7..ff175960d 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,8 +1,8 @@ use std::sync::Arc; use cyfs_base::{ - AnyNamedObject, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, - RsaCPUObjectSigner, TypelessCoreObject, + AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -71,23 +71,27 @@ impl RPathService { &self.0.rpath } - pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { - log::info!( - "group({:?}) push proposal {}", - self.rpath(), - proposal.desc().object_id() - ); + pub async fn push_proposal( + &self, + proposal: GroupProposal, + ) -> BuckyResult> { + let proposal_id = proposal.desc().object_id(); + + log::info!("group({:?}) push proposal {}", self.rpath(), proposal_id); let object_raw = proposal.to_vec()?; let any_obj = AnyNamedObject::Core(TypelessCoreObject::clone_from_slice(object_raw.as_slice())?); - let non_obj = NONObjectInfo::new( - proposal.desc().object_id(), - object_raw, - Some(Arc::new(any_obj)), - ); + let non_obj = NONObjectInfo::new(proposal_id, object_raw, Some(Arc::new(any_obj))); self.0.non_driver.put_object(non_obj).await?; - self.0.pending_proposal_handle.on_proposal(proposal).await + self.0.pending_proposal_handle.on_proposal(proposal).await?; + + let waiter = self.0.hotstuff.wait_proposal_result(proposal_id).await; + + waiter.wait().await.map_or( + Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown")), + |r| r, + ) } pub fn select_branch(&self, block_id: ObjectId, source: ObjectId) -> BuckyResult<()> { diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs index 50abe1afb..74ee64c85 100644 --- a/src/component/cyfs-stack/src/group/transform.rs +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -72,7 +72,9 @@ impl GroupInputTransformer { .push_proposal(Self::convert_common(req_common), req) .await?; - let resp = GroupPushProposalInputResponse {}; + let resp = GroupPushProposalInputResponse { + object: out_resp.object, + }; Ok(resp) } @@ -144,7 +146,9 @@ impl GroupOutputTransformer { .push_proposal(self.convert_common(req_common), req) .await?; - let resp = GroupPushProposalOutputResponse {}; + let resp = GroupPushProposalOutputResponse { + object: in_resp.object, + }; Ok(resp) } diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs index e14691b5e..a6e65420c 100644 --- a/src/component/cyfs-stack/src/group_api/router/local_service.rs +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -97,7 +97,7 @@ impl GroupInputProcessor for LocalGroupService { service .push_proposal(req) .await - .map(|_| GroupPushProposalInputResponse {}) + .map(|object| GroupPushProposalInputResponse { object }) .map_err(|err| { log::error!( "group push proposal {}-{}-{} {} failed {:?}", diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs index f01f2eaa5..182cc2f2d 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_handler.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -87,15 +87,21 @@ impl GroupRequestHandler { req: NONInputHttpRequest, ) -> tide::Response { match self.on_push_proposal(req).await { - Ok(_) => { - let http_resp: tide::Response = RequestorHelper::new_ok_response(); - - http_resp - } + Ok(resp) => Self::encode_push_proposal_response(resp), Err(e) => RequestorHelper::trans_error(e), } } + pub fn encode_push_proposal_response(resp: GroupPushProposalInputResponse) -> tide::Response { + let mut http_resp = RequestorHelper::new_response(tide::StatusCode::Ok); + + if let Some(object) = resp.object { + NONRequestorHelper::encode_object_info(&mut http_resp, object); + } + + http_resp.into() + } + async fn on_push_proposal( &self, mut req: NONInputHttpRequest, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fa136b3fa..2c00ed58e 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -4,7 +4,7 @@ use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, - RequestProtocol, RequestSourceInfo, + RequestGlobalStatePath, RequestProtocol, RequestSourceInfo, }; use crate::{non::NONInputProcessor, non_api::NONService}; @@ -27,10 +27,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + self.non_service .get_object(NONGetObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some(req_path.format_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -57,10 +59,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); log::debug!("put object {} with access {}", obj.object_id, access); + + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some(req_path.format_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -93,10 +98,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { let obj_type_code = obj.object_id.obj_type_code(); let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Some("group/inner-cmd")); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: Some("group-inner".to_string()), + req_path: Some(req_path.format_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d3999ea0a..6b867447a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -573,9 +573,10 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, - RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, - RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, + CreateObjectMapOption, GlobalStatePathAccessItem, NONPostObjectInputRequest, + NONPostObjectInputResponse, RequestGlobalStatePath, RequestSourceInfo, RouterHandlerAction, + RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, + RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -614,6 +615,21 @@ mod GroupDecService { local_name, }; + let req_path = RequestGlobalStatePath::new( + Some(dec_app_id.object_id().clone()), + Option::::None, + ) + .format_string(); + + cyfs_stack + .root_state_meta_stub(None, None) + .add_access(GlobalStatePathAccessItem::new( + "group/proposal", + AccessString::full().value(), + )) + .await + .unwrap(); + cyfs_stack .router_handlers() .post_object() @@ -622,7 +638,7 @@ mod GroupDecService { format!("group-proposal-listener-{}", dec_app_id).as_str(), 0, Some(filter), - Some("group-proposal".to_string()), + Some(req_path), RouterHandlerAction::Pass, Some(Box::new(routine)), ) @@ -656,11 +672,13 @@ mod GroupDecService { let (proposal, remain) = GroupProposal::raw_decode(param.request.object.object_raw.as_slice())?; assert_eq!(remain.len(), 0); - self.service.push_proposal(&proposal).await.unwrap(); + + let result = self.service.push_proposal(&proposal).await; + Ok(RouterHandlerPostObjectResult { action: RouterHandlerAction::Response, request: None, - response: None, + response: Some(result.map(|result| NONPostObjectInputResponse { object: result })), }) } } @@ -998,7 +1016,7 @@ fn create_proposal( async fn main_run() { log::info!("main_run"); - async_std::task::sleep(Duration::from_millis(10000)).await; + // async_std::task::sleep(Duration::from_millis(10000)).await; cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") @@ -1197,7 +1215,7 @@ async fn main_run() { } } - async_std::task::sleep(Duration::from_millis(10000)).await; + async_std::task::sleep(Duration::from_millis(20000)).await; // let client = admin_group_mgrs // .get(0) From e081168013cf7202ec27951ee8b1981d38c32302 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Mar 2023 17:36:31 +0800 Subject: [PATCH 417/553] Split the function AnyNamedObject::raw_decode to little. --- src/component/cyfs-base/src/objects/any.rs | 307 ++++++++++++--------- 1 file changed, 171 insertions(+), 136 deletions(-) diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index 38698c7f9..a146b7f91 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -340,6 +340,162 @@ impl AnyNamedObject { pub fn nonce(&self) -> &Option { match_any_obj!(self, o, { o.nonce() }, _chunk_id, { &None }) } + + fn raw_decode_device<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (device, buf) = Device::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/device error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Device(device)), + buf, + )) + } + + fn raw_decode_people<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (people, buf) = People::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/people error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::People(people)), + buf, + )) + } + + fn raw_decode_app_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::AppGroup(app_group)), + buf, + )) + } + + fn raw_decode_simple_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); + e + })?; + return Ok(( + AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), + buf, + )); + } + + fn raw_decode_org<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (org, buf) = Org::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/org error:{}", e); + e + })?; + return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); + } + + fn raw_decode_union_account<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/ua error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::UnionAccount(ua)), + buf, + )) + } + + fn raw_decode_file<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (file, buf) = File::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/file error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::File(file)), buf)) + } + + fn raw_decode_dir<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (dir, buf) = Dir::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/dir error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Dir(dir)), buf)) + } + + fn raw_decode_diff<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (diff, buf) = Diff::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/diff error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Diff(diff)), buf)) + } + + fn raw_decode_proof_of_service<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (prof, buf) = ProofOfService::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/prof error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::ProofOfService(prof)), + buf, + )) + } + + fn raw_decode_tx<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (tx, buf) = Tx::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/tx error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Tx(tx)), buf)) + } + + fn raw_decode_action<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (action, buf) = Action::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/action error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Action(action)), + buf, + )) + } + + fn raw_decode_object_map<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (relation, buf) = ObjectMap::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/relation error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::ObjectMap(relation)), + buf, + )) + } + + fn raw_decode_contract<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (contract, buf) = Contract::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/contract error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Contract(contract)), + buf, + )) + } + + fn raw_decode_custom<'de>( + buf: &'de [u8], + is_dec_app_object: bool, + ) -> Result<(Self, &'de [u8]), BuckyError> { + if is_dec_app_object { + // println!("is dec app object"); + + let (dec_obj, buf) = TypelessDECAppObject::raw_decode(buf)?; + Ok((AnyNamedObject::DECApp(dec_obj), buf)) + } else { + // println!("is core object"); + + let (core_obj, buf) = TypelessCoreObject::raw_decode(buf)?; + Ok((AnyNamedObject::Core(core_obj), buf)) + } + } } impl RawEncode for AnyNamedObject { @@ -372,147 +528,26 @@ impl<'de> RawDecode<'de> for AnyNamedObject { })?; match obj_type_info.obj_type_code() { - ObjectTypeCode::Device => { - let (device, buf) = Device::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/device error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Device(device)), - buf, - )); - } - ObjectTypeCode::People => { - let (people, buf) = People::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/people error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::People(people)), - buf, - )); - } - ObjectTypeCode::Org => { - let (org, buf) = Org::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/org error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); - } - ObjectTypeCode::AppGroup => { - let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::AppGroup(app_group)), - buf, - )); - } - ObjectTypeCode::SimpleGroup => { - let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), - buf, - )); - } - ObjectTypeCode::UnionAccount => { - let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/ua error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::UnionAccount(ua)), - buf, - )); - } + ObjectTypeCode::Device => Self::raw_decode_device(buf), + ObjectTypeCode::People => Self::raw_decode_people(buf), + ObjectTypeCode::AppGroup => Self::raw_decode_app_group(buf), + ObjectTypeCode::UnionAccount => Self::raw_decode_union_account(buf), ObjectTypeCode::Chunk => { unreachable!(); } - ObjectTypeCode::File => { - let (file, buf) = File::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/file error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::File(file)), buf)); - } - ObjectTypeCode::Dir => { - let (dir, buf) = Dir::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/dir error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Dir(dir)), buf)); - } - ObjectTypeCode::Diff => { - let (diff, buf) = Diff::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/diff error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Diff(diff)), buf)); - } - ObjectTypeCode::ProofOfService => { - let (prof, buf) = ProofOfService::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/prof error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::ProofOfService(prof)), - buf, - )); - } - ObjectTypeCode::Tx => { - let (tx, buf) = Tx::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/tx error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Tx(tx)), buf)); - } - ObjectTypeCode::Action => { - let (action, buf) = Action::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/action error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Action(action)), - buf, - )); - } - ObjectTypeCode::ObjectMap => { - let (relation, buf) = ObjectMap::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/relation error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::ObjectMap(relation)), - buf, - )); - } - ObjectTypeCode::Contract => { - let (contract, buf) = Contract::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/contract error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Contract(contract)), - buf, - )); - } + ObjectTypeCode::File => Self::raw_decode_file(buf), + ObjectTypeCode::Dir => Self::raw_decode_dir(buf), + ObjectTypeCode::Diff => Self::raw_decode_diff(buf), + ObjectTypeCode::ProofOfService => Self::raw_decode_proof_of_service(buf), + ObjectTypeCode::Tx => Self::raw_decode_tx(buf), + ObjectTypeCode::Action => Self::raw_decode_action(buf), + ObjectTypeCode::ObjectMap => Self::raw_decode_object_map(buf), + ObjectTypeCode::Contract => Self::raw_decode_contract(buf), ObjectTypeCode::Custom => { - return if obj_type_info.is_decapp_object() { - // println!("is dec app object"); - - let (dec_obj, buf) = TypelessDECAppObject::raw_decode(buf)?; - Ok((AnyNamedObject::DECApp(dec_obj), buf)) - } else { - // println!("is core object"); - - let (core_obj, buf) = TypelessCoreObject::raw_decode(buf)?; - Ok((AnyNamedObject::Core(core_obj), buf)) - }; + Self::raw_decode_custom(buf, obj_type_info.is_decapp_object()) } + ObjectTypeCode::SimpleGroup => Self::raw_decode_simple_group(buf), + ObjectTypeCode::Org => Self::raw_decode_org(buf), } } } From c135ff7c5a8f6bdd809df178ed533eb29714a227 Mon Sep 17 00:00:00 2001 From: jing-git Date: Tue, 14 Mar 2023 11:10:52 +0800 Subject: [PATCH 418/553] Fix: send cache packages after tunnel connection --- src/component/cyfs-bdt/src/tunnel/container.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/component/cyfs-bdt/src/tunnel/container.rs b/src/component/cyfs-bdt/src/tunnel/container.rs index 6c5edc03f..77c367800 100644 --- a/src/component/cyfs-bdt/src/tunnel/container.rs +++ b/src/component/cyfs-bdt/src/tunnel/container.rs @@ -36,6 +36,7 @@ use super::{ udp, tcp }; +use core::mem; #[derive(Clone)] pub struct BuildTunnelParams { @@ -807,12 +808,16 @@ impl TunnelOwner for TunnelContainer { TunnelStateImpl::Connecting(connecting) => { info!("{} connecting=>active with default {}", self, tunnel.as_ref().as_ref()); connecting.waiter.transfer_into(&mut next_step.waiters); + + mem::swap(&mut next_step.packages, &mut connecting.packages); + state.tunnel_state = TunnelStateImpl::Active(TunnelActiveState { default_tunnel: tunnel.clone(), remote_timestamp: remote_timestamp }); next_step.new_default = Some(tunnel.clone()); + true }, TunnelStateImpl::Dead(_) => { From 327ad5e75443d8b463c551711568e972a99fdcd7 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 15 Mar 2023 17:35:39 +0800 Subject: [PATCH 419/553] Fix: Wrong path detection causes dec app installation or startup error on windows --- src/service/app-manager/src/dapp.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index fff62587a..7c592cd47 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -188,11 +188,7 @@ impl DApp { } info!("run cmd {} in {}", cmd, dir.display()); let program = which::which(args[0]).unwrap_or_else(|_| dir.join(args[0])); - if !program.exists() { - let err = format!("exec program path {} not exists!", program.display()); - error!("{}", &err); - return Err(BuckyError::new(BuckyErrorCode::NotFound, err)); - } + info!("program full path: {}", program.display()); let mut command = Command::new(program); command.args(&args[1..]).current_dir(dir); if let Some(out) = stdout { From ad8274f4af28fa165d1adb3230d25b5c3f51ba08 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Mar 2023 20:59:37 +0800 Subject: [PATCH 420/553] Zone for group --- .../cyfs-group/src/dec/group_manager.rs | 33 +++++------ .../cyfs-stack/src/stack/cyfs_stack.rs | 5 +- .../cyfs-stack/src/stack/group_non_driver.rs | 27 ++++++--- src/tests/group-example/src/main.rs | 56 ++++++++++++------- 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 579f63831..766da468e 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -290,22 +290,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.rpath(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: unimplemented + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.rpath(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 493f6ace8..78256f60d 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -434,7 +434,10 @@ impl CyfsStackImpl { let group_manager = GroupManager::new( signer, - Box::new(GroupNONDriver::new(non_service.clone())), + Box::new(GroupNONDriver::new( + non_service.clone(), + device_id.object_id().clone(), + )), bdt_stack.clone(), global_state_manager.clone_processor(), )?; diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 2c00ed58e..7347a4c38 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -11,11 +11,15 @@ use crate::{non::NONInputProcessor, non_api::NONService}; pub struct GroupNONDriver { non_service: Arc, + local_device_id: ObjectId, } impl GroupNONDriver { - pub fn new(non_service: Arc) -> Self { - Self { non_service } + pub fn new(non_service: Arc, local_device_id: ObjectId) -> Self { + Self { + non_service, + local_device_id, + } } } @@ -27,12 +31,17 @@ impl cyfs_group::NONDriver for GroupNONDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { - let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + log::debug!( + "get object {}, local: {}, from: {:?}", + object_id, + self.local_device_id, + from + ); self.non_service .get_object(NONGetObjectInputRequest { common: NONInputRequestCommon { - req_path: Some(req_path.format_string()), + req_path: None, source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -58,14 +67,18 @@ impl cyfs_group::NONDriver for GroupNONDriver { async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); - log::debug!("put object {} with access {}", obj.object_id, access); - let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + log::debug!( + "put object {} with access {}, local: {}", + obj.object_id, + access, + self.local_device_id + ); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { - req_path: Some(req_path.format_string()), + req_path: None, source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 6b867447a..6bcc78920 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -2,10 +2,12 @@ use std::{clone, collections::HashSet, sync::Arc, time::Duration}; use async_std::sync::Mutex; use cyfs_base::{ - AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, - TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawDecode, + RawFrom, TypelessCoreObject, +}; +use cyfs_core::{ + DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath, Text, TextObj, }; -use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group_lib::GroupManager; use cyfs_lib::{ CyfsStackRequestorType, DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, @@ -566,14 +568,14 @@ mod GroupDecService { use cyfs_base::*; use cyfs_core::{ CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, - GroupProposalObject, + GroupProposalObject, Text, TextObj, }; use cyfs_group_lib::{ DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, RPathService, }; use cyfs_lib::{ - CreateObjectMapOption, GlobalStatePathAccessItem, NONPostObjectInputRequest, + CreateObjectMapOption, GlobalStatePathAccessItem, NONObjectInfo, NONPostObjectInputRequest, NONPostObjectInputResponse, RequestGlobalStatePath, RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -768,7 +770,7 @@ mod GroupDecService { } }; - let result_value = { + let (result_value, result_value_u64) = { /** * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ @@ -785,10 +787,11 @@ mod GroupDecService { let delta = u64::from_be_bytes(delta); let value = prev_value + delta; - ObjectIdDataBuilder::new() + let result_value = ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() - .unwrap() + .unwrap(); + (result_value, value) }; let result_state_id = { @@ -819,14 +822,21 @@ mod GroupDecService { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? */ - None + let text = Text::build("value", "header", format!("{}", result_value_u64)) + .no_create_time() + .build(); + Some(NONObjectInfo::new( + text.desc().object_id(), + text.to_vec().unwrap(), + None, + )) }; let context = { /** * 执行请求的上下文,运算过程中可能有验证节点无法得到的上下文信息(比如时间戳,随机数) */ - None + Some(Vec::from(result_value_u64.to_le_bytes())) }; /** @@ -855,19 +865,20 @@ mod GroupDecService { .await?; log::info!( - "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{:?}/{:?}, got: {:?}/{:?}/{:?}", prev_state_id, execute_result.result_state_id, - execute_result.context.is_none(), - execute_result.receipt.is_none(), + execute_result.context.as_ref().map(|v| v.to_hex()), + execute_result.receipt.as_ref().map(|r| r.object_id), result.result_state_id, - result.context.is_none(), - result.receipt.is_none() + result.context.as_ref().map(|v| v.to_hex()), + result.receipt.as_ref().map(|r| r.object_id) ); let is_ok = execute_result.result_state_id == result.result_state_id - && execute_result.context.is_none() - && execute_result.receipt.is_none(); + && execute_result.context == result.context + && execute_result.receipt.as_ref().map(|r| r.object_id) + == result.receipt.as_ref().map(|r| r.object_id); if is_ok { Ok(()) @@ -1201,11 +1212,18 @@ async fn main_run() { ); let result = client.post_proposal(&proposal).await; + let result_text = result.as_ref().map(|obj| { + obj.as_ref().map(|obj| { + Text::raw_decode(obj.object_raw.as_slice()) + .map(|(txt, _)| txt.value().to_string()) + }) + }); log::info!( - "client {:?} post proposal {}, result: {:?}", + "client {:?} post proposal {}, result: {:?}, result-text: {:?}", local_name, proposal.desc().object_id(), - result.map(|o| o.map(|o| o.object_id)) + result.as_ref().map(|o| o.as_ref().map(|o| o.object_id)), + result_text ); }); From fe7627ecfe8c469f02a8f8a3bdd1acf199f30f78 Mon Sep 17 00:00:00 2001 From: jing-git Date: Tue, 14 Mar 2023 11:10:52 +0800 Subject: [PATCH 421/553] Fix: send cache packages after tunnel connection --- src/component/cyfs-bdt/src/tunnel/container.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/component/cyfs-bdt/src/tunnel/container.rs b/src/component/cyfs-bdt/src/tunnel/container.rs index 6c5edc03f..77c367800 100644 --- a/src/component/cyfs-bdt/src/tunnel/container.rs +++ b/src/component/cyfs-bdt/src/tunnel/container.rs @@ -36,6 +36,7 @@ use super::{ udp, tcp }; +use core::mem; #[derive(Clone)] pub struct BuildTunnelParams { @@ -807,12 +808,16 @@ impl TunnelOwner for TunnelContainer { TunnelStateImpl::Connecting(connecting) => { info!("{} connecting=>active with default {}", self, tunnel.as_ref().as_ref()); connecting.waiter.transfer_into(&mut next_step.waiters); + + mem::swap(&mut next_step.packages, &mut connecting.packages); + state.tunnel_state = TunnelStateImpl::Active(TunnelActiveState { default_tunnel: tunnel.clone(), remote_timestamp: remote_timestamp }); next_step.new_default = Some(tunnel.clone()); + true }, TunnelStateImpl::Dead(_) => { From b022487d1e7dd0fff05e4eabefca0e0e49a219d7 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Wed, 15 Mar 2023 17:35:39 +0800 Subject: [PATCH 422/553] Fix: Wrong path detection causes dec app installation or startup error on windows --- src/service/app-manager/src/dapp.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/service/app-manager/src/dapp.rs b/src/service/app-manager/src/dapp.rs index fff62587a..7c592cd47 100644 --- a/src/service/app-manager/src/dapp.rs +++ b/src/service/app-manager/src/dapp.rs @@ -188,11 +188,7 @@ impl DApp { } info!("run cmd {} in {}", cmd, dir.display()); let program = which::which(args[0]).unwrap_or_else(|_| dir.join(args[0])); - if !program.exists() { - let err = format!("exec program path {} not exists!", program.display()); - error!("{}", &err); - return Err(BuckyError::new(BuckyErrorCode::NotFound, err)); - } + info!("program full path: {}", program.display()); let mut command = Command::new(program); command.args(&args[1..]).current_dir(dir); if let Some(out) = stdout { From 78478dc43b0b07547cd447d11289827de3018523 Mon Sep 17 00:00:00 2001 From: streetycat <34021271+streetycat@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:56:48 +0800 Subject: [PATCH 423/553] Buckyos (#123) * Add interface create_new_with_option for RootStateStub to add params(owner/dec) * Split the function AnyNamedObject::raw_decode to little. * Fix: send cache packages after tunnel connection * Fix: Wrong path detection causes dec app installation or startup error on windows --------- Co-authored-by: jing-git Co-authored-by: weiqiushi --- src/component/cyfs-base/src/objects/any.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index b4c5c2d64..bea4f1650 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -377,12 +377,23 @@ impl AnyNamedObject { )) } - fn raw_decode_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { - let (group, buf) = Group::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/group error:{}", e); + fn raw_decode_simple_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); e })?; - Ok((AnyNamedObject::Standard(StandardObject::Group(group)), buf)) + return Ok(( + AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), + buf, + )); + } + + fn raw_decode_org<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (org, buf) = Org::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/org error:{}", e); + e + })?; + return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); } fn raw_decode_union_account<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { @@ -523,7 +534,6 @@ impl<'de> RawDecode<'de> for AnyNamedObject { ObjectTypeCode::Device => Self::raw_decode_device(buf), ObjectTypeCode::People => Self::raw_decode_people(buf), ObjectTypeCode::AppGroup => Self::raw_decode_app_group(buf), - ObjectTypeCode::Group => Self::raw_decode_group(buf), ObjectTypeCode::UnionAccount => Self::raw_decode_union_account(buf), ObjectTypeCode::Chunk => { unreachable!(); @@ -539,6 +549,8 @@ impl<'de> RawDecode<'de> for AnyNamedObject { ObjectTypeCode::Custom => { Self::raw_decode_custom(buf, obj_type_info.is_decapp_object()) } + ObjectTypeCode::SimpleGroup => Self::raw_decode_simple_group(buf), + ObjectTypeCode::Org => Self::raw_decode_org(buf), } } } From c9d58d23740fd94e86f13a7967bb5b98912238f5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Mar 2023 17:01:58 +0800 Subject: [PATCH 424/553] Ensure the result-state is exist on the GroupState --- src/component/cyfs-base/src/objects/any.rs | 19 +- .../protos/group_bft_protocol.proto | 8 +- src/component/cyfs-group-lib/src/delegate.rs | 2 - .../cyfs-group-lib/src/group_manager.rs | 19 +- .../src/objects/group_command.rs | 24 - .../cyfs-group-lib/src/rpath_service.rs | 4 - .../src/consensus/hotstuff/hotstuff.rs | 929 +++++++++++------- .../cyfs-group/src/dec/group_events.rs | 6 - .../cyfs-group/src/network/protocol.rs | 2 +- .../cyfs-group/src/network/sender.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- src/tests/group-example/src/main.rs | 106 +- 12 files changed, 703 insertions(+), 432 deletions(-) diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index bea4f1650..355ded409 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -377,25 +377,17 @@ impl AnyNamedObject { )) } - fn raw_decode_simple_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { - let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); + fn raw_decode_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (simple_group, buf) = Group::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/group error:{}", e); e })?; return Ok(( - AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), + AnyNamedObject::Standard(StandardObject::Group(simple_group)), buf, )); } - fn raw_decode_org<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { - let (org, buf) = Org::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/org error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); - } - fn raw_decode_union_account<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { log::error!("AnyNamedObject::raw_decode/ua error:{}", e); @@ -549,8 +541,7 @@ impl<'de> RawDecode<'de> for AnyNamedObject { ObjectTypeCode::Custom => { Self::raw_decode_custom(buf, obj_type_info.is_decapp_object()) } - ObjectTypeCode::SimpleGroup => Self::raw_decode_simple_group(buf), - ObjectTypeCode::Org => Self::raw_decode_org(buf), + ObjectTypeCode::Group => Self::raw_decode_group(buf), } } } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto index 2bfdd8d21..427e17681 100644 --- a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -54,10 +54,6 @@ message GroupCommandVerify { } message GroupCommandCommited { - bytes proposal = 1; // Proposal.to_vec() - optional bytes prev_state_id = 2; // ObjectId - optional bytes result_state_id = 3; // ObjectId - optional bytes receipt = 4; // NONObjectInfo.to_vec() - optional bytes context = 5; // Vec - bytes block = 6; // Block.to_vec() + optional bytes prev_state_id = 1; // ObjectId + bytes block = 2; // Block.to_vec() } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index d678438c3..14adb523c 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -38,9 +38,7 @@ pub trait RPathDelegate: Sync + Send { async fn on_commited( &self, - proposal: &GroupProposal, prev_state_id: &Option, - execute_result: &ExecuteResult, block: &GroupConsensusBlock, object_map_processor: &dyn GroupObjectMapProcessor, ); diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 07bae1f7a..c15200386 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,10 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; +use cyfs_core::{ + CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposalObject, + GroupRPath, +}; use cyfs_lib::{ CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RequestGlobalStatePath, RouterHandlerAction, RouterHandlerChain, @@ -343,7 +346,7 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let rpath = cmd.proposal.rpath(); + let rpath = cmd.block.rpath(); let service = self .find_or_restart_service( rpath.group_id(), @@ -356,21 +359,13 @@ impl GroupManager { .map_err(|err| { log::warn!( "group on_commited find service {:?} failed, err: {:?}", - cmd.proposal.rpath(), + cmd.block.rpath(), err ); err })?; - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; - - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; + service.on_commited(&cmd.prev_state_id, &cmd.block).await; Ok(()) } diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs index 912ced438..0e441d98f 100644 --- a/src/component/cyfs-group-lib/src/objects/group_command.rs +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -260,11 +260,7 @@ impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupComma #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] #[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] pub struct GroupCommandCommited { - pub proposal: GroupProposal, pub prev_state_id: Option, - pub result_state_id: Option, - pub receipt: Option, - pub context: Option>, pub block: GroupConsensusBlock, } @@ -275,17 +271,7 @@ impl ProtobufTransform for GroupComm Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), None => None, }, - proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, - result_state_id: match value.result_state_id.as_ref() { - Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), - None => None, - }, - receipt: match value.receipt.as_ref() { - Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), - None => None, - }, block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, - context: value.context, }) } } @@ -293,20 +279,10 @@ impl ProtobufTransform for GroupComm impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { fn transform(value: &GroupCommandCommited) -> BuckyResult { Ok(Self { - proposal: value.proposal.to_vec()?, prev_state_id: match value.prev_state_id.as_ref() { Some(prev_state_id) => Some(prev_state_id.to_vec()?), None => None, }, - result_state_id: match value.result_state_id.as_ref() { - Some(result_state_id) => Some(result_state_id.to_vec()?), - None => None, - }, - receipt: match value.receipt.as_ref() { - Some(receipt) => Some(receipt.to_vec()?), - None => None, - }, - context: value.context.clone(), block: value.block.to_vec()?, }) } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index d6aa6972d..74f113e3f 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -104,17 +104,13 @@ impl RPathService { pub(crate) async fn on_commited( &self, - proposal: &GroupProposal, prev_state_id: &Option, - execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { self.0 .delegate .on_commited( - proposal, prev_state_id, - execute_result, block, &GroupObjectMapProcessorImpl { stack: self.0.stack.clone(), diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 23e2152f1..e7f69f9a1 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,31 +1,38 @@ -use std::{collections::HashMap, sync::Arc, time::{SystemTime, Duration}}; +use std::{ + collections::HashMap, + fmt::format, + sync::Arc, + time::{Duration, SystemTime}, +}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, + ObjectDesc, ObjectId, ObjectLink, ObjectTypeCode, OwnerObjectDesc, RawConvertTo, RawDecode, + RawEncode, RsaCPUObjectSigner, SignatureSource, Signer, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; -use cyfs_lib::{NONObjectInfo}; +use cyfs_group_lib::{ExecuteResult, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use itertools::Itertools; use crate::{ - consensus::{synchronizer::Synchronizer}, dec_state::{StatePusher, CallReplyNotifier, CallReplyWaiter}, helper::Timer, Committee, - GroupStorage, HotstuffMessage, - PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, + consensus::synchronizer::Synchronizer, + dec_state::{CallReplyNotifier, CallReplyWaiter, StatePusher}, + helper::Timer, + Committee, GroupObjectMapProcessor, GroupStorage, HotstuffMessage, PendingProposalConsumer, + RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, }; /** * TODO: generate empty block when the 'Node' is synchronizing - * + * * synchronizing: max_quorum_round - round > THRESHOLD */ @@ -80,20 +87,17 @@ impl Hotstuff { state_pusher.clone(), event_notifier, rpath.clone(), - proposal_result_notifier.clone() + proposal_result_notifier.clone(), ); - async_std::task::spawn(async move { - runner.run() - .await - }); + async_std::task::spawn(async move { runner.run().await }); Self { local_device_id, tx_message, state_pusher, rpath, - proposal_result_notifier + proposal_result_notifier, } } @@ -222,6 +226,7 @@ struct HotstuffRunner { high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, max_quorum_round: u64, + max_quorum_height: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -267,17 +272,19 @@ impl HotstuffRunner { let last_qc = store.last_qc(); let last_tc = store.last_tc(); - let last_vote_round = store - .last_vote_round(); + let last_vote_round = store.last_vote_round(); let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); let quorum_round = block_quorum_round.max(timeout_quorum_round); - let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { - let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); - (block.round(), qc_round) - }); - let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - + let (max_round_block_round, max_round_qc_round) = + max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); + let round = last_vote_round + .max(quorum_round + 1) + .max(max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); @@ -291,7 +298,14 @@ impl HotstuffRunner { let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); - let max_height = store.header_height() + 2; + let max_quorum_round = round - 1; + let header_height = store.header_height(); + let max_height = header_height + 2; + let max_quorum_height = if header_height == 0 { + 0 + } else { + header_height + 1 + }; let synchronizer = Synchronizer::new( network_sender.clone(), @@ -323,7 +337,8 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, - max_quorum_round: round - 1, + max_quorum_round, + max_quorum_height, state_pusher, tx_block_gen, rx_block_gen, @@ -361,13 +376,17 @@ impl HotstuffRunner { */ Self::check_block_result_state(block)?; - log::debug!("[hotstuff] local: {:?}, handle_block-step2: {:?}", + log::debug!( + "[hotstuff] local: {:?}, handle_block-step2: {:?}", self, - block.block_id()); + block.block_id() + ); { // check leader - let leader_owner = self.get_leader_owner(Some(block.group_chunk_id()), block.round()).await?; + let leader_owner = self + .get_leader_owner(Some(block.group_chunk_id()), block.round()) + .await?; if &leader_owner != block.owner() { log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", @@ -395,19 +414,24 @@ impl HotstuffRunner { let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); self.update_max_quorum_round(quorum_round); + self.update_max_quorum_height(block.height() - 1); - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + log::debug!( + "[hotstuff] local: {:?}, handle_block-step3: {:?}", self, - block.block_id()); + block.block_id() + ); let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, - Err(err) => return err + Err(err) => return err, }; - log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", + log::debug!( + "[hotstuff] local: {:?}, handle_block-step4: {:?}", self, - block.block_id()); + block.block_id() + ); self.synchronizer.pop_link_from(block); @@ -471,33 +495,38 @@ impl HotstuffRunner { prev_block: &Option, remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = match prev_block - .as_ref() { - Some(prev_block) => { - let result_state_id = prev_block.result_state_id(); - if let Some(result_state_id) = result_state_id { - self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; - } - result_state_id.clone() - }, - None => None - }; + let mut prev_state_id = match prev_block.as_ref() { + Some(prev_block) => { + let result_state_id = prev_block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]) + .await?; + } + result_state_id.clone() + } + None => None, + }; for proposal_exe_info in block.proposals() { // 去重 if let Some(prev_block_id) = block.prev_block_id() { - if self.store + let is_already_finished = self.store .is_proposal_finished(&proposal_exe_info.proposal, prev_block_id) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, check proposal {:?} in block {:?} with prev-block {:?} duplicate failed, {:?}." , self, proposal_exe_info.proposal, block.block_id(), prev_block_id, err); err - })? { - log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." + })?; + + if is_already_finished { + log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." , self, proposal_exe_info.proposal, block.block_id(), prev_block_id); - - return Err(BuckyError::new(BuckyErrorCode::ErrorState, "duplicate proposal")) - } + + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "duplicate proposal", + )); + } } let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); @@ -509,9 +538,9 @@ impl HotstuffRunner { err })?; - + Some(receipt) - }, + } None => None, }; @@ -551,7 +580,11 @@ impl HotstuffRunner { Ok(()) } - async fn get_leader_owner(&self, group_chunk_id: Option<&ObjectId>, round: u64) -> BuckyResult { + async fn get_leader_owner( + &self, + group_chunk_id: Option<&ObjectId>, + round: u64, + ) -> BuckyResult { let leader = self .committee .get_leader(group_chunk_id, round) @@ -587,32 +620,37 @@ impl HotstuffRunner { match leader_owner { Some(owner) => Ok(owner), None => { - log::warn!("[hotstuff] local: {:?}, a owner must be set to the device {}", + log::warn!( + "[hotstuff] local: {:?}, a owner must be set to the device {}", self, leader ); - Err(BuckyError::new(BuckyErrorCode::InvalidTarget, "no owner for device")) + Err(BuckyError::new( + BuckyErrorCode::InvalidTarget, + "no owner for device", + )) } } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { - match self.store.block_linked(block).await - .map_err(|err| Err(err))? { - + async fn check_block_linked( + &mut self, + block: &GroupConsensusBlock, + remote: ObjectId, + ) -> Result, BuckyResult<()>> { + match self + .store + .block_linked(block) + .await + .map_err(|err| Err(err))? + { crate::storage::BlockLinkState::Expired => { - log::warn!( - "[hotstuff] local: {:?}, receive block expired.", - self - ); + log::warn!("[hotstuff] local: {:?}, receive block expired.", self); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } crate::storage::BlockLinkState::Duplicate => { - log::warn!( - "[hotstuff] local: {:?}, receive duplicate block.", - self - ); - Err( Err(BuckyError::new( + log::warn!("[hotstuff] local: {:?}, receive duplicate block.", self); + Err(Err(BuckyError::new( BuckyErrorCode::AlreadyExists, "duplicate block", ))) @@ -625,7 +663,8 @@ impl HotstuffRunner { ); // 顺序连接状态 - Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; + Self::check_empty_block_result_state_with_prev(block, &prev_block) + .map_err(|err| Err(err))?; Ok(prev_block) } crate::storage::BlockLinkState::Pending => { @@ -656,7 +695,10 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, receive block in invalid branch.", self ); - Err( Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch"))) + Err(Err(BuckyError::new( + BuckyErrorCode::Conflict, + "conflict branch", + ))) } } } @@ -665,17 +707,21 @@ impl HotstuffRunner { &mut self, block: &GroupConsensusBlock, remote: ObjectId, - proposals: &HashMap + proposals: &HashMap, ) -> BuckyResult<()> { /** * 验证过的块执行这个函数 */ - if let Err(err) = self.non_driver.put_block(block).await { - if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + if err.code() != BuckyErrorCode::AlreadyExists + && err.code() != BuckyErrorCode::NotChange + { log::warn!( "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", - self, block.block_id(), block.height(), block.round() + self, + block.block_id(), + block.height(), + block.round() ); return Err(err); } @@ -683,14 +729,19 @@ impl HotstuffRunner { log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", - self, block.block_id(), block.height(), block.round() + self, + block.block_id(), + block.height(), + block.round() ); let debug_identify = self.debug_identify(); let new_header_block = self.store.push_block(block.clone()).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, push verified block {:?} to storage failed {:?}", - debug_identify, block.block_id(), err + debug_identify, + block.block_id(), + err ); err @@ -698,59 +749,76 @@ impl HotstuffRunner { if let Some((header_block, old_header_block, _discard_blocks)) = new_header_block { let header_block = header_block.clone(); - self.on_new_block_commit(&header_block, &old_header_block, block).await; + self.on_new_block_commit(&header_block, &old_header_block, block) + .await; } match self.vote_mgr.add_voting_block(block).await { VoteThresholded::QC(qc) => { log::debug!( "[hotstuff] local: {:?}, the qc of block {:?} has received before", - self, block.block_id() + self, + block.block_id() ); return self.process_block_qc(qc, block).await; - }, + } VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( "[hotstuff] local: {:?}, the timeout-qc of block {:?} has received before", - self, block.block_id() + self, + block.block_id() ); return self .process_timeout_qc(tc, max_high_qc_block.as_ref()) - .await + .await; } VoteThresholded::None => {} } log::debug!( "[hotstuff] local: {:?}, process_block-step4 {:?}", - self, block.block_id() + self, + block.block_id() ); if block.round() != self.round { log::debug!( "[hotstuff] local: {:?}, not my round {}, expect {}", - self, block.round(), self.round + self, + block.round(), + self.round ); // 不是我的投票round return Ok(()); } if let Some(vote) = self.make_vote(block, proposals, &remote).await { - log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", - self, block.block_id(), block.round()); + log::info!( + "[hotstuff] local: {:?}, vote to block {}, round: {}", + self, + block.block_id(), + block.round() + ); - let next_leader = self.committee.get_leader(None, self.round + 1).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get next leader in round {} failed {:?}", - self, self.round + 1, err - ); + let next_leader = self + .committee + .get_leader(None, self.round + 1) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get next leader in round {} failed {:?}", + self, + self.round + 1, + err + ); - err - })?; + err + })?; if self.local_device_id == next_leader { - self.handle_vote(&vote, Some(block), self.local_device_id).await?; + self.handle_vote(&vote, Some(block), self.local_device_id) + .await?; } else { self.network_sender .post_message( @@ -765,12 +833,28 @@ impl HotstuffRunner { Ok(()) } - async fn on_new_block_commit(&mut self, new_header_block: &GroupConsensusBlock, old_header_block: &Option, qc_qc_block: &GroupConsensusBlock) { + async fn on_new_block_commit( + &mut self, + new_header_block: &GroupConsensusBlock, + old_header_block: &Option, + qc_qc_block: &GroupConsensusBlock, + ) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed, old: {:?}, qc-qc: {}", - self, new_header_block.block_id(), old_header_block.as_ref().map(|b| b.block_id()), qc_qc_block.block_id() + self, + new_header_block.block_id(), + old_header_block.as_ref().map(|b| b.block_id()), + qc_qc_block.block_id() ); + if new_header_block.height() <= self.max_quorum_height - 2 { + log::info!( + "[hotstuff] local: {:?}, new header-block {:?} committed, old: {:?}, qc-qc: {}, ignore notify history block({}/{})", + self, new_header_block.block_id(), old_header_block.as_ref().map(|b| b.block_id()), qc_qc_block.block_id(), new_header_block.height(), self.max_quorum_height + ); + return; + } + /** * 这里只清理已经提交的block包含的proposal * 已经执行过的待提交block包含的proposal在下次打包时候去重 @@ -779,7 +863,8 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, process_block-step1 {:?}", - self, qc_qc_block.block_id() + self, + qc_qc_block.block_id() ); let (_, qc_block) = self @@ -789,11 +874,13 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(new_header_block, old_header_block, qc_block).await; + self.notify_block_committed(new_header_block, old_header_block, qc_block) + .await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", - self, qc_qc_block.block_id() + self, + qc_qc_block.block_id() ); // notify by the block generator @@ -806,13 +893,16 @@ impl HotstuffRunner { // reply let futs = new_header_block.proposals().iter().map(|proposal_info| { let receipt = match proposal_info.receipt.as_ref() { - Some(receipt) => NONObjectInfo::raw_decode(receipt.as_slice()).map(|(receipt, remain)| { - assert_eq!(remain.len(), 0); - Some(receipt) - }), + Some(receipt) => { + NONObjectInfo::raw_decode(receipt.as_slice()).map(|(receipt, remain)| { + assert_eq!(remain.len(), 0); + Some(receipt) + }) + } None => Ok(None), }; - self.proposal_result_notifier.reply(&proposal_info.proposal, receipt) + self.proposal_result_notifier + .reply(&proposal_info.proposal, receipt) }); futures::future::join_all(futs).await; @@ -820,59 +910,42 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, process_block-step3 {:?}", - self, qc_qc_block.block_id() + self, + qc_qc_block.block_id() ); } - async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); - - let mut pre_state_id = old_header_block - .as_ref() - .map_or(None, |b| b.result_state_id().clone()); + async fn notify_block_committed( + &self, + new_header: &GroupConsensusBlock, + old_header_block: &Option, + qc_block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + assert_eq!( + new_header.prev_block_id(), + old_header_block.as_ref().map(|b| b.block_id().object_id()) + ); - for proposal in new_header.proposals() { - let proposal_obj = self - .non_driver - .get_proposal(&proposal.proposal, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, new_header.block_id(), err - ); + if let Some(result_state_id) = new_header.result_state_id() { + self.make_sure_result_state(result_state_id, &[new_header.owner()]) + .await?; + } - err - })?; - let receipt = match proposal.receipt.as_ref() { - Some(receipt) => { - let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, new_header.block_id(), err - ); - err - })?; - assert_eq!(remain.len(), 0); - Some(receipt) + let prev_state_id = match old_header_block.as_ref() { + Some(old_header_block) => { + let result_state_id = old_header_block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[old_header_block.owner()]) + .await?; } - None => None, - }; + result_state_id.clone() + } + None => None, + }; - self.event_notifier - .on_commited( - proposal_obj, - pre_state_id, - &ExecuteResult { - result_state_id: proposal.result_state.clone(), - receipt, - context: proposal.context.clone(), - }, - new_header.clone(), - ) - .await; - - pre_state_id = proposal.result_state.clone(); - } + self.event_notifier + .on_commited(prev_state_id, new_header.clone()) + .await; Ok(()) } @@ -880,8 +953,11 @@ impl HotstuffRunner { async fn process_qc(&mut self, qc: &Option) { let qc_round = qc.as_ref().map_or(0, |qc| qc.round); - log::debug!("[hotstuff] local: {:?}, process_qc round {}", - self, qc_round); + log::debug!( + "[hotstuff] local: {:?}, process_qc round {}", + self, + qc_round + ); self.advance_round(qc_round).await; self.update_high_qc(qc); @@ -889,15 +965,23 @@ impl HotstuffRunner { async fn advance_round(&mut self, round: u64) { if round < self.round { - log::debug!("[hotstuff] local: {:?}, round {} timeout expect {}", - self, round, self.round); + log::debug!( + "[hotstuff] local: {:?}, round {} timeout expect {}", + self, + round, + self.round + ); return; } - match self.committee.get_group(None).await { + match self.committee.get_group(None).await { Ok(group) => { - log::info!("[hotstuff] local: {:?}, update round from {} to {}", - self, self.round, round + 1); + log::info!( + "[hotstuff] local: {:?}, update round from {} to {}", + self, + self.round, + round + 1 + ); self.timer.reset(group.consensus_interval()); self.round = round + 1; @@ -917,8 +1001,12 @@ impl HotstuffRunner { if to_high_round > cur_high_round { self.high_qc = qc.clone(); - log::info!("[hotstuff] local: {:?}, update high-qc from {} to {}", - self, cur_high_round, to_high_round); + log::info!( + "[hotstuff] local: {:?}, update high-qc from {} to {}", + self, + cur_high_round, + to_high_round + ); } } @@ -928,6 +1016,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_height(&mut self, quorum_height: u64) { + if quorum_height > self.max_quorum_height { + self.max_quorum_height = quorum_height; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -935,24 +1029,38 @@ impl HotstuffRunner { .map(|proposal| proposal.proposal) .collect::>(); - log::debug!("[hotstuff] local: {:?}, remove proposals: {:?}", - self, proposals.len()); + log::debug!( + "[hotstuff] local: {:?}, remove proposals: {:?}", + self, + proposals.len() + ); self.proposal_consumer.remove_proposals(proposals).await } async fn notify_proposal_err(&self, proposal: &GroupProposal, err: BuckyError) { - log::debug!("[hotstuff] local: {:?}, proposal {} failed {:?}", - self, proposal.desc().object_id(), err); + log::debug!( + "[hotstuff] local: {:?}, proposal {} failed {:?}", + self, + proposal.desc().object_id(), + err + ); - self.proposal_result_notifier.reply(&proposal.desc().object_id(), Err(err.clone())).await; + self.proposal_result_notifier + .reply(&proposal.desc().object_id(), Err(err.clone())) + .await; self.state_pusher .notify_proposal_err(proposal.clone(), err) .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { + async fn make_vote( + &mut self, + block: &GroupConsensusBlock, + mut proposals: &HashMap, + remote: &ObjectId, + ) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -973,9 +1081,9 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - // && qc_round - // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() - // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; @@ -1003,10 +1111,10 @@ impl HotstuffRunner { block.prev_block_id() ); - return None - }, + return None; + } }, - None => None + None => None, }; match self.check_group_is_latest(block.group_chunk_id()).await { @@ -1023,7 +1131,11 @@ impl HotstuffRunner { // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 let mut proposal_temp: HashMap = HashMap::new(); if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + match self + .non_driver + .load_all_proposals_for_block(block, &mut proposal_temp) + .await + { Ok(_) => proposals = &proposal_temp, Err(err) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", @@ -1031,7 +1143,7 @@ impl HotstuffRunner { block.block_id(), err ); - return None + return None; } } } else { @@ -1039,7 +1151,8 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", self, block.block_id(), ); @@ -1049,16 +1162,28 @@ impl HotstuffRunner { if proposals.len() != block.proposals().len() { let mut dup_proposals = block.proposals().clone(); dup_proposals.sort_unstable_by_key(|p| p.proposal); - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", self, block.block_id(), - dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + dup_proposals + .iter() + .group_by(|p| p.proposal) + .into_iter() + .map(|g| (g.0, g.1.count())) + .filter(|g| g.1 > 1) + .map(|g| g.0) + .collect_vec() ); return None; } - if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + if let Err(err) = self + .check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote) + .await + { + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", self, block.block_id(), err @@ -1066,16 +1191,24 @@ impl HotstuffRunner { return None; } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", - self, block.block_id(), block.round()); + log::debug!( + "[hotstuff] local: {:?}, make-vote before sign {}, round: {}", + self, + block.block_id(), + block.round() + ); let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => { - log::debug!("[hotstuff] local: {:?}, make-vote after sign {}, round: {}", - self, block.block_id(), block.round()); - + log::debug!( + "[hotstuff] local: {:?}, make-vote after sign {}, round: {}", + self, + block.block_id(), + block.round() + ); + vote - }, + } Err(e) => { log::warn!( "[hotstuff] local: {:?}, signature for block-vote failed, block: {}, err: {}", @@ -1099,11 +1232,16 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { + fn check_timestamp_precision( + block: &GroupConsensusBlock, + prev_block: Option<&GroupConsensusBlock>, + proposals: &HashMap, + ) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { - log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + log::warn!( + "[hotstuff] block {} check timestamp {:?} failed with now {:?}", block.block_id(), block_timestamp, now @@ -1112,31 +1250,36 @@ impl HotstuffRunner { false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); + let prev_block_time = + bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { - log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + log::warn!( + "[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", block.block_id(), block_timestamp, prev_block_time ); - return false + return false; } - } + } } for proposal in block.proposals() { let proposal_id = proposal.proposal; - let proposal = proposals.get(&proposal_id).expect("should load all proposals"); + let proposal = proposals + .get(&proposal_id) + .expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { - log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + log::warn!( + "[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", block.block_id(), block_timestamp, proposal_id, proposal_timestamp ); - return false + return false; } } true @@ -1163,7 +1306,9 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, receive timeout vote({}/{}/{:?}), local-round: {}", self, - vote.block_id, vote.round, vote.prev_block_id, + vote.block_id, + vote.round, + vote.prev_block_id, self.round ); return Ok(()); @@ -1173,7 +1318,9 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, verify vote({}/{}/{:?}) failed {:?}", self, - vote.block_id, vote.round, vote.prev_block_id, + vote.block_id, + vote.round, + vote.prev_block_id, err ); err @@ -1188,23 +1335,31 @@ impl HotstuffRunner { }; let is_prev_none = prev_block.is_none(); - let qc = self.vote_mgr.add_vote(vote.clone(), prev_block).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, add vote({}/{}/{:?}) prev-block: {} failed {:?}", - self, - vote.block_id, vote.round, vote.prev_block_id, - if is_prev_none {"None"} else {"Some"}, + let qc = self + .vote_mgr + .add_vote(vote.clone(), prev_block) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, add vote({}/{}/{:?}) prev-block: {} failed {:?}", + self, + vote.block_id, + vote.round, + vote.prev_block_id, + if is_prev_none { "None" } else { "Some" }, + err + ); err - ); - err - })?; + })?; if let Some((qc, block)) = qc { log::info!( "[hotstuff] local: {:?}, vote({}/{}/{:?}) prev-block: {} qc", self, - vote.block_id, vote.round, vote.prev_block_id, - if is_prev_none {"None"} else {"Some"} + vote.block_id, + vote.round, + vote.prev_block_id, + if is_prev_none { "None" } else { "Some" } ); self.process_block_qc(qc, &block).await?; @@ -1318,7 +1473,8 @@ impl HotstuffRunner { self.committee .verify_timeout(timeout, block.as_ref()) - .await.map_err(|err| { + .await + .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, handle_timeout: {:?}, verify failed {:?}", self, @@ -1334,7 +1490,8 @@ impl HotstuffRunner { let tc = self .vote_mgr .add_timeout(timeout.clone(), block.as_ref()) - .await.map_err(|err| { + .await + .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, handle_timeout: {:?}, check tc failed {:?}", self, @@ -1377,16 +1534,20 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", - self, - tc.round, - err - ); + let new_leader = self + .committee + .get_leader(None, self.round) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", + self, + tc.round, + err + ); - err - })?; + err + })?; if self.local_device_id == new_leader { self.generate_block(Some(tc)).await; Ok(()) @@ -1425,7 +1586,7 @@ impl HotstuffRunner { let max_high_qc = match max_high_qc { Some(max_high_qc) => max_high_qc, - None => return Ok(()) + None => return Ok(()), }; if tc.round < self.round { @@ -1436,12 +1597,13 @@ impl HotstuffRunner { ); return Ok(()); } - + if max_high_qc.high_qc_round >= tc.round { log::warn!( "[hotstuff] local: {:?}, handle_tc: {:?} ignore for high-qc round {} invalid", self, - tc.round, max_high_qc.high_qc_round + tc.round, + max_high_qc.high_qc_round ); return Ok(()); @@ -1476,15 +1638,18 @@ impl HotstuffRunner { Some(block) }; - self.committee.verify_tc(tc, block.as_ref()).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, handle_tc: {:?} verify tc failed {:?}", - self, - tc.round, + self.committee + .verify_tc(tc, block.as_ref()) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} verify tc failed {:?}", + self, + tc.round, + err + ); err - ); - err - })?; + })?; log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); @@ -1496,15 +1661,19 @@ impl HotstuffRunner { self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, handle_tc: {:?} get new leader failed {:?}", - self, - tc.round, + let new_leader = self + .committee + .get_leader(None, self.round) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} get new leader failed {:?}", + self, + tc.round, + err + ); err - ); - err - })?; + })?; if self.local_device_id == new_leader { self.generate_block(Some(tc.clone())).await; @@ -1513,10 +1682,7 @@ impl HotstuffRunner { } async fn local_timeout_round(&mut self) -> BuckyResult<()> { - log::debug!( - "[hotstuff] local: {:?}, local_timeout_round", - self, - ); + log::debug!("[hotstuff] local: {:?}, local_timeout_round", self,); let latest_group = match self.committee.get_group(None).await { Ok(group) => { @@ -1526,7 +1692,8 @@ impl HotstuffRunner { Err(err) => { log::warn!( "[hotstuff] local: {:?}, local_timeout_round get latest group failed {:?}", - self, err + self, + err ); self.timer.reset(HOTSTUFF_TIMEOUT_DEFAULT); @@ -1539,10 +1706,13 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ).await.map_err(|err| { + ) + .await + .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", - self, err + self, + err ); err })?; @@ -1550,7 +1720,9 @@ impl HotstuffRunner { self.store.set_last_vote_round(self.round).await?; self.broadcast(HotstuffMessage::TimeoutVote(timeout.clone()), &latest_group); - self.tx_message.send((HotstuffMessage::TimeoutVote(timeout), self.local_device_id)).await; + self.tx_message + .send((HotstuffMessage::TimeoutVote(timeout), self.local_device_id)) + .await; Ok(()) } @@ -1561,19 +1733,32 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, generate_block with qc {:?} and tc {:?}, now: {:?}", self, - self.high_qc.as_ref().map(|qc| format!("{}/{}/{:?}", qc.block_id, qc.round, qc.votes.iter().map(|v| v.voter).collect::>())), - tc.as_ref().map(|tc| format!("{}/{:?}", tc.round, tc.votes.iter().map(|v| v.voter).collect::>())), + self.high_qc.as_ref().map(|qc| format!( + "{}/{}/{:?}", + qc.block_id, + qc.round, + qc.votes.iter().map(|v| v.voter).collect::>() + )), + tc.as_ref().map(|tc| format!( + "{}/{:?}", + tc.round, + tc.votes.iter().map(|v| v.voter).collect::>() + )), now ); - let mut proposals = self.proposal_consumer.query_proposals().await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, generate_block query proposal failed {:?}", - self, + let mut proposals = self + .proposal_consumer + .query_proposals() + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, generate_block query proposal failed {:?}", + self, + err + ); err - ); - err - })?; + })?; proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); @@ -1581,10 +1766,11 @@ impl HotstuffRunner { Some(qc) => { let prev_block = self.store.find_block_in_cache(&qc.block_id)?; if let Some(result_state_id) = prev_block.result_state_id() { - self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + self.make_sure_result_state(result_state_id, &[prev_block.owner()]) + .await?; } Some(prev_block) - }, + } None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1593,7 +1779,7 @@ impl HotstuffRunner { self, err ); - + err })?; @@ -1626,25 +1812,29 @@ impl HotstuffRunner { } let create_time = bucky_time_to_system_time(proposal.desc().create_time()); - if Self::calc_time_delta(now, create_time) - > TIME_PRECISION - { + if Self::calc_time_delta(now, create_time) > TIME_PRECISION { // 时间误差太大 remove_proposals.push(proposal.desc().object_id()); time_adjust_proposals.push(proposal); continue; } - let ending = proposal.effective_ending() - .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), - |ending| bucky_time_to_system_time(ending)); + let ending = proposal + .effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), |ending| { + bucky_time_to_system_time(ending) + }); if now >= ending { remove_proposals.push(proposal.desc().object_id()); timeout_proposals.push(proposal); continue; } - match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { + match self + .event_notifier + .on_execute(proposal.clone(), result_state_id) + .await + { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); @@ -1656,7 +1846,8 @@ impl HotstuffRunner { }; } - self.notify_adjust_time_proposals(time_adjust_proposals).await; + self.notify_adjust_time_proposals(time_adjust_proposals) + .await; self.notify_timeout_proposals(timeout_proposals).await; self.notify_failed_proposals(failed_proposals).await; self.remove_pending_proposals(remove_proposals).await; @@ -1673,11 +1864,20 @@ impl HotstuffRunner { } let proposals_map = HashMap::from_iter( - executed_proposals.iter() - .map(|(proposal, _)| (proposal.desc().object_id(), proposal.clone())) + executed_proposals + .iter() + .map(|(proposal, _)| (proposal.desc().object_id(), proposal.clone())), ); - let block = self.package_block_with_proposals(executed_proposals, &latest_group, result_state_id, &prev_block, tc).await?; + let block = self + .package_block_with_proposals( + executed_proposals, + &latest_group, + result_state_id, + &prev_block, + tc, + ) + .await?; self.broadcast(HotstuffMessage::Block(block.clone()), &latest_group); self.tx_block_gen.send((block, proposals_map)).await; @@ -1691,10 +1891,17 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, generate_block timestamp err {:?}", self, - time_adjust_proposals.iter().map(|proposal| { - let desc = proposal.desc(); - (desc.object_id(), desc.owner(), bucky_time_to_system_time(desc.create_time())) - }).collect::>() + time_adjust_proposals + .iter() + .map(|proposal| { + let desc = proposal.desc(); + ( + desc.object_id(), + desc.owner(), + bucky_time_to_system_time(desc.create_time()), + ) + }) + .collect::>() ); } @@ -1713,15 +1920,21 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, generate_block timeout {:?}", self, - timeout_proposals.iter().map(|proposal| { - let desc = proposal.desc(); - ( - desc.object_id(), - desc.owner(), - bucky_time_to_system_time(desc.create_time()), - proposal.effective_ending().as_ref().map(|ending| bucky_time_to_system_time(*ending)) - ) - }).collect::>() + timeout_proposals + .iter() + .map(|proposal| { + let desc = proposal.desc(); + ( + desc.object_id(), + desc.owner(), + bucky_time_to_system_time(desc.create_time()), + proposal + .effective_ending() + .as_ref() + .map(|ending| bucky_time_to_system_time(*ending)), + ) + }) + .collect::>() ); } @@ -1740,14 +1953,13 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, generate_block failed proposal {:?}", self, - failed_proposals.iter().map(|(proposal, err)| { - let desc = proposal.desc(); - ( - desc.object_id(), - desc.owner(), - err.clone() - ) - }).collect::>() + failed_proposals + .iter() + .map(|(proposal, err)| { + let desc = proposal.desc(); + (desc.object_id(), desc.owner(), err.clone()) + }) + .collect::>() ); } @@ -1771,12 +1983,13 @@ impl HotstuffRunner { .await; } - async fn package_block_with_proposals(&self, + async fn package_block_with_proposals( + &self, executed_proposals: Vec<(GroupProposal, ExecuteResult)>, group: &Group, result_state_id: Option, prev_block: &Option, - tc: Option + tc: Option, ) -> BuckyResult { let proposal_count = executed_proposals.len(); let proposals_param = executed_proposals @@ -1811,7 +2024,10 @@ impl HotstuffRunner { log::info!( "[hotstuff] local: {:?}, generate_block new block {}/{}/{}, with proposals: {}", self, - block.block_id(), block.height(), block.round(), proposal_count + block.block_id(), + block.height(), + block.round(), + proposal_count ); self.sign_block(&mut block).await.map_err(|err| { @@ -1858,7 +2074,9 @@ impl HotstuffRunner { let rpath = self.rpath.clone(); async_std::task::spawn(async move { - network_sender.broadcast(msg, rpath.clone(), targets.as_slice()).await + network_sender + .broadcast(msg, rpath.clone(), targets.as_slice()) + .await }); Ok(()) @@ -1880,24 +2098,26 @@ impl HotstuffRunner { ); will_wait_proposals = true - }, + } Some(pre_block) => { if pre_block.proposals().len() == 0 { match pre_block.prev_block_id() { Some(pre_pre_block_id) => { - let pre_pre_block = - match self.store.find_block_in_cache(pre_pre_block_id) { - Ok(pre_pre_block) => pre_pre_block, - Err(err) => { - log::warn!( + let pre_pre_block = match self + .store + .find_block_in_cache(pre_pre_block_id) + { + Ok(pre_pre_block) => pre_pre_block, + Err(err) => { + log::warn!( "[hotstuff] local: {:?}, new empty block will generate for find prev-block {} failed {:?}", self, pre_pre_block_id, err ); - return false; - } - }; + return false; + } + }; if pre_pre_block.proposals().len() == 0 { log::warn!( "[hotstuff] local: {:?}, new empty block will ignore for 2 prev-block({}/{}) is empty", @@ -1926,7 +2146,7 @@ impl HotstuffRunner { if will_wait_proposals { match self.proposal_consumer.wait_proposals().await { Ok(rx) => self.rx_proposal_waiter = Some((rx, self.round)), - _ => return false + _ => return false, } } @@ -1934,12 +2154,12 @@ impl HotstuffRunner { } async fn handle_proposal_waiting(&mut self) -> BuckyResult<()> { - log::debug!( - "[hotstuff] local: {:?}, handle_proposal_waiting", - self - ); + log::debug!("[hotstuff] local: {:?}, handle_proposal_waiting", self); - assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); + assert_eq!( + self.committee.get_leader(None, self.round).await?, + self.local_device_id + ); self.generate_block(self.with_tc()).await } @@ -1983,58 +2203,111 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } - async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + async fn make_sure_result_state( + &self, + result_state_id: &ObjectId, + remotes: &[&ObjectId], + ) -> BuckyResult<()> { // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 let obj_map_processor = self.store.get_object_map_processor(); + let local_trace_log = format!("{:?}", self); #[async_recursion::async_recursion] - async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + async fn make_sure_sub_tree( + root_id: &ObjectId, + non_driver: crate::network::NONDriverHelper, + remote: &ObjectId, + obj_map_processor: &dyn GroupObjectMapProcessor, + local_trace_log: &str, + ) -> BuckyResult<()> { if root_id.is_data() { return Ok(()); } if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 + log::debug!( + "[hotstuff] {} make_sure_result_state {} already exist.", + local_trace_log, + root_id + ); return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { - log::warn!("get branch {} failed {:?}", root_id, err); - err - })?; + let obj = non_driver + .get_object(root_id, Some(remote)) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] {} get branch {} failed {:?}", + local_trace_log, + root_id, + err + ); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { - let single_op_env = obj_map_processor.create_single_op_env().await?; - single_op_env.load(root_id).await?; + let single_op_env = obj_map_processor.create_single_op_env().await.map_err(|err| { + log::warn!("[hotstuff] {} make_sure_result_state {} create_single_op_env failed {:?}.", local_trace_log, root_id, err); + err + })?; + single_op_env.load(root_id).await.map_err(|err| { + log::warn!( + "[hotstuff] {} make_sure_result_state {} load failed {:?}.", + local_trace_log, + root_id, + err + ); + err + })?; loop { let branchs = single_op_env.next(16).await?; for branch in branchs.list.iter() { let branch_id = match branch { - cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { - Some(branch_id) => branch_id, - None => continue, - }, + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => { + match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + } + } cyfs_base::ObjectMapContentItem::Map(map) => &map.1, - cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { - Some(branch_id) => branch_id, - None => continue, - }, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => { + match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + } + } cyfs_base::ObjectMapContentItem::Set(set) => set, }; - make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + make_sure_sub_tree( + branch_id, + non_driver.clone(), + remote, + obj_map_processor, + local_trace_log, + ) + .await?; } if branchs.list.len() < 16 { - return Ok(()) + return Ok(()); } } - }, - _ => return Ok(()) + } + _ => return Ok(()), } } let mut result = Ok(()); for remote in remotes { - result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + result = make_sure_sub_tree( + result_state_id, + self.non_driver.clone(), + remote, + obj_map_processor, + local_trace_log.as_str(), + ) + .await; if result.is_ok() { return result; } diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index a25accb19..5573cab44 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -109,17 +109,11 @@ impl RPathEventNotifier { pub async fn on_commited( &self, - proposal: GroupProposal, prev_state_id: Option, - execute_result: &ExecuteResult, block: GroupConsensusBlock, ) { let cmd = GroupCommandCommited { - proposal, prev_state_id, - result_state_id: execute_result.result_state_id.clone(), - receipt: execute_result.receipt.clone(), - context: execute_result.context.clone(), block, }; diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 1f2a46a73..b6eec1177 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -461,7 +461,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; - encode_with_length(buf, addr, purpose, 2)?; + let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; max.raw_encode(buf, purpose) } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index dcbc64a53..a33e09187 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -63,7 +63,17 @@ impl Sender { let mut buf = Vec::with_capacity(len); buf.resize(len, 0); let remain = pkg.raw_encode(buf.as_mut_slice(), &None).unwrap(); - assert_eq!(remain.len(), 0); + + assert_eq!( + remain.len(), + 0, + "[group-sender] {:?}-{} post group message to {:?} encode err, pkg: {:?}, len: {}", + pkg.rpath(), + self.local_device_id, + remote, + pkg, + buf.len() + ); log::debug!( "[group-sender] {:?}-{} post group message to {:?}, pkg: {:?}, len: {}", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 7347a4c38..7613e3447 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -31,7 +31,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { - log::debug!( + log::info!( "get object {}, local: {}, from: {:?}", object_id, self.local_device_id, @@ -68,7 +68,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); - log::debug!( + log::info!( "put object {} with access {}, local: {}", obj.object_id, access, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 6bcc78920..7ededd629 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -575,10 +575,11 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - CreateObjectMapOption, GlobalStatePathAccessItem, NONObjectInfo, NONPostObjectInputRequest, - NONPostObjectInputResponse, RequestGlobalStatePath, RequestSourceInfo, RouterHandlerAction, - RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, - RouterHandlerPostObjectResult, SharedCyfsStack, + CreateObjectMapOption, GlobalStatePathAccessItem, NONAPILevel, NONGetObjectInputRequest, + NONGetObjectOutputRequest, NONInputRequestCommon, NONObjectInfo, NONOutputRequestCommon, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestGlobalStatePath, + RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, + RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -598,6 +599,8 @@ mod GroupDecService { cyfs_stack.clone(), Box::new(GroupRPathDelegateFactory { local_name: local_name.clone(), + stack: cyfs_stack.clone(), + dec_id: dec_app_id.object_id().clone(), }), &cyfs_lib::CyfsStackRequestorType::Http, ) @@ -610,7 +613,11 @@ mod GroupDecService { .start_rpath_service( group_id, rpath.to_string(), - Box::new(MyRPathDelegate::new(local_name.to_string())), + Box::new(MyRPathDelegate::new( + local_name.to_string(), + cyfs_stack.clone(), + dec_app_id.object_id().clone(), + )), ) .await .unwrap(), @@ -687,6 +694,8 @@ mod GroupDecService { pub struct GroupRPathDelegateFactory { local_name: String, + stack: SharedCyfsStack, + dec_id: ObjectId, } impl GroupRPathDelegateFactory { @@ -712,7 +721,11 @@ mod GroupDecService { ) -> BuckyResult> { if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 - Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) + Ok(Box::new(MyRPathDelegate::new( + self.local_name.clone(), + self.stack.clone(), + self.dec_id.clone(), + ))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } @@ -721,14 +734,18 @@ mod GroupDecService { pub struct MyRPathDelegate { local_name: String, + stack: SharedCyfsStack, + dec_id: ObjectId, finished_proposals: Arc>>, } impl MyRPathDelegate { - pub fn new(local_name: String) -> Self { + pub fn new(local_name: String, stack: SharedCyfsStack, dec_id: ObjectId) -> Self { MyRPathDelegate { local_name, finished_proposals: Arc::new(Mutex::new(HashSet::new())), + stack, + dec_id, } } } @@ -918,19 +935,12 @@ mod GroupDecService { async fn on_commited( &self, - proposal: &GroupProposal, prev_state_id: &Option, - execute_result: &ExecuteResult, block: &GroupConsensusBlock, object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 - let delta_buf = proposal.params().as_ref().unwrap().as_slice(); - let mut delta = [0u8; 8]; - delta.copy_from_slice(delta_buf); - let delta = u64::from_be_bytes(delta); - let prev_value = match prev_state_id { Some(prev_state_id) => { let state_op_env = object_map_processor @@ -958,14 +968,14 @@ mod GroupDecService { u64::from_be_bytes(prev_value) }); - let result_value = match execute_result.result_state_id { + let result_value = match block.result_state_id() { Some(result_state_id) => { let state_op_env = object_map_processor .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(result_state_id) + .load(result_state_id.clone()) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -985,21 +995,53 @@ mod GroupDecService { u64::from_be_bytes(result_value) }); - let proposal_id = proposal.desc().object_id(); + let proposal_infos = + futures::future::join_all(block.proposals().iter().map(|proposal_info| async { + let proposal = self + .stack + .non_service() + .get_object(NONGetObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(self.dec_id), + level: NONAPILevel::Router, + target: Some(block.owner().clone()), + flags: 0, + }, + object_id: proposal_info.proposal, + inner_path: None, + }) + .await + .unwrap(); + let proposal = proposal.object; + let (proposal, _remain) = + GroupProposal::raw_decode(proposal.object_raw.as_slice()).unwrap(); + + let delta_buf = proposal.params().as_ref().unwrap().as_slice(); + let mut delta = [0u8; 8]; + delta.copy_from_slice(delta_buf); + let delta = u64::from_be_bytes(delta); + (proposal_info.proposal, delta) + })) + .await; log::info!( - "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", + "proposal commited: height: {}/{}, delta: {:?}, result: {} -> {}, proposal: {:?}, block: {}, local: {}", block.height(), block.round(), - delta, + proposal_infos.iter().map(|(_, delta)| *delta).collect::>(), prev_value, result_value, - proposal_id, + proposal_infos.iter().map(|(id, _)| *id).collect::>(), block.block_id(), self.local_name ); - let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); - assert!(is_new_finished); + let mut finished_proposals = self.finished_proposals.lock().await; + block.proposals().iter().for_each(|proposal_info| { + let is_new_finished = finished_proposals.insert(proposal_info.proposal); + assert!(is_new_finished); + }); } } } @@ -1148,13 +1190,13 @@ async fn main_run() { member_group_mgrs.push(group_mgr); } - async_std::task::sleep(Duration::from_millis(10000)).await; + // async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 20usize; + let PROPOSAL_COUNT = 200usize; for i in 1..PROPOSAL_COUNT { let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); @@ -1187,13 +1229,7 @@ async fn main_run() { }; noc.put_object(req).await; proposals.push(proposal); - } - // futures::future::join_all(prepare_futures).await; - - log::info!("proposals prepared."); - - for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = member_stacks.get(i % member_stacks.len()).unwrap(); let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); @@ -1227,12 +1263,18 @@ async fn main_run() { ); }); - if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(1000)).await; + if i % 28 == 0 { + async_std::task::sleep(Duration::from_millis(4000)).await; log::info!("will push new proposals, i: {}", i); } } + // futures::future::join_all(prepare_futures).await; + + log::info!("proposals prepared."); + + // for i in 1..PROPOSAL_COUNT {} + async_std::task::sleep(Duration::from_millis(20000)).await; // let client = admin_group_mgrs From 4a5876f78f4fc092ee9a63d6db5e1c28bd114a1d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Mar 2023 20:43:00 +0800 Subject: [PATCH 425/553] Timeout and retry to avoid the long-pending in NON --- .../src/consensus/hotstuff/hotstuff.rs | 36 +++++ .../cyfs-group/src/dec/group_manager.rs | 12 +- .../cyfs-group/src/network/non_driver.rs | 30 ++++- .../cyfs-stack/src/stack/group_non_driver.rs | 126 ++++++++++++++++-- src/tests/group-example/src/main.rs | 20 ++- 5 files changed, 206 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e7f69f9a1..d69207622 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1061,6 +1061,12 @@ impl HotstuffRunner { mut proposals: &HashMap, remote: &ObjectId, ) -> Option { + log::debug!( + "[hotstuff] local: {:?} make vote {} step 0", + self, + block.block_id() + ); + if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -1117,6 +1123,12 @@ impl HotstuffRunner { None => None, }; + log::debug!( + "[hotstuff] local: {:?} make vote {} step 1", + self, + block.block_id() + ); + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -1128,6 +1140,12 @@ impl HotstuffRunner { } } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 2", + self, + block.block_id() + ); + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 let mut proposal_temp: HashMap = HashMap::new(); if proposals.len() == 0 && block.proposals().len() > 0 { @@ -1150,6 +1168,12 @@ impl HotstuffRunner { assert_eq!(proposals.len(), block.proposals().len()); } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 3", + self, + block.block_id() + ); + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { log::warn!( "[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", @@ -1178,6 +1202,12 @@ impl HotstuffRunner { return None; } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 4", + self, + block.block_id() + ); + if let Err(err) = self .check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote) .await @@ -1229,6 +1259,12 @@ impl HotstuffRunner { return None; } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 5", + self, + block.block_id() + ); + Some(vote) } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 766da468e..f7e874cff 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -107,7 +107,11 @@ impl GroupManager { let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); let state_mgr = local_info.global_state_mgr.clone(); - let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let non_driver = NONDriverHelper::new( + local_info.non_driver.clone(), + dec_id.clone(), + local_device_id.object_id().clone(), + ); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -386,7 +390,11 @@ impl GroupManager { let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); - let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let non_driver = NONDriverHelper::new( + local_info.non_driver.clone(), + dec_id.clone(), + local_device_id.object_id().clone(), + ); let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index c7f9e7d93..b8a2ac29b 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -38,14 +38,20 @@ pub(crate) struct NONDriverHelper { driver: Arc>, dec_id: ObjectId, cache: NONObjectCache, + local_device_id: ObjectId, } impl NONDriverHelper { - pub fn new(driver: Arc>, dec_id: ObjectId) -> Self { + pub fn new( + driver: Arc>, + dec_id: ObjectId, + local_device_id: ObjectId, + ) -> Self { Self { driver, dec_id, cache: NONObjectCache::new(), + local_device_id, } } @@ -239,14 +245,32 @@ impl NONDriverHelper { _ => panic!("invalid remote type: {:?}", block_owner.obj_type_code()), }; + log::debug!( + "{} load_all_proposals_for_block {} from {}", + self.local_device_id, + block.block_id(), + remote + ); + let load_futs = block.proposals().iter().map(|proposal| { let proposal_id = proposal.proposal; let non_driver = non_driver.clone(); let remote = remote.clone(); async move { - non_driver + let ret = non_driver .get_proposal(&proposal_id, Some(remote.object_id())) - .await + .await; + + log::debug!( + "{} load_all_proposals_for_block {}/{} from {}, ret: {:?}", + self.local_device_id, + block.block_id(), + proposal_id, + remote, + ret.as_ref().map(|_| ()) + ); + + ret } }); diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 7613e3447..5f00c6640 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,14 +1,17 @@ -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; -use cyfs_base::{AccessString, BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, RequestGlobalStatePath, RequestProtocol, RequestSourceInfo, }; +use futures::FutureExt; use crate::{non::NONInputProcessor, non_api::NONService}; +const TIMEOUT_HALF: Duration = Duration::from_millis(2000); + pub struct GroupNONDriver { non_service: Arc, local_device_id: ObjectId, @@ -21,11 +24,8 @@ impl GroupNONDriver { local_device_id, } } -} -#[async_trait::async_trait] -impl cyfs_group::NONDriver for GroupNONDriver { - async fn get_object( + async fn get_object_impl( &self, dec_id: &ObjectId, object_id: &ObjectId, @@ -65,7 +65,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { .map(|resp| resp.object) } - async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + async fn put_object_impl(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); log::info!( @@ -102,7 +102,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { .map(|_| ()) } - async fn post_object( + async fn post_object_impl( &self, dec_id: &ObjectId, obj: NONObjectInfo, @@ -149,3 +149,113 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) } } + +#[async_trait::async_trait] +impl cyfs_group::NONDriver for GroupNONDriver { + async fn get_object( + &self, + dec_id: &ObjectId, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let fut1 = match futures::future::select( + self.get_object_impl(dec_id, object_id, from).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!( + "group get object timeout (type={:?}) from {:?}, local: {:?}", + object_id.obj_type_code(), + from, + self.local_device_id + ); + + match futures::future::select( + self.get_object_impl(dec_id, object_id, from).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } + + async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let fut1 = match futures::future::select( + self.put_object_impl(dec_id, obj.clone()).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!( + "group put object timeout (type={:?}/{:?}), local: {:?}", + obj.object_id.obj_type_code(), + obj.object.as_ref().map(|o| o.obj_type()), + self.local_device_id + ); + + match futures::future::select( + self.put_object_impl(dec_id, obj).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } + + async fn post_object( + &self, + dec_id: &ObjectId, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { + let fut1 = match futures::future::select( + self.post_object_impl(dec_id, obj.clone(), to).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!( + "group post object timeout (type={:?}/{:?}) to {:?}, local: {:?}", + obj.object_id.obj_type_code(), + obj.object.as_ref().map(|o| o.obj_type()), + to, + self.local_device_id + ); + + match futures::future::select( + self.post_object_impl(dec_id, obj, to).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } +} diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 7ededd629..752e9c4ac 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -578,8 +578,9 @@ mod GroupDecService { CreateObjectMapOption, GlobalStatePathAccessItem, NONAPILevel, NONGetObjectInputRequest, NONGetObjectOutputRequest, NONInputRequestCommon, NONObjectInfo, NONOutputRequestCommon, NONPostObjectInputRequest, NONPostObjectInputResponse, RequestGlobalStatePath, - RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, - RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, + RequestSourceInfo, RootStateOpEnvAccess, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, + RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -758,7 +759,10 @@ mod GroupDecService { object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env(None) + .create_sub_tree_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) .await .expect(format!("create_sub_tree_op_env failed").as_str()); let prev_value = match prev_state_id { @@ -944,7 +948,10 @@ mod GroupDecService { let prev_value = match prev_state_id { Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env(None) + .create_sub_tree_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env @@ -971,7 +978,10 @@ mod GroupDecService { let result_value = match block.result_state_id() { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env(None) + .create_sub_tree_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env From 9119a611033055a2e3ffac5d1473f200547ff667 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Mar 2023 20:44:07 +0800 Subject: [PATCH 426/553] Rebuild result-state by DEC.on_verify when it's download from remote failed. --- .../src/consensus/hotstuff/hotstuff.rs | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d69207622..2d416c357 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1074,11 +1074,25 @@ impl HotstuffRunner { return None; } + let mut only_rebuild_result_state = false; if self.max_quorum_round >= self.round { - log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", - self, block.block_id(), block.round(), self.max_quorum_round, self.round); + if let Some(result_state_id) = block.result_state_id() { + if self + .make_sure_result_state(result_state_id, &[block.owner(), remote]) + .await + .is_err() + { + // download from remote failed, we need to calcute the result-state by the DEC.on_verify + only_rebuild_result_state = true; + } + } - return None; + if !only_rebuild_result_state { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } } // round只能逐个递增 @@ -1129,14 +1143,16 @@ impl HotstuffRunner { block.block_id() ); - match self.check_group_is_latest(block.group_chunk_id()).await { - Ok(is_latest) if is_latest => {} - _ => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", - self, - block.block_id()); + if !only_rebuild_result_state { + match self.check_group_is_latest(block.group_chunk_id()).await { + Ok(is_latest) if is_latest => {} + _ => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", + self, + block.block_id()); - return None; + return None; + } } } @@ -1146,7 +1162,6 @@ impl HotstuffRunner { block.block_id() ); - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 let mut proposal_temp: HashMap = HashMap::new(); if proposals.len() == 0 && block.proposals().len() > 0 { match self @@ -1174,7 +1189,10 @@ impl HotstuffRunner { block.block_id() ); - if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + if !only_rebuild_result_state + && !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) + { log::warn!( "[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", self, @@ -1183,7 +1201,7 @@ impl HotstuffRunner { return None; } - if proposals.len() != block.proposals().len() { + if !only_rebuild_result_state && proposals.len() != block.proposals().len() { let mut dup_proposals = block.proposals().clone(); dup_proposals.sort_unstable_by_key(|p| p.proposal); log::warn!( @@ -1228,6 +1246,12 @@ impl HotstuffRunner { block.round() ); + if only_rebuild_result_state { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{} rebuild only.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + return None; + } + let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => { log::debug!( From 1609d514004a7b59cf6ac6be454277351eb4de83 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Mar 2023 20:58:11 +0800 Subject: [PATCH 427/553] Add signature for desc --- .../cyfs-stack/src/resolver/device_manager.rs | 3 ++- src/tests/group-example/src/main.rs | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 97e822c31..7deeb0083 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -128,6 +128,7 @@ impl DeviceInfoManagerImpl { object_id: &ObjectId, object: &Arc, ) -> BuckyResult<()> { + // TODO: 先验证所有成员签名,但这跟Group的变更策略有关,最终可能要跟链上比对才能验证,因为如果Group变更只需要部分成员签名,这将导致Group上只携带部分成员的签名 if object_id.obj_type_code() != ObjectTypeCode::Group { let msg = format!( "verify object own's body sign by owner failed for expect group, id = {}", @@ -181,7 +182,7 @@ impl DeviceInfoManagerImpl { let singer_obj_any = signer_obj.object.take(); let req = VerifyObjectInnerRequest { - sign_type: VerifySignType::Body, + sign_type: VerifySignType::Both, object: ObjectInfo { object_id: object_id.clone(), object: object.clone(), diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 752e9c4ac..880732884 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -197,6 +197,7 @@ mod Common { log::info!("create group: {:?}", group.desc().object_id()); + let desc_hash = group.desc().raw_hash_value().unwrap(); let body_hash = group.body().as_ref().unwrap().raw_hash_value().unwrap(); let signers = [admins, members].concat(); signers @@ -205,6 +206,17 @@ mod Common { let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); async_std::task::block_on(async move { + let desc_signature = signer + .sign( + desc_hash.as_slice(), + &cyfs_base::SignatureSource::Object(ObjectLink { + obj_id: owner.desc().object_id(), + obj_owner: None, + }), + ) + .await + .unwrap(); + let body_signature = signer .sign( body_hash.as_slice(), @@ -215,10 +227,13 @@ mod Common { ) .await .unwrap(); - body_signature + (desc_signature, body_signature) }) }) - .for_each(|signature| group.signs_mut().push_body_sign(signature)); + .for_each(|(desc_signature, body_signature)| { + group.signs_mut().push_desc_sign(desc_signature); + group.signs_mut().push_body_sign(body_signature); + }); group } From b9a8ddaca732bcbc8a688cccce25f11708a85913 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 8 Apr 2023 16:40:21 +0800 Subject: [PATCH 428/553] Remove fields for rights in `Group`. --- .../protos/standard_objects-permission.proto | 115 -------- .../cyfs-base/protos/standard_objects.proto | 59 +--- src/component/cyfs-base/src/objects/group.rs | 262 ++---------------- src/component/cyfs-chunk-lib/src/chunk.rs | 32 --- .../cyfs-core/protos/core_objects.proto | 2 +- .../cyfs-core/src/group/group_blob.rs | 44 +++ .../src/group/group_consensus_block.rs | 18 +- src/component/cyfs-core/src/group/mod.rs | 2 + .../src/objects/group_update_proposal.rs | 53 ++-- src/component/cyfs-group/Cargo.toml | 1 - .../src/consensus/hotstuff/hotstuff.rs | 53 ++-- .../consensus/synchronizer/synchronizer.rs | 2 +- .../src/consensus/vote/committee.rs | 30 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 4 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/rpath_service.rs | 1 - .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 18 +- .../cyfs-group/src/dec_state/state_pusher.rs | 22 +- src/component/cyfs-group/src/helper/timer.rs | 2 - .../cyfs-group/src/network/listener.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 14 +- .../cyfs-group/src/storage/group_storage.rs | 24 +- src/tests/group-example/src/main.rs | 2 - 24 files changed, 182 insertions(+), 583 deletions(-) delete mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto create mode 100644 src/component/cyfs-core/src/group/group_blob.rs diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto deleted file mode 100644 index 09f9e3684..000000000 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ /dev/null @@ -1,115 +0,0 @@ -syntax="proto3"; - -// contract -message ContractBodyContent { - bytes data = 1; -} - -// device -message DeviceBodyContent { - repeated bytes endpoints = 1; - repeated bytes sn_list = 2; - repeated bytes passive_pn_list = 3; - optional string name = 4; - optional uint32 bdt_version = 5; -} - -// dir -message DirBodyContent { - enum Type { - Chunk = 0; - ObjList = 1; - } - Type type = 1; - optional bytes chunk_id = 2; - - // 使用list编码hash_map - message ObjItem { - bytes obj_id = 1; - bytes value = 2; - } - repeated ObjItem obj_list = 3; -} - -// file -message ChunkList { - enum Type { - ChunkInList = 0; - ChunkInFile = 1; - ChunkInBundle = 2; - } - enum HashMethod { - Serial = 0; - } - - Type type = 1; - repeated bytes chunk_id_list = 2; - bytes file_id = 3; - optional HashMethod hash_method = 4; -} - -message FileBodyContent { - ChunkList chunk_list = 1; -} - -// people -message PeopleBodyContent { - repeated bytes ood_list = 1; - optional string name = 2; - optional bytes icon = 3; - optional string ood_work_mode = 4; -} - -message GroupMember { - bytes id = 1; - string title = 2; -} - -message CommonGroupBodyContent { - string name = 1; - optional bytes icon = 2; - string description = 3; - - repeated GroupMember members = 4; - - repeated bytes ood_list = 5; - - optional bytes prev_version = 6; - uint64 version_num = 7; -} - -// simple_group -message SimpleGroupDescContent { - bytes unique_id = 1; - bytes founder_id = 2; - repeated GroupMember admins = 3; -} - -message SimpleGroupBodyContent { - CommonGroupBodyContent common = 1; -} - -// org -message OrgDescContent { - bytes unique_id = 1; - bytes founder_id = 2; -} - -message OrgBodyContent { - repeated GroupMember admins = 1; - CommonGroupBodyContent common = 2; -} - -// tx -message TxBodyContent { - bytes data = 1; -} - -// proof_of_service -message ProofData { - bytes data = 1; -} - -message ProofOfServiceBodyContent { - ProofData data = 1; -} \ No newline at end of file diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index 4a9714958..a363ec57a 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -63,39 +63,6 @@ message PeopleBodyContent { message GroupMember { bytes id = 1; string title = 2; - string role = 3; // for acl - uint64 shares = 4; -} - -message GroupMethodACL { - string name = 1; - - // target - optional bytes target_dec_id = 2; - optional string rpath = 3; - - double min_support_percent = 4; - string permissions = 5; // ACL-String -} - -message GroupRoleACL { - string name = 1; - - // target - optional bytes target_dec_id = 2; - optional string rpath = 3; - string method = 4; - - double right_percent = 5; - bool is_operator = 6; - string permissions = 7; // ACL-String -} - -message GroupJoinSignature { - bytes signature = 1; // Sign(member_id, group_id, hash, is_admin) - bytes member_id = 2; - bool is_admin = 4; - bytes hash = 5; // Hash(Encode(Group)) } message CommonGroupBodyContent { @@ -105,24 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - uint64 total_equity = 5; - - // acl - repeated GroupMethodACL method_acls = 6; - repeated GroupRoleACL role_acls = 7; - - repeated bytes ood_list = 8; // 1/0 for every member/admin - - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms - - repeated bytes revoked_conclusions = 12; - - uint64 version = 13; - - // TODO: 这个Group的签名准备放到Group信息变更的提案里 - repeated GroupJoinSignature join_signatures = 14; // signature for every member/admin + repeated bytes ood_list = 5; + + optional bytes prev_blob_id = 6; + uint64 version = 7; } // simple_group @@ -130,7 +83,6 @@ message SimpleGroupDescContent { bytes unique_id = 1; bytes founder_id = 2; repeated GroupMember admins = 3; - uint32 conclusion_limit = 4; // the admins can make any conclusion with the signatures more than ${conclusion_limit} } message SimpleGroupBodyContent { @@ -145,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 5c8cda714..29aee5849 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -1,7 +1,6 @@ use crate::codec as cyfs_base; use crate::*; -use std::collections::HashSet; use std::convert::TryFrom; pub enum GroupMemberScope { @@ -72,6 +71,10 @@ impl GroupBodyContent { self.common().version } + pub fn prev_blob_id(&self) -> &Option { + &self.common().prev_blob_id + } + fn common(&self) -> &CommonGroupBodyContent { match self { GroupBodyContent::Org(body) => &body.common, @@ -94,8 +97,6 @@ pub type GroupDesc = NamedObjectDesc; pub type GroupId = NamedObjectId; pub type Group = NamedObjectBase; -pub const GROUP_DEFAULT_CONSENSUS_INTERVAL: u64 = 5000; // default 5000 ms - impl GroupDesc { pub fn group_id(&self) -> GroupId { GroupId::try_from(self.calculate_id()).unwrap() @@ -106,12 +107,10 @@ impl Group { pub fn new_simple_group( founder_id: ObjectId, admins: Vec, - conclusion_limit: Option, area: Area, ) -> GroupBuilder { let desc_content = SimpleGroupDescContent { unique_id: UniqueId::create_with_random(), - conclusion_limit: conclusion_limit.map_or((admins.len() as u32 >> 1) + 1, |n| n), admins, founder_id, }; @@ -221,19 +220,13 @@ impl Group { self.common_mut().version = version; } - pub fn consensus_interval(&self) -> u64 { - let interval = self.common().consensus_interval; - if interval == 0 { - GROUP_DEFAULT_CONSENSUS_INTERVAL - } else { - interval - } + pub fn prev_blob_id(&self) -> &Option { + &self.common().prev_blob_id } - pub fn set_consensus_interval(&mut self, interval: u64) { - self.common_mut().consensus_interval = interval; + pub fn set_prev_blob_id(&mut self, prev_blob_id: Option) { + self.common_mut().prev_blob_id = prev_blob_id; } - // pub fn join_member( // &self, // member_id: &ObjectId, @@ -387,8 +380,6 @@ impl Group { pub struct GroupMember { pub id: ObjectId, pub title: String, - pub role: String, - pub shares: u64, } impl GroupMember { @@ -396,8 +387,6 @@ impl GroupMember { GroupMember { id, title: "".to_string(), - role: "".to_string(), - shares: 0, } } } @@ -409,8 +398,6 @@ impl TryFrom for GroupMember { let ret = Self { id: ProtobufCodecHelper::decode_buf(value.id)?, title: value.title, - role: value.role, - shares: value.shares, }; Ok(ret) @@ -425,159 +412,6 @@ impl TryFrom<&GroupMember> for protos::GroupMember { ret.id = value.id.to_vec()?; ret.title = value.title.clone(); - ret.role = value.role.clone(); - ret.shares = value.shares; - - Ok(ret) - } -} - -#[derive(Clone, Debug)] -pub struct GroupMethodACL { - pub name: String, - pub target_dec_id: Option, - pub rpath: Option, - pub min_support_percent: f64, - pub permissions: String, // ACL-String -} - -impl TryFrom for GroupMethodACL { - type Error = BuckyError; - - fn try_from(mut value: protos::GroupMethodACL) -> BuckyResult { - let ret = Self { - name: value.take_name(), - target_dec_id: if value.has_target_dec_id() { - Some(ProtobufCodecHelper::decode_buf(value.take_target_dec_id())?) - } else { - None - }, - rpath: if value.has_rpath() { - Some(value.take_rpath()) - } else { - None - }, - min_support_percent: value.min_support_percent, - permissions: value.take_permissions(), // ACL-String - }; - - Ok(ret) - } -} - -impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { - type Error = BuckyError; - - fn try_from(value: &GroupMethodACL) -> BuckyResult { - let mut ret = Self::new(); - - ret.name = value.name.clone(); - if let Some(dec_id) = &value.target_dec_id { - ret.set_target_dec_id(dec_id.to_vec()?); - } - if let Some(rpath) = &value.rpath { - ret.set_rpath(rpath.clone()); - } - ret.min_support_percent = value.min_support_percent; - ret.permissions = value.permissions.clone(); - - Ok(ret) - } -} - -#[derive(Clone, Debug)] -pub struct GroupRoleACL { - pub name: String, - pub target_dec_id: Option, - pub rpath: Option, - pub method: String, - - pub right_percent: f64, - pub is_operator: bool, - pub permissions: String, // ACL-String -} - -impl TryFrom for GroupRoleACL { - type Error = BuckyError; - - fn try_from(mut value: protos::GroupRoleACL) -> BuckyResult { - let ret = Self { - name: value.take_name(), - target_dec_id: if value.has_target_dec_id() { - Some(ProtobufCodecHelper::decode_buf(value.take_target_dec_id())?) - } else { - None - }, - rpath: if value.has_rpath() { - Some(value.take_rpath()) - } else { - None - }, - method: value.take_method(), - right_percent: value.right_percent, - is_operator: value.is_operator, - permissions: value.take_permissions(), // ACL-String - }; - - Ok(ret) - } -} - -impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { - type Error = BuckyError; - - fn try_from(value: &GroupRoleACL) -> BuckyResult { - let mut ret = Self::new(); - - ret.set_name(value.name.clone()); - if let Some(dec_id) = &value.target_dec_id { - ret.set_target_dec_id(dec_id.to_vec()?); - } - if let Some(rpath) = &value.rpath { - ret.set_rpath(rpath.clone()); - } - ret.method = value.method.clone(); - ret.right_percent = value.right_percent; - ret.is_operator = value.is_operator; - ret.permissions = value.permissions.clone(); - - Ok(ret) - } -} - -#[derive(Clone, Debug)] -pub struct GroupJoinSignature { - signature: Signature, - member_id: ObjectId, - is_admin: bool, - hash: HashValue, -} - -impl TryFrom for GroupJoinSignature { - type Error = BuckyError; - - fn try_from(value: protos::GroupJoinSignature) -> BuckyResult { - let ret = Self { - signature: ProtobufCodecHelper::decode_buf(value.signature)?, - member_id: ProtobufCodecHelper::decode_buf(value.member_id)?, - is_admin: value.is_admin, - hash: ProtobufCodecHelper::decode_buf(value.hash)?, - }; - - Ok(ret) - } -} - -impl TryFrom<&GroupJoinSignature> for protos::GroupJoinSignature { - type Error = BuckyError; - - fn try_from(value: &GroupJoinSignature) -> BuckyResult { - let mut ret = Self::new(); - - ret.signature = value.signature.to_vec()?; - ret.member_id = value.member_id.to_vec()?; - ret.is_admin = value.is_admin; - ret.hash = value.hash.to_vec()?; Ok(ret) } @@ -590,22 +424,11 @@ struct CommonGroupBodyContent { description: String, members: Vec, - total_equity: u64, - - // map优化以快速匹配 - method_acls: Vec, - - role_acls: Vec, ood_list: Vec, - history_block_max: u64, - history_block_lifespan: u64, - - revoked_conclusions: HashSet, version: u64, - consensus_interval: u64, - join_signatures: Vec, + prev_blob_id: Option, } impl CommonGroupBodyContent { @@ -621,16 +444,9 @@ impl CommonGroupBodyContent { icon, description, members, - total_equity: 0, - method_acls: vec![], - role_acls: vec![], ood_list, - history_block_max: 0, - history_block_lifespan: 0, - revoked_conclusions: HashSet::default(), version: 0, - consensus_interval: 0, - join_signatures: vec![], + prev_blob_id: None, } } } @@ -648,24 +464,13 @@ impl TryFrom for CommonGroupBodyContent { }, description: value.take_description(), members: ProtobufCodecHelper::decode_value_list(value.take_members())?, - total_equity: value.total_equity, - method_acls: ProtobufCodecHelper::decode_value_list(value.take_method_acls())?, - role_acls: ProtobufCodecHelper::decode_value_list(value.take_role_acls())?, ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, - history_block_max: value.get_history_block_max(), - history_block_lifespan: value.get_history_block_lifespan(), - revoked_conclusions: HashSet::from_iter(ProtobufCodecHelper::decode_buf_list( - value.take_revoked_conclusions(), - )?), version: value.version, - consensus_interval: if value.has_consensus_interval() { - value.get_consensus_interval() + prev_blob_id: if value.has_prev_blob_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_prev_blob_id())?) } else { - 0 + None }, - join_signatures: ProtobufCodecHelper::decode_value_list( - value.take_join_signatures().into_vec(), - )?, }; Ok(ret) @@ -685,33 +490,14 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { ret.description = value.description.clone(); ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); - ret.total_equity = value.total_equity; - ret.set_method_acls(ProtobufCodecHelper::encode_nested_list(&value.method_acls)?); - ret.set_role_acls(ProtobufCodecHelper::encode_nested_list(&value.role_acls)?); ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( value.ood_list.as_slice(), )?); - if value.history_block_max > 0 { - ret.set_history_block_max(value.history_block_max); - } - if value.history_block_lifespan > 0 { - ret.set_history_block_lifespan(value.history_block_lifespan); - } - ret.set_revoked_conclusions(ProtobufCodecHelper::encode_buf_list( - value - .revoked_conclusions - .iter() - .map(|id| id.clone()) - .collect::>() - .as_slice(), - )?); + ret.version = value.version; - if value.consensus_interval > 0 { - ret.set_consensus_interval(value.consensus_interval); + if let Some(prev_blob_id) = &value.prev_blob_id { + ret.set_prev_blob_id(prev_blob_id.to_vec()?); } - ret.set_join_signatures(ProtobufCodecHelper::encode_nested_list( - &value.join_signatures, - )?); Ok(ret) } @@ -722,7 +508,6 @@ pub struct SimpleGroupDescContent { unique_id: UniqueId, founder_id: ObjectId, admins: Vec, - conclusion_limit: u32, } impl TryFrom for SimpleGroupDescContent { @@ -732,7 +517,6 @@ impl TryFrom for SimpleGroupDescContent { let ret = Self { unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, admins: ProtobufCodecHelper::decode_value_list(value.admins)?, - conclusion_limit: value.conclusion_limit, founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, }; @@ -749,7 +533,6 @@ impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { ret.unique_id = value.unique_id.to_vec()?; ret.founder_id = value.founder_id.to_vec()?; ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); - ret.conclusion_limit = value.conclusion_limit; Ok(ret) } @@ -833,7 +616,6 @@ impl TryFrom<&OrgDescContent> for protos::OrgDescContent { #[derive(Clone, Debug, Default)] pub struct OrgBodyContent { admins: Vec, - token_contract: Option, common: CommonGroupBodyContent, } @@ -849,7 +631,6 @@ impl OrgBodyContent { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), admins, - token_contract: None, } } @@ -868,13 +649,6 @@ impl TryFrom for OrgBodyContent { fn try_from(mut value: protos::OrgBodyContent) -> BuckyResult { let ret = Self { admins: ProtobufCodecHelper::decode_value_list(value.take_admins())?, - token_contract: if value.has_token_contract() { - Some(ProtobufCodecHelper::decode_buf( - value.take_token_contract(), - )?) - } else { - None - }, common: ProtobufCodecHelper::decode_value(value.take_common())?, }; @@ -891,10 +665,6 @@ impl TryFrom<&OrgBodyContent> for protos::OrgBodyContent { ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); ret.set_common(ProtobufCodecHelper::encode_nested_item(&value.common)?); - if let Some(token_contract) = value.token_contract { - ret.set_token_contract(token_contract.to_vec()?); - } - Ok(ret) } } diff --git a/src/component/cyfs-chunk-lib/src/chunk.rs b/src/component/cyfs-chunk-lib/src/chunk.rs index cc7114070..054cb052b 100644 --- a/src/component/cyfs-chunk-lib/src/chunk.rs +++ b/src/component/cyfs-chunk-lib/src/chunk.rs @@ -309,35 +309,3 @@ impl async_std::io::Write for ChunkWrite { Poll::Ready(Ok(())) } } - -impl From<&Group> for ChunkMeta { - fn from(group: &Group) -> Self { - let len = group.raw_measure(&None).unwrap(); - let mut buf = vec![0u8; len]; - let remain = group.raw_encode(buf.as_mut_slice(), &None).unwrap(); - assert_eq!(remain.len(), 0); - ChunkMeta::MemChunk(buf) - } -} - -impl TryFrom<&ChunkMeta> for Group { - type Error = BuckyError; - - fn try_from(value: &ChunkMeta) -> Result { - match value { - ChunkMeta::MemChunk(buf) => { - let (group, remain) = Group::raw_decode(buf.as_slice())?; - assert_eq!(remain.len(), 0); - Ok(group) - } - ChunkMeta::MMapChunk(_, _) => Err(BuckyError::new( - BuckyErrorCode::InvalidFormat, - format!("expected ChunkMeta::MemChunk, got ChunkMeta::MMapChunk"), - )), - ChunkMeta::SharedMemChunk(_, _, _) => Err(BuckyError::new( - BuckyErrorCode::InvalidFormat, - format!("expected ChunkMeta::MemChunk, got ChunkMeta::SharedMemChunk"), - )), - } - } -} diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 8048b3951..d49009e4c 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -417,7 +417,7 @@ message GroupConsensusBlockDescContent { bytes meta_block_id = 5; uint64 round = 7; - bytes group_chunk_id = 8; + bytes group_blob_id = 8; } message GroupConsensusBlockBodyContent { diff --git a/src/component/cyfs-core/src/group/group_blob.rs b/src/component/cyfs-core/src/group/group_blob.rs new file mode 100644 index 000000000..90829215d --- /dev/null +++ b/src/component/cyfs-core/src/group/group_blob.rs @@ -0,0 +1,44 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, RawDecode, RawEncode, +}; + +use crate::{Storage, StorageObj}; + +pub trait GroupBlob: Sized { + fn to_blob(&self) -> Storage; + + fn from_blob(blob: &Storage) -> BuckyResult; + + fn blob_storage_id(&self) -> String; +} + +impl GroupBlob for Group { + fn to_blob(&self) -> Storage { + let len = self.raw_measure(&None).unwrap(); + let mut buf = vec![0u8; len]; + let remain = self.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + Storage::create_with_hash(self.blob_storage_id().as_str(), buf) + } + + fn from_blob(blob: &Storage) -> BuckyResult { + let group_buf = blob.value(); + let (group, remain) = Group::raw_decode(group_buf.as_slice())?; + assert_eq!(remain.len(), 0); + + let expected_id = group.blob_storage_id(); + + if blob.id() != expected_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("unknown storage, expect {}, got {}", expected_id, blob.id()), + )); + } + + Ok(group) + } + + fn blob_storage_id(&self) -> String { + format!("group@{}@{}", self.desc().object_id(), self.version()) + } +} diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 7d447ad15..4b4bf4f9a 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -16,7 +16,7 @@ pub struct GroupConsensusBlockDescContent { height: u64, meta_block_id: ObjectId, round: u64, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, } impl DescContent for GroupConsensusBlockDescContent { @@ -55,8 +55,8 @@ impl GroupConsensusBlockDescContent { self.round } - pub fn group_chunk_id(&self) -> &ObjectId { - &self.group_chunk_id + pub fn group_blob_id(&self) -> &ObjectId { + &self.group_blob_id } } @@ -242,7 +242,7 @@ pub trait GroupConsensusBlockObject { height: u64, meta_block_id: ObjectId, round: u64, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, qc: Option, tc: Option, owner: ObjectId, @@ -259,7 +259,7 @@ pub trait GroupConsensusBlockObject { fn named_object(&self) -> &NamedObjectBase; fn named_object_mut(&mut self) -> &mut NamedObjectBase; fn round(&self) -> u64; - fn group_chunk_id(&self) -> &ObjectId; + fn group_blob_id(&self) -> &ObjectId; fn qc(&self) -> &Option; fn tc(&self) -> &Option; } @@ -272,7 +272,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { height: u64, meta_block_id: ObjectId, round: u64, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, qc: Option, tc: Option, owner: ObjectId, @@ -287,7 +287,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { meta_block_id, body_hash: body.hash(), round, - group_chunk_id, + group_blob_id, }; let block = GroupConsensusBlockBuilder::new(desc, body) @@ -371,9 +371,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { desc.round } - fn group_chunk_id(&self) -> &ObjectId { + fn group_blob_id(&self) -> &ObjectId { let desc = self.0.desc().content(); - &desc.group_chunk_id + &desc.group_blob_id } fn qc(&self) -> &Option { diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index d7134a3c0..0fa271b8c 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,10 +4,12 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; +mod group_blob; pub use group_consensus_block::*; pub use group_proposal::*; // pub use group_proposal_decide_param::*; +pub use group_blob::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs index f06d876b9..4f79316b6 100644 --- a/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs +++ b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs @@ -2,7 +2,6 @@ use std::mem; use async_std::task; use cyfs_base::*; -use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupProposal, GroupProposalBuilder, GroupProposalDescContent, GroupProposalObject, GroupPropsalDecideParam, GroupRPath, GroupUpdateGroupPropsalParam, @@ -13,13 +12,13 @@ use crate::{GROUP_METHOD_UPDATE, STATEPATH_GROUP_DEC_ID, STATEPATH_GROUP_DEC_RPA pub struct GroupUpdateProposal { proposal: GroupProposal, target_dec_id: Vec, - from_chunk_id: Option, + from_blob_id: Option, to_group: Group, } impl GroupUpdateProposal { pub fn create( - from_group_chunk_id: Option, + from_group_blob_id: Option, to_group: Group, owner: ObjectId, target_dec_id: Vec, @@ -28,7 +27,7 @@ impl GroupUpdateProposal { effective_ending: Option, ) -> GroupUpdateProposalBuilder { GroupUpdateProposalBuilder::create( - from_group_chunk_id, + from_group_blob_id, to_group, owner, target_dec_id, @@ -65,8 +64,8 @@ impl GroupUpdateProposal { self.target_dec_id.as_slice() } - pub fn from_chunk_id(&self) -> &Option { - &self.from_chunk_id + pub fn from_blob_id(&self) -> &Option { + &self.from_blob_id } pub fn to_group(&self) -> &Group { @@ -125,24 +124,24 @@ impl TryFrom for GroupUpdateProposal { } let payload = value.payload().as_ref().unwrap(); - let (group_chunk, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); + let (group_blob, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); assert_eq!(remain.len(), 0); - let to_group = Group::try_from(&group_chunk)?; + let to_group = Group::try_from(&group_blob)?; - let to_chunk_id = - task::block_on(async { group_chunk.to_chunk().await.unwrap().calculate_id() }); - if &to_chunk_id.object_id() != param.to_chunk_id() { + let to_blob_id = + task::block_on(async { group_blob.to_chunk().await.unwrap().calculate_id() }); + if &to_blob_id.object_id() != param.to_blob_id() { return Err(BuckyError::new( BuckyErrorCode::InvalidFormat, - "the chunk in GroupUpdateProposal.body is not match with the to_chunk_id in desc.param", + "the chunk in GroupUpdateProposal.body is not match with the to_blob_id in desc.param", )); } let ret = Self { proposal: value, target_dec_id: Vec::from(param.target_dec_id()), - from_chunk_id: param.from_chunk_id().clone(), + from_blob_id: param.from_blob_id().clone(), to_group, }; @@ -153,13 +152,13 @@ impl TryFrom for GroupUpdateProposal { pub struct GroupUpdateProposalBuilder { proposal: GroupProposalBuilder, target_dec_id: Vec, - from_chunk_id: Option, + from_blob_id: Option, to_group: Option, } impl GroupUpdateProposalBuilder { pub fn create( - from_group_chunk_id: Option, + from_group_blob_id: Option, to_group: Group, owner: ObjectId, target_dec_id: Vec, @@ -167,20 +166,20 @@ impl GroupUpdateProposalBuilder { effective_begining: Option, effective_ending: Option, ) -> Self { - let group_chunk = ChunkMeta::from(&to_group); - let group_chunk_vec = { - let len = group_chunk.raw_measure(&None).unwrap(); + let group_blob = ChunkMeta::from(&to_group); + let group_blob_vec = { + let len = group_blob.raw_measure(&None).unwrap(); let mut buf = vec![0u8; len]; - let remain = group_chunk.raw_encode(buf.as_mut_slice(), &None).unwrap(); + let remain = group_blob.raw_encode(buf.as_mut_slice(), &None).unwrap(); assert_eq!(remain.len(), 0); buf }; - let to_chunk_id = - task::block_on(async { group_chunk.to_chunk().await.unwrap().calculate_id() }); + let to_blob_id = + task::block_on(async { group_blob.to_chunk().await.unwrap().calculate_id() }); let param = - GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_chunk_id.object_id()); + GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_blob_id.object_id()); let param_vec = { let len = param.raw_measure(&None).unwrap(); let mut buf = vec![0u8; len]; @@ -196,7 +195,7 @@ impl GroupUpdateProposalBuilder { update_rpath, GROUP_METHOD_UPDATE.to_string(), Some(param_vec), - Some(group_chunk_vec), + Some(group_blob_vec), None, owner, meta_block_id, @@ -207,7 +206,7 @@ impl GroupUpdateProposalBuilder { Self { proposal, target_dec_id, - from_chunk_id: from_group_chunk_id, + from_blob_id: from_group_blob_id, to_group: Some(to_group), } } @@ -237,15 +236,15 @@ impl GroupUpdateProposalBuilder { pub fn build(mut self) -> GroupUpdateProposal { let mut target_dec_id: Vec = vec![]; - let mut from_chunk_id: Option = None; + let mut from_blob_id: Option = None; let to_group = self.to_group.take().unwrap(); mem::swap(&mut target_dec_id, &mut self.target_dec_id); - mem::swap(&mut from_chunk_id, &mut self.from_chunk_id); + mem::swap(&mut from_blob_id, &mut self.from_blob_id); GroupUpdateProposal { proposal: self.proposal.build(), target_dec_id, - from_chunk_id, + from_blob_id, to_group, } } diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 1caf5b9a4..7a28cf89b 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,5 +32,4 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 2d416c357..c19a807fa 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,6 +1,5 @@ use std::{ collections::HashMap, - fmt::format, sync::Arc, time::{Duration, SystemTime}, }; @@ -11,10 +10,9 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectLink, ObjectTypeCode, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, RsaCPUObjectSigner, SignatureSource, Signer, }; -use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupBlob, GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, + GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::{ExecuteResult, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; @@ -27,7 +25,8 @@ use crate::{ helper::Timer, Committee, GroupObjectMapProcessor, GroupStorage, HotstuffMessage, PendingProposalConsumer, RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + GROUP_DEFAULT_CONSENSUS_INTERVAL, HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, + TIME_PRECISION, }; /** @@ -297,7 +296,7 @@ impl HotstuffRunner { let tc = last_tc.clone(); let vote_mgr = VoteMgr::new(committee.clone(), round); - let init_timer_interval = store.group().consensus_interval(); + let init_timer_interval = GROUP_DEFAULT_CONSENSUS_INTERVAL; let max_quorum_round = round - 1; let header_height = store.header_height(); let max_height = header_height + 2; @@ -385,7 +384,7 @@ impl HotstuffRunner { { // check leader let leader_owner = self - .get_leader_owner(Some(block.group_chunk_id()), block.round()) + .get_leader_owner(Some(block.group_blob_id()), block.round()) .await?; if &leader_owner != block.owner() { @@ -582,17 +581,17 @@ impl HotstuffRunner { async fn get_leader_owner( &self, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { let leader = self .committee - .get_leader(group_chunk_id, round) + .get_leader(group_blob_id, round) .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", self, - group_chunk_id, round, + group_blob_id, round, err ); @@ -983,7 +982,7 @@ impl HotstuffRunner { round + 1 ); - self.timer.reset(group.consensus_interval()); + self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); self.round = round + 1; self.vote_mgr.cleanup(self.round); self.tc = None; @@ -1144,7 +1143,7 @@ impl HotstuffRunner { ); if !only_rebuild_result_state { - match self.check_group_is_latest(block.group_chunk_id()).await { + match self.check_group_is_latest(block.group_blob_id()).await { Ok(is_latest) if is_latest => {} _ => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", @@ -1746,7 +1745,7 @@ impl HotstuffRunner { let latest_group = match self.committee.get_group(None).await { Ok(group) => { - self.timer.reset(group.consensus_interval()); + self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); group } Err(err) => { @@ -2062,11 +2061,7 @@ impl HotstuffRunner { }) .collect(); - let group_chunk_id = ChunkMeta::from(group) - .to_chunk() - .await - .unwrap() - .calculate_id(); + let group_blob_id = group.to_blob().desc().object_id(); let mut block = GroupConsensusBlock::create( self.rpath.clone(), @@ -2075,7 +2070,7 @@ impl HotstuffRunner { prev_block.as_ref().map_or(0, |b| b.height()) + 1, ObjectId::default(), // TODO: meta block id self.round, - group_chunk_id.object_id(), + group_blob_id, self.high_qc.clone(), tc, self.local_id, @@ -2256,11 +2251,11 @@ impl HotstuffRunner { Ok(()) } - async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { + async fn check_group_is_latest(&self, group_blob_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; - let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; - let latest_chunk_id = group_chunk.calculate_id(); - Ok(latest_chunk_id.as_object_id() == group_chunk_id) + let group_blob = latest_group.to_blob(); + let latest_chunk_id = group_blob.desc().object_id(); + Ok(&latest_chunk_id == group_blob_id) } async fn make_sure_result_state( @@ -2379,16 +2374,16 @@ impl HotstuffRunner { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. let max_round_block = self.store.block_with_max_round(); - let group_chunk_id = max_round_block.as_ref().map(|block| block.group_chunk_id()); - let last_group = self.committee.get_group(group_chunk_id).await; - let latest_group = match group_chunk_id.as_ref() { + let group_blob_id = max_round_block.as_ref().map(|block| block.group_blob_id()); + let last_group = self.committee.get_group(group_blob_id).await; + let latest_group = match group_blob_id.as_ref() { Some(_) => self.committee.get_group(None).await, None => last_group.clone(), }; - let duration = latest_group - .as_ref() - .map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| g.consensus_interval()); + let duration = latest_group.as_ref().map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| { + GROUP_DEFAULT_CONSENSUS_INTERVAL + }); self.timer.reset(duration); if let Ok(leader) = self.committee.get_leader(None, self.round).await { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 59cb43b96..1052d4268 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -6,7 +6,7 @@ use std::{ }; use async_std::channel::{Receiver, Sender}; -use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId}; +use cyfs_base::{BuckyResult, NamedObject, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 398274723..6b32187a3 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -9,13 +9,11 @@ use cyfs_base::{ ObjectDesc, ObjectId, OwnerObjectDesc, RsaCPUObjectVerifier, SignatureSource, SingleKeyObjectDesc, Verifier, }; -use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupBlob, GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use cyfs_lib::NONObjectInfo; use crate::network::NONDriverHelper; @@ -24,7 +22,7 @@ pub(crate) struct Committee { group_id: ObjectId, non_driver: NONDriverHelper, local_device_id: ObjectId, - group_cache: Arc>>, // (group_chunk_id, group) + group_cache: Arc>>, // (group_blob_id, group) } impl Committee { @@ -37,16 +35,16 @@ impl Committee { } } - pub async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - self.check_group(group_chunk_id, None).await + pub async fn get_group(&self, group_blob_id: Option<&ObjectId>) -> BuckyResult { + self.check_group(group_blob_id, None).await } pub async fn quorum_threshold( &self, voters: &HashSet, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, ) -> BuckyResult { - let group = self.check_group(group_chunk_id, None).await?; + let group = self.check_group(group_blob_id, None).await?; let voters: Vec<&ObjectId> = voters .iter() .filter(|id| { @@ -64,10 +62,10 @@ impl Committee { pub async fn get_leader( &self, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { - let group = self.check_group(group_chunk_id, None).await?; + let group = self.check_group(group_blob_id, None).await?; let i = (round % (group.ood_list().len() as u64)) as usize; Ok(group.ood_list()[i].object_id().clone()) } @@ -94,7 +92,7 @@ impl Committee { ); let group = self - .check_group(Some(block.group_chunk_id()), Some(&from)) + .check_group(Some(block.group_blob_id()), Some(&from)) .await?; if !self.check_block_sign(&block, &group).await? { @@ -162,7 +160,7 @@ impl Committee { )); } - self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + self.check_group(Some(block_desc.content().group_blob_id()), Some(&from)) .await?; log::debug!( @@ -252,7 +250,7 @@ impl Committee { let is_enough = self .quorum_threshold( &tc.votes.iter().map(|v| v.voter).collect(), - prev_block.map(|b| b.group_chunk_id()), + prev_block.map(|b| b.group_blob_id()), ) .await?; @@ -316,7 +314,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block_desc.group_chunk_id()), + Some(prev_block_desc.group_blob_id()), ) .await?; @@ -366,8 +364,8 @@ impl Committee { .get_group(&self.group_id, chunk_id, from) .await?; - let group_chunk = ChunkMeta::from(&group).to_chunk().await?; - let calc_id = group_chunk.calculate_id().object_id(); + let group_blob = group.to_blob(); + let calc_id = group_blob.desc().object_id(); if let Some(id) = chunk_id { assert_eq!(&calc_id, id); } diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 6a9735a7f..d2128a20f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -244,7 +244,7 @@ impl QCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.0).collect(), - Some(block.group_chunk_id()), + Some(block.group_blob_id()), ) .await?; if self.thresholded { @@ -315,7 +315,7 @@ impl TCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.voter).collect(), - block.map(|block| block.group_chunk_id()), + block.map(|block| block.group_blob_id()), ) .await?; diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 77a652a7e..61f8a1106 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -22,3 +22,4 @@ pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; pub const MEMORY_CACHE_DURATION: Duration = Duration::from_secs(300); +pub const GROUP_DEFAULT_CONSENSUS_INTERVAL: u64 = 5000; // default 5000 ms diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index ff175960d..a43f99b99 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -5,7 +5,6 @@ use cyfs_base::{ RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_group_lib::RPathDelegate; use cyfs_lib::NONObjectInfo; use crate::{ diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 8fd67496b..b9d33efc4 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_core::{GroupRPath}; use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index e019db892..382a67120 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -104,7 +104,7 @@ impl DecStateSynchronizer { struct DecStateSynchronizerCache { state_cache: DecStorageCache, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, group: Group, } @@ -112,7 +112,7 @@ struct UpdateNotifyInfo { header_block: GroupConsensusBlock, qc: HotstuffBlockQC, remotes: HashSet, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, group: Group, } @@ -247,7 +247,7 @@ impl DecStateSynchronizerRunner { header_block: notify_info.header_block.clone(), qc: notify_info.qc.clone(), }, - group_chunk_id: notify_info.group_chunk_id, + group_blob_id: notify_info.group_blob_id, group: notify_info.group.clone(), }); self.update_notifies = None; @@ -276,15 +276,15 @@ impl DecStateSynchronizerRunner { if self.state_cache.is_none() { let state_cache = self.store.cur_state().await; if let Some(state_cache) = state_cache { - let group_chunk_id = state_cache.header_block.group_chunk_id().clone(); + let group_blob_id = state_cache.header_block.group_blob_id().clone(); let group = self .non_driver - .get_group(self.rpath.group_id(), Some(&group_chunk_id), None) + .get_group(self.rpath.group_id(), Some(&group_blob_id), None) .await; if let Ok(group) = group { self.state_cache = Some(DecStateSynchronizerCache { state_cache, - group_chunk_id, + group_blob_id, group, }); } @@ -320,15 +320,15 @@ impl DecStateSynchronizerRunner { { let group = self .committee - .check_group(Some(header_block.group_chunk_id()), None) + .check_group(Some(header_block.group_blob_id()), None) .await?; - let group_chunk_id = header_block.group_chunk_id().clone(); + let group_blob_id = header_block.group_blob_id().clone(); self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc: qc, remotes: HashSet::from([remote]), - group_chunk_id, + group_blob_id, group, }); }; diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 99c3fed62..acf061ae7 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -88,7 +88,7 @@ impl StatePusher { struct HeaderBlockNotifyProgress { header_block: GroupConsensusBlock, qc_block: GroupConsensusBlock, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, members: Vec, total_notify_times: usize, cur_block_notify_times: usize, @@ -218,14 +218,10 @@ impl StateChanggeRunner { return; } - if block.group_chunk_id() != progress.header_block.group_chunk_id() { + if block.group_blob_id() != progress.header_block.group_blob_id() { let group = self .non_driver - .get_group( - block.rpath().group_id(), - Some(block.group_chunk_id()), - None, - ) + .get_group(block.rpath().group_id(), Some(block.group_blob_id()), None) .await; if group.is_err() { return; @@ -238,7 +234,7 @@ impl StateChanggeRunner { .collect(); } - progress.group_chunk_id = block.group_chunk_id().clone(); + progress.group_blob_id = block.group_blob_id().clone(); progress.total_notify_times += progress.cur_block_notify_times; progress.cur_block_notify_times = 0; progress.header_block = block; @@ -247,11 +243,7 @@ impl StateChanggeRunner { None => { let group = self .non_driver - .get_group( - block.rpath().group_id(), - Some(block.group_chunk_id()), - None, - ) + .get_group(block.rpath().group_id(), Some(block.group_blob_id()), None) .await; if group.is_err() { return; @@ -268,12 +260,12 @@ impl StateChanggeRunner { None => return, }; - let group_chunk_id = block.group_chunk_id().clone(); + let group_blob_id = block.group_blob_id().clone(); self.notify_progress = Some(HeaderBlockNotifyProgress { header_block: block, qc_block, - group_chunk_id, + group_blob_id, members, total_notify_times, cur_block_notify_times: 0, diff --git a/src/component/cyfs-group/src/helper/timer.rs b/src/component/cyfs-group/src/helper/timer.rs index 6d2ebb234..5edda71b4 100644 --- a/src/component/cyfs-group/src/helper/timer.rs +++ b/src/component/cyfs-group/src/helper/timer.rs @@ -1,6 +1,4 @@ -use std::future::Future; use std::ops::Sub; -use std::pin::Pin; use std::time::{Duration, Instant}; pub struct Timer { diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index e66ef8a43..02017184d 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -1,4 +1,4 @@ -use std::time::{Duration, Instant}; +use std::time::{Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index b8a2ac29b..3e400ce44 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -163,16 +163,16 @@ impl NONDriverHelper { pub async fn get_group( &self, group_id: &ObjectId, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { - // TODO: ignore group_chunk_id first - // match group_chunk_id { - // Some(group_chunk_id) => { - // let chunk = self.get_object(group_chunk_id, from).await?; - // let (group_chunk, remain) = ChunkMeta::raw_decode(chunk.object_raw.as_slice())?; + // TODO: ignore group_blob_id first + // match group_blob_id { + // Some(group_blob_id) => { + // let blob = self.get_object(group_blob_id, from).await?; + // let (group_blob, remain) = Storage::raw_decode(blob.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // let group = Group::try_from(&group_chunk)?; + // let group = Group::from_blob(&group_blob)?; // if &group.desc().object_id() == group_id { // Ok(group) // } else { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 78af14c4b..17756b992 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -4,10 +4,10 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, - HotstuffTimeout, + GroupBlob, GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, + HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; @@ -42,7 +42,7 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, cache: StorageCacheInfo, @@ -60,8 +60,8 @@ impl GroupStorage { root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; - let group_chunk = ChunkMeta::from(&group); - let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + let group_blob = group.to_blob(); + let group_blob_id = group_blob.desc().object_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) @@ -77,7 +77,7 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_chunk_id: group_chunk_id.object_id(), + group_blob_id, storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), @@ -108,8 +108,8 @@ impl GroupStorage { log::warn!("get group {} from noc failed {:?}", group_id, err); err })?; - let group_chunk = ChunkMeta::from(&group); - let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + let group_blob = group.to_blob(); + let group_blob_id = group_blob.desc().object_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) @@ -139,7 +139,7 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_chunk_id: group_chunk_id.object_id(), + group_blob_id, storage_engine: StorageEngineGroupState::new( dec_group_state, state_path, @@ -180,8 +180,8 @@ impl GroupStorage { &self.group } - pub fn group_chunk_id(&self) -> &ObjectId { - &self.group_chunk_id + pub fn group_blob_id(&self) -> &ObjectId { + &self.group_blob_id } pub fn dec_state_id(&self) -> &Option { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 880732884..8186031b8 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -193,8 +193,6 @@ mod Common { .collect(), ); - group.set_consensus_interval(5000); - log::info!("create group: {:?}", group.desc().object_id()); let desc_hash = group.desc().raw_hash_value().unwrap(); From 217774877c8a066898567d92d65667f2a69f5785 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 8 Apr 2023 20:17:34 +0800 Subject: [PATCH 429/553] MetaChain: update group --- src/component/cyfs-base-meta/Cargo.toml | 1 + src/component/cyfs-base-meta/src/group.rs | 234 ++++++++++++++++++ src/component/cyfs-base-meta/src/lib.rs | 26 +- .../src/executor/tx_proc/desc_proc.rs | 79 +++++- 4 files changed, 318 insertions(+), 22 deletions(-) create mode 100644 src/component/cyfs-base-meta/src/group.rs diff --git a/src/component/cyfs-base-meta/Cargo.toml b/src/component/cyfs-base-meta/Cargo.toml index 8e23382cf..896044164 100644 --- a/src/component/cyfs-base-meta/Cargo.toml +++ b/src/component/cyfs-base-meta/Cargo.toml @@ -20,5 +20,6 @@ serde_json = '1.0' hex = '0.4.2' async-trait = '0.1.53' async-std = '1.11' +futures = '0.3.25' primitive-types = { version = '0.9' } codec = { package = 'parity-scale-codec', version = '2.0', default-features = false, features = ['derive', 'full'], optional = true } diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs new file mode 100644 index 000000000..a97b79f5d --- /dev/null +++ b/src/component/cyfs-base-meta/src/group.rs @@ -0,0 +1,234 @@ +use std::collections::HashSet; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, + ObjectTypeCode, People, PeopleId, RawConvertTo, RsaCPUObjectVerifier, Signature, + SingleKeyObjectDesc, Verifier, +}; +use cyfs_core::GroupBlob; + +async fn verify_signature( + signs: Option<&Vec>, + data_buf: &[u8], + verifier: &RsaCPUObjectVerifier, + signer_id: &PeopleId, +) -> BuckyResult<()> { + let signs = signs.map_or([].as_slice(), |s| s.as_slice()); + let sign = signs.iter().find(|s| match s.sign_source() { + cyfs_base::SignatureSource::Object(signer) => &signer.obj_id == signer_id.object_id(), + _ => false, + }); + + match sign { + Some(sign) => { + if verifier.verify(data_buf, sign).await { + Ok(()) + } else { + let msg = format!("Invalid signature from {}", signer_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)) + } + } + None => { + let msg = format!("Not found signature from {}", signer_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::NotFound, msg)) + } + } +} + +async fn verify_group_signature( + group: &Group, + people_id: &PeopleId, + member_querier: &impl MemberQuerier, +) -> BuckyResult<()> { + let people = member_querier.get_people(people_id).await?; + let verifier = RsaCPUObjectVerifier::new(people.desc().public_key().clone()); + let desc_buf = group.desc().to_vec()?; + verify_signature( + group.signs().desc_signs(), + desc_buf.as_slice(), + &verifier, + people_id, + ) + .await?; + let body_buf = group.body().to_vec()?; + verify_signature( + group.signs().body_signs(), + body_buf.as_slice(), + &verifier, + people_id, + ) + .await +} + +#[async_trait::async_trait] +pub trait MemberQuerier: Send + Sync { + async fn get_people(&self, people_id: &PeopleId) -> BuckyResult; +} + +#[async_trait::async_trait] +pub trait GroupVerifier { + // Check the update is allowed + async fn is_update_valid( + &self, + latest_group: Option<&Group>, + member_querier: &impl MemberQuerier, + ) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +impl GroupVerifier for Group { + async fn is_update_valid( + &self, + latest_group: Option<&Group>, + member_querier: &impl MemberQuerier, + ) -> BuckyResult<()> { + let group_id = self.desc().object_id(); + let (last_admins, last_members) = match latest_group { + Some(latest_group) => { + let latest_group_id = latest_group.desc().object_id(); + if group_id != latest_group_id { + let msg = format!( + "The new group({}) is unmatch with the latest group({}).", + group_id, latest_group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let latest_group_blob = latest_group.to_blob(); + let latest_group_blob_id = latest_group_blob.desc().object_id(); + if self.version() != latest_group.version() + 1 + || self.prev_blob_id() != &Some(latest_group_blob_id) + { + let msg = format!("Attempt to update group({}) from unknown version({}/{:?}), latest version: {}/{}.", group_id, self.version() - 1, self.prev_blob_id(), latest_group.version(), latest_group_blob_id); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + (latest_group.admins(), latest_group.members()) + } + None => match self.prev_blob_id() { + Some(prev_blob_id) => { + let msg = format!( + "The latest group({}) is necessary for update. prev_blob_id: {}", + group_id, prev_blob_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + None => ([].as_slice(), [].as_slice()), + }, + }; + + // admins: > 1/2 + // new members: all + + let last_admins = HashSet::::from_iter( + last_admins + .iter() + .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) + .map(|m| m.id), + ); + let last_members = HashSet::::from_iter( + last_members + .iter() + .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) + .map(|m| m.id), + ); + let add_admins = HashSet::::from_iter( + self.admins() + .iter() + .filter(|m| { + m.id.obj_type_code() == ObjectTypeCode::People && !last_admins.contains(&m.id) + }) + .map(|m| m.id), + ); + let add_members = HashSet::::from_iter( + self.members() + .iter() + .filter(|m| { + m.id.obj_type_code() == ObjectTypeCode::People && !last_members.contains(&m.id) + }) + .map(|m| m.id), + ); + + if add_admins.len() != self.admins().len() - last_admins.len() { + let msg = format!( + "Update group({}) with duplicate admins or invalid admins.", + group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + + if add_members.len() != self.members().len() - add_members.len() { + let msg = format!( + "Update group({}) with duplicate members or invalid members.", + group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + + let additionals = add_admins + .union(&add_members) + .map(|id| *id) + .collect::>(); + if additionals.len() != add_admins.len() + add_members.len() { + let msg = format!( + "Update group({}) with admins is not necessary in members.", + group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + + let check_peoples = + futures::future::join_all(last_admins.iter().chain(additionals.iter()).map( + |people_id| async move { + let people_id = PeopleId::try_from(people_id).unwrap(); + verify_group_signature(self, &people_id, member_querier).await + }, + )) + .await; + + let (last_admin_signs, add_member_signs) = check_peoples.split_at(last_admins.len()); + let last_admin_sign_count = last_admin_signs.iter().filter(|s| s.is_ok()).count(); + if last_admin_sign_count <= last_admins.len() / 2 { + let msg = format!( + "Update group({}) failed for signatures from admins in latest version is not enough: expected {}, got {}.", + group_id, + last_admins.len() / 2 + 1, + last_admin_sign_count + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)); + } + + let failed_add_member_sign_pos = add_member_signs.iter().position(|s| s.is_err()); + match failed_add_member_sign_pos { + Some(pos) => { + let msg = format!( + "Update group({}) failed for signatures from additional member({:?}) is invalid.", + group_id, + additionals.get(pos) + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)); + } + None => { + log::info!( + "Update group({}) verify ok, from {:?}/{:?}, to {}/{}", + group_id, + latest_group.map(|group| group.version()), + self.prev_blob_id(), + self.version(), + self.to_blob().desc().object_id() + ); + Ok(()) + } + } + } +} diff --git a/src/component/cyfs-base-meta/src/lib.rs b/src/component/cyfs-base-meta/src/lib.rs index 09481a16d..2beadb599 100644 --- a/src/component/cyfs-base-meta/src/lib.rs +++ b/src/component/cyfs-base-meta/src/lib.rs @@ -1,28 +1,30 @@ extern crate alloc; pub use block::*; +pub use code::*; pub use config::*; +pub use contract::*; pub use event::*; pub use extension::*; +pub use group::*; +pub use nft::*; pub use sn_service::*; pub use spv::*; pub use tx::*; pub use types::*; pub use view::*; -pub use code::*; -pub use contract::*; -pub use nft::*; -mod types; -mod config; mod block; -mod view; -mod event; -mod tx; -mod sn_service; -mod spv; -mod extension; mod code; +mod config; mod contract; -mod nft; +mod event; pub mod evm_def; +mod extension; +mod group; +mod nft; +mod sn_service; +mod spv; +mod tx; +mod types; +mod view; diff --git a/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs b/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs index 6130659d7..713a45b13 100644 --- a/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs +++ b/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs @@ -55,35 +55,60 @@ impl TxExecutor { let desc = ret.unwrap(); if desc.hash()? != tx.desc_hash { - error!("data hash mismatch!, except {}, actual {}", &tx.desc_hash, desc.hash()?); + error!( + "data hash mismatch!, except {}, actual {}", + &tx.desc_hash, + desc.hash()? + ); error!("tx data hex: {}", hex::encode(data)); error!("rust data hex: {}", hex::encode(desc.to_vec().unwrap())); return Err(meta_err!(ERROR_HASH_ERROR)); } let objid = context::id_from_desc(&desc); + let state_ref = context.ref_state().to_rc()?; + + if let SavedMetaObject::Group(group) = &desc { + group + .is_update_valid(None, &PeopleQuerier(state_ref.clone())) + .await?; + } //TODO:是否需要检测已经objid 已经有余额存在? // 是否需要校验caller能否创建desc? - context - .ref_state() - .to_rc()? - .create_obj_desc(&objid, &desc) - .await?; + state_ref.create_obj_desc(&objid, &desc).await?; if let SavedMetaObject::File(file) = &desc { if file.desc().owner().is_some() { - context.ref_state().to_rc()?.set_beneficiary(&file.desc().calculate_id(), file.desc().owner().as_ref().unwrap()).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary( + &file.desc().calculate_id(), + file.desc().owner().as_ref().unwrap(), + ) + .await?; } } else if let SavedMetaObject::Data(data) = &desc { if let Ok(obj) = AnyNamedObject::clone_from_slice(data.data.as_slice()) { if obj.owner().is_some() { - context.ref_state().to_rc()?.set_beneficiary(&obj.calculate_id(), obj.owner().as_ref().unwrap()).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary(&obj.calculate_id(), obj.owner().as_ref().unwrap()) + .await?; } } } else if let SavedMetaObject::Device(device) = &desc { if device.desc().owner().is_some() { - context.ref_state().to_rc()?.set_beneficiary(&device.desc().calculate_id(), device.desc().owner().as_ref().unwrap()).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary( + &device.desc().calculate_id(), + device.desc().owner().as_ref().unwrap(), + ) + .await?; } } @@ -160,11 +185,29 @@ impl TxExecutor { // return Err(ERROR_ACCESS_DENIED); //} - let mut rent_state = context.ref_state().to_rc()?.get_desc_extra(&objid).await?; + let state_ref = context.ref_state().to_rc()?; + + let mut rent_state = state_ref.get_desc_extra(&objid).await?; if rent_state.rent_arrears > 0 { return Err(crate::meta_err!(ERROR_RENT_ARREARS)); } + if let SavedMetaObject::Group(group) = &desc { + let latest_group = state_ref.get_obj_desc(&objid).await?; + if let SavedMetaObject::Group(latest_group) = latest_group { + group + .is_update_valid(Some(&latest_group), &PeopleQuerier(state_ref.clone())) + .await?; + } else { + let msg = format!( + "Attempt get group({}) from different type.", + group.desc().object_id() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + } + context .ref_state() .to_rc()? @@ -278,3 +321,19 @@ impl TxExecutor { Ok(()) } } + +struct PeopleQuerier(StateRef); + +#[async_trait::async_trait] +impl MemberQuerier for PeopleQuerier { + async fn get_people(&self, people_id: &PeopleId) -> BuckyResult { + let obj = self.0.get_obj_desc(people_id.object_id()).await?; + if let SavedMetaObject::People(people) = obj { + Ok(people) + } else { + let msg = format!("Attempt get people({}) from different type.", people_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) + } + } +} From 9dd0ff0676a0b48133b24b0e7dd8fe8d53b4f3ca Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 10 Apr 2023 14:46:27 +0800 Subject: [PATCH 430/553] Refuse group with empty admins --- src/component/cyfs-base-meta/src/group.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index a97b79f5d..614056d47 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -85,6 +85,13 @@ impl GroupVerifier for Group { member_querier: &impl MemberQuerier, ) -> BuckyResult<()> { let group_id = self.desc().object_id(); + + if self.admins().len() == 0 { + let msg = format!("Update group({}) with no admins.", group_id); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let (last_admins, last_members) = match latest_group { Some(latest_group) => { let latest_group_id = latest_group.desc().object_id(); From 79334cccd6e7c28e18e6ac4ed2431e2c942272d2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 10 Apr 2023 16:13:24 +0800 Subject: [PATCH 431/553] Support `None` founder_id --- src/component/cyfs-base/src/objects/group.rs | 85 +++++++------------- 1 file changed, 29 insertions(+), 56 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 29aee5849..5ddd02ae7 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -105,7 +105,7 @@ impl GroupDesc { impl Group { pub fn new_simple_group( - founder_id: ObjectId, + founder_id: Option, admins: Vec, area: Area, ) -> GroupBuilder { @@ -124,7 +124,7 @@ impl Group { .area(area) } - pub fn new_org(founder_id: ObjectId, area: Area) -> GroupBuilder { + pub fn new_org(founder_id: Option, area: Area) -> GroupBuilder { let desc_content = OrgDescContent { founder_id, unique_id: UniqueId::create_with_random(), @@ -139,6 +139,13 @@ impl Group { .area(area) } + pub fn founder_id(&self) -> &Option { + match self.desc().content() { + GroupDescContent::SimpleGroup(s) => &s.founder_id, + GroupDescContent::Org(o) => &o.founder_id, + } + } + pub fn name(&self) -> &str { self.common().name.as_str() } @@ -227,39 +234,6 @@ impl Group { pub fn set_prev_blob_id(&mut self, prev_blob_id: Option) { self.common_mut().prev_blob_id = prev_blob_id; } - // pub fn join_member( - // &self, - // member_id: &ObjectId, - // private_key: &PrivateKey, - // ) -> BuckyResult<&GroupJoinSignature> { - // unimplemented!() - // } - - // pub fn verify( - // &self, - // signature: &GroupJoinSignature, - // member_id: &ObjectId, - // public_key: &PublicKey, - // ) -> BuckyResult { - // unimplemented!() - // } - - // pub fn verify_member( - // &self, - // member_id: &ObjectId, - // is_admin: bool, - // public_key: &PublicKey, - // ) -> BuckyResult { - // unimplemented!() - // } - - // pub fn verify_members( - // &self, - // members: &[(ObjectId, PublicKey)], - // is_admin: bool, - // ) -> BuckyResult { - // unimplemented!() - // } pub fn is_simple_group(&self) -> bool { match self.desc().content() { @@ -354,19 +328,6 @@ impl Group { oods } - // pub fn group_hash(&self) -> ObjectId { - // let mut without_sign = self.clone(); - // without_sign.common_mut().join_signatures = vec![]; - - // let mut hash = HashValue::default(); - // let remain = without_sign - // .raw_encode(hash.as_mut_slice(), &Some(RawEncodePurpose::Hash)) - // .unwrap(); - // assert_eq!(remain.len(), 0); - - // ObjectId::from_slice_value(&hash.as_slice()[..31]) - // } - fn common(&self) -> &CommonGroupBodyContent { self.body().as_ref().unwrap().content().common() } @@ -506,18 +467,22 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { #[derive(Clone, Debug)] pub struct SimpleGroupDescContent { unique_id: UniqueId, - founder_id: ObjectId, + founder_id: Option, admins: Vec, } impl TryFrom for SimpleGroupDescContent { type Error = BuckyError; - fn try_from(value: protos::SimpleGroupDescContent) -> BuckyResult { + fn try_from(mut value: protos::SimpleGroupDescContent) -> BuckyResult { let ret = Self { + founder_id: if value.has_founder_id() { + ProtobufCodecHelper::decode_buf(value.take_founder_id())? + } else { + None + }, unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, admins: ProtobufCodecHelper::decode_value_list(value.admins)?, - founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, }; Ok(ret) @@ -531,7 +496,9 @@ impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { let mut ret = Self::new(); ret.unique_id = value.unique_id.to_vec()?; - ret.founder_id = value.founder_id.to_vec()?; + if let Some(founder_id) = value.founder_id.as_ref() { + ret.set_founder_id(founder_id.to_vec()?); + } ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); Ok(ret) @@ -584,16 +551,20 @@ impl TryFrom<&SimpleGroupBodyContent> for protos::SimpleGroupBodyContent { #[derive(Clone, Debug)] pub struct OrgDescContent { unique_id: UniqueId, - founder_id: ObjectId, + founder_id: Option, } impl TryFrom for OrgDescContent { type Error = BuckyError; - fn try_from(value: protos::OrgDescContent) -> BuckyResult { + fn try_from(mut value: protos::OrgDescContent) -> BuckyResult { let ret = Self { + founder_id: if value.has_founder_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_founder_id())?) + } else { + None + }, unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, - founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, }; Ok(ret) @@ -607,7 +578,9 @@ impl TryFrom<&OrgDescContent> for protos::OrgDescContent { let mut ret = Self::new(); ret.unique_id = value.unique_id.to_vec()?; - ret.founder_id = value.founder_id.to_vec()?; + if let Some(founder_id) = value.founder_id.as_ref() { + ret.set_founder_id(founder_id.to_vec()?); + } Ok(ret) } From 5110294a144cb1642c6e1601330ef74961a1b754 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 10 Apr 2023 20:46:10 +0800 Subject: [PATCH 432/553] `desc-tools` for `Group` --- src/component/cyfs-base-meta/src/group.rs | 14 +- .../cyfs-base/protos/standard_objects.proto | 10 +- src/component/cyfs-base/src/codec/format.rs | 33 +- src/component/cyfs-base/src/objects/group.rs | 125 ++++++-- src/tests/group-example/src/main.rs | 2 +- src/tools/desc-tool/src/create.rs | 301 ++++++++++++------ src/tools/desc-tool/src/desc.rs | 31 +- src/tools/desc-tool/src/modify.rs | 160 ++++++++-- src/tools/desc-tool/src/show.rs | 92 +++++- src/tools/desc-tool/src/util.rs | 35 +- 10 files changed, 604 insertions(+), 199 deletions(-) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index 614056d47..34ee769e9 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -125,7 +125,19 @@ impl GroupVerifier for Group { log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } - None => ([].as_slice(), [].as_slice()), + None => { + if let Some(founder) = self.founder_id() { + if self.admins().iter().find(|m| &m.id == founder).is_none() { + let msg = format!( + "Update group({}) the founder({}) must be an administrator.", + group_id, founder + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + } + ([].as_slice(), [].as_slice()) + } }, }; diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index a363ec57a..e025fd753 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -66,9 +66,9 @@ message GroupMember { } message CommonGroupBodyContent { - string name = 1; - optional bytes icon = 2; - string description = 3; + optional string name = 1; + optional string icon = 2; + optional string description = 3; repeated GroupMember members = 4; @@ -81,7 +81,7 @@ message CommonGroupBodyContent { // simple_group message SimpleGroupDescContent { bytes unique_id = 1; - bytes founder_id = 2; + optional bytes founder_id = 2; repeated GroupMember admins = 3; } @@ -92,7 +92,7 @@ message SimpleGroupBodyContent { // org message OrgDescContent { bytes unique_id = 1; - bytes founder_id = 2; + optional bytes founder_id = 2; } message OrgBodyContent { diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index 75863c9d1..162f5066a 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -564,10 +564,19 @@ impl ObjectFormat for PeopleBodyContent { } } -// simple group +// group impl ObjectFormat for GroupDescContent { fn format_json(&self) -> serde_json::Value { - let map = serde_json::Map::new(); + let mut map = serde_json::Map::new(); + + JsonCodecHelper::encode_option_string_field( + &mut map, + "founder", + self.founder_id().as_ref(), + ); + if let GroupDescContent::SimpleGroup(simple_group) = self { + JsonCodecHelper::encode_str_array_field(&mut map, "admins", simple_group.admins()); + } map.into() } @@ -577,13 +586,25 @@ impl ObjectFormat for GroupBodyContent { fn format_json(&self) -> serde_json::Value { let mut map = serde_json::Map::new(); - JsonCodecHelper::encode_string_field(&mut map, "name", self.name()); - JsonCodecHelper::encode_str_array_field( + JsonCodecHelper::encode_option_string_field(&mut map, "name", self.name().as_ref()); + JsonCodecHelper::encode_option_string_field(&mut map, "icon", self.icon().as_ref()); + JsonCodecHelper::encode_option_string_field( &mut map, - "members", - &self.members().iter().map(|m| m.id).collect_vec(), + "description", + self.description().as_ref(), ); + + if let GroupBodyContent::Org(org) = self { + JsonCodecHelper::encode_str_array_field(&mut map, "admins", org.admins()); + } + JsonCodecHelper::encode_str_array_field(&mut map, "members", self.members()); JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", self.ood_list()); + JsonCodecHelper::encode_option_string_field( + &mut map, + "prev_blob_id", + self.prev_blob_id().as_ref(), + ); + JsonCodecHelper::encode_string_field(&mut map, "version", &self.version()); map.into() } diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 5ddd02ae7..70c3c0342 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -2,6 +2,7 @@ use crate::codec as cyfs_base; use crate::*; use std::convert::TryFrom; +use std::str::FromStr; pub enum GroupMemberScope { Admin, @@ -15,6 +16,15 @@ pub enum GroupDescContent { Org(OrgDescContent), } +impl GroupDescContent { + pub fn founder_id(&self) -> &Option { + match self { + GroupDescContent::SimpleGroup(desc) => &desc.founder_id, + GroupDescContent::Org(desc) => &desc.founder_id, + } + } +} + #[derive(Clone, Debug, RawEncode, RawDecode)] pub enum GroupBodyContent { SimpleGroup(SimpleGroupBodyContent), @@ -39,16 +49,16 @@ impl BodyContent for GroupBodyContent { } impl GroupBodyContent { - pub fn name(&self) -> &str { - self.common().name.as_str() + pub fn name(&self) -> &Option { + &self.common().name } - pub fn icon(&self) -> &Option { + pub fn icon(&self) -> &Option { &self.common().icon } - pub fn description(&self) -> &str { - self.common().description.as_str() + pub fn description(&self) -> &Option { + &self.common().description } pub fn members(&self) -> &Vec { @@ -146,27 +156,27 @@ impl Group { } } - pub fn name(&self) -> &str { - self.common().name.as_str() + pub fn name(&self) -> &Option { + &self.common().name } - pub fn set_name(&mut self, name: String) { + pub fn set_name(&mut self, name: Option) { self.common_mut().name = name; } - pub fn icon(&self) -> &Option { + pub fn icon(&self) -> &Option { &self.common().icon } - pub fn set_icon(&mut self, icon: Option) { + pub fn set_icon(&mut self, icon: Option) { self.common_mut().icon = icon; } - pub fn description(&self) -> &str { - self.common().description.as_str() + pub fn description(&self) -> &Option { + &self.common().description } - pub fn set_description(&mut self, description: String) { + pub fn set_description(&mut self, description: Option) { self.common_mut().description = description; } @@ -344,6 +354,9 @@ pub struct GroupMember { } impl GroupMember { + pub fn new(id: ObjectId, title: String) -> Self { + GroupMember { id, title } + } pub fn from_member_id(id: ObjectId) -> GroupMember { GroupMember { id, @@ -378,11 +391,41 @@ impl TryFrom<&GroupMember> for protos::GroupMember { } } +impl FromStr for GroupMember { + type Err = BuckyError; + + fn from_str(s: &str) -> Result { + let mut fields = s.split(":"); + + let id = if let Some(id) = fields.next() { + PeopleId::from_str(id)? + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + "need peopleid of member.", + )); + }; + + let title = fields.next().unwrap_or(""); + + Ok(Self { + id: id.object_id().clone(), + title: title.to_string(), + }) + } +} + +impl ToString for GroupMember { + fn to_string(&self) -> String { + format!("{}:{}", self.id, self.title) + } +} + #[derive(Clone, Debug, Default)] struct CommonGroupBodyContent { - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, members: Vec, @@ -394,9 +437,9 @@ struct CommonGroupBodyContent { impl CommonGroupBodyContent { fn new( - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, members: Vec, ood_list: Vec, ) -> Self { @@ -417,13 +460,21 @@ impl TryFrom for CommonGroupBodyContent { fn try_from(mut value: protos::CommonGroupBodyContent) -> BuckyResult { let ret = Self { - name: value.take_name(), + name: if value.has_name() { + Some(value.take_name()) + } else { + None + }, icon: if value.has_icon() { - Some(ProtobufCodecHelper::decode_buf(value.take_icon())?) + Some(value.take_icon()) + } else { + None + }, + description: if value.has_description() { + Some(value.take_description()) } else { None }, - description: value.take_description(), members: ProtobufCodecHelper::decode_value_list(value.take_members())?, ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, version: value.version, @@ -444,11 +495,15 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { fn try_from(value: &CommonGroupBodyContent) -> BuckyResult { let mut ret = Self::new(); - ret.name = value.name.clone(); - if let Some(icon) = &value.icon { - ret.set_icon(icon.to_vec()?); + if let Some(name) = value.name.as_ref() { + ret.set_name(name.clone()); + } + if let Some(icon) = value.icon.as_ref() { + ret.set_icon(icon.clone()); + } + if let Some(description) = value.description.as_ref() { + ret.set_description(description.clone()); } - ret.description = value.description.clone(); ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( @@ -471,6 +526,12 @@ pub struct SimpleGroupDescContent { admins: Vec, } +impl SimpleGroupDescContent { + pub fn admins(&self) -> &Vec { + &self.admins + } +} + impl TryFrom for SimpleGroupDescContent { type Error = BuckyError; @@ -512,9 +573,9 @@ pub struct SimpleGroupBodyContent { impl SimpleGroupBodyContent { fn new( - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, members: Vec, ood_list: Vec, ) -> Self { @@ -594,9 +655,9 @@ pub struct OrgBodyContent { impl OrgBodyContent { fn new( - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, admins: Vec, members: Vec, ood_list: Vec, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 8186031b8..bc8b5fded 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -174,7 +174,7 @@ mod Common { ) -> Group { log::info!("create group"); - let mut group = Group::new_org(founder.desc().object_id(), Area::default()).build(); + let mut group = Group::new_org(Some(founder.desc().object_id()), Area::default()).build(); group.check_org_body_content_mut().set_admins( admins .iter() diff --git a/src/tools/desc-tool/src/create.rs b/src/tools/desc-tool/src/create.rs index 2e9b8e842..0671520f5 100644 --- a/src/tools/desc-tool/src/create.rs +++ b/src/tools/desc-tool/src/create.rs @@ -1,17 +1,28 @@ -use clap::{ArgMatches, App, SubCommand, Arg}; use crate::desc; -use crate::util::{get_objids_from_matches, get_deviceids_from_matches}; -use std::path::{Path}; +use crate::desc::create_people_desc; +use crate::util::{ + get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches, +}; +use clap::{App, Arg, ArgMatches, SubCommand}; +use cyfs_base::{ + sign_and_set_named_object_desc, Area, DeviceCategory, FileEncoder, + NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, SignatureSource, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, BuckyResult, +}; use log::*; -use cyfs_base::{Area, FileEncoder, NamedObject, ObjectDesc, AnyNamedObject, FileDecoder, PublicKeyRef, DeviceCategory, ObjectId, RsaCPUObjectSigner, sign_and_set_named_object_desc, SignatureSource, SIGNATURE_SOURCE_REFINDEX_SELF, SIGNATURE_SOURCE_REFINDEX_OWNER}; -use std::str::FromStr; use std::io::Write; -use crate::desc::create_people_desc; - +use std::path::Path; +use std::str::FromStr; pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { - let id_file_arg = Arg::with_name("id_file").long("idfile").takes_value(true).help("write object id to file"); - let save_path = Arg::with_name("save_path").long("savepath").takes_value(true).help("save file path"); + let id_file_arg = Arg::with_name("id_file") + .long("idfile") + .takes_value(true) + .help("write object id to file"); + let save_path = Arg::with_name("save_path") + .long("savepath") + .takes_value(true) + .help("save file path"); SubCommand::with_name("create").about("create desc") .subcommand(SubCommand::with_name("people").about("create people desc and sec") .arg(Arg::with_name("owner").long("owner").short("o").takes_value(true) @@ -24,15 +35,25 @@ pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { .arg(Arg::with_name("area").long("area").short("a").takes_value(true) .help("Object area info, if not set,will calc base ip. format [county:carrier:city:inner]")) .arg(id_file_arg.clone()).arg(save_path.clone())) - .subcommand(SubCommand::with_name("sgroup").about("create sgroup desc") - .arg(Arg::with_name("threshold").long("threshold").default_value("1").required(true) - .help("threshold in simple group")) + .subcommand(SubCommand::with_name("group").about("create group desc") + .arg(Arg::with_name("founder").long("founder").short("f") + .help("founder of group")) + .arg(Arg::with_name("admins").required(true).long("admins").short("A").value_delimiter(";") + .help("admins in group. format [peopleid:title]")) .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";") - .help("members in simple group")) + .help("members in group. format [peopleid:title]")) .arg(Arg::with_name("ood_list").long("oodlist").short("l").value_delimiter(";") .help("oods in group")) - .arg(Arg::with_name("owners").long("owners").short("o").value_delimiter(";") - .help("group owners, must have desc file in same path")) + .arg(Arg::with_name("name").long("name").short("n") + .help("name of group")) + .arg(Arg::with_name("icon").long("icon").short("I") + .help("icon of group")) + .arg(Arg::with_name("description").long("description").short("d") + .help("description of group")) + .arg(Arg::with_name("area").required(true).long("area").short("a").takes_value(true) + .help("Object area info. format [county:carrier:city:inner]")) + .arg(Arg::with_name("org").long("org").short("O").takes_value(false) + .help("create a group as organization that administrators is changable.")) .arg(id_file_arg.clone()).arg(save_path.clone())) .subcommand(SubCommand::with_name("device").about("create device desc and sec") .arg(Arg::with_name("area").long("area").short("a").takes_value(true) @@ -71,14 +92,23 @@ fn write_id_file(matches: &ArgMatches, id: &ObjectId) { } fn get_area(matches: &ArgMatches) -> Option { - matches.value_of("area").map(|str_area| { - match Area::from_str(str_area) { + matches + .value_of("area") + .map(|str_area| match Area::from_str(str_area) { Ok(area) => area, Err(_) => { error!("decode area from {} fail, use default", str_area); Area::default() - }, - } + } + }) +} + +fn get_area_no_default(matches: &ArgMatches) -> BuckyResult> { + matches.value_of("area").map_or(Ok(None), |str_area| { + Area::from_str(str_area).map(|a| Some(a)).map_err(|e| { + error!("decode area from {} fail", str_area); + e + }) }) } @@ -88,17 +118,17 @@ fn get_key_bits(matches: &ArgMatches) -> usize { "rsa2048" => 2048, "rsa3072" => 3072, "secp" => 1, - _ => 0 + _ => 0, } } pub async fn create_desc(matches: &ArgMatches<'_>) { match matches.subcommand() { ("device", Some(matches)) => { - let owner = matches.value_of("owner").map(|str| { - ObjectId::from_str(str).unwrap() - }); - let sn_list = get_deviceids_from_matches(matches,"snlist").unwrap_or(vec![]); + let owner = matches + .value_of("owner") + .map(|str| ObjectId::from_str(str).unwrap()); + let sn_list = get_deviceids_from_matches(matches, "snlist").unwrap_or(vec![]); let eps = matches.values_of_lossy("eps").unwrap_or(vec![]); let str_unique_id = matches.value_of("deviceid").unwrap(); @@ -116,79 +146,41 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { "pc" => DeviceCategory::PC, "server" => DeviceCategory::Server, "browser" => DeviceCategory::Browser, - _ => {unreachable!()} + _ => { + unreachable!() + } }; let area = get_area(matches); let save_path = matches.value_of("save_path").unwrap_or("").to_owned(); - if let Some((device, _)) = desc::create_device_desc(area, category, key_bits, str_unique_id, owner, eps, sn_list, Some(save_path)) { + if let Some((device, _)) = desc::create_device_desc( + area, + category, + key_bits, + str_unique_id, + owner, + eps, + sn_list, + Some(save_path), + ) { write_id_file(matches, &device.desc().calculate_id()); } return; } - ("sgroup", Some(matches)) => { - // TODO - // match matches.value_of("threshold").unwrap().parse::() { - // Ok(threshold) => { - // let owners = if let Some(strs) = matches.values_of_lossy("owners") { - // let mut owners = vec![]; - // for str in &strs { - // if let Ok((obj, _)) = AnyNamedObject::decode_from_file(&Path::new(str).with_extension("desc"), &mut vec![]) { - // if let Some(pk) = obj.public_key() { - // match pk { - // PublicKeyRef::Single(pk) => {owners.push(pk.clone())} - // PublicKeyRef::MN((_, pks)) => { - // owners.append(&mut pks.clone()) - // } - // } - // } else { - // warn!("desc {} not have pubkey, ignore", str); - // } - // } else { - // error!("decode desc file {} fail", str); - // } - // } - // owners - // } else { - // vec![] - // }; - - // if threshold as usize > owners.len() { - // error!("threshold must small owners count, detail info use --help"); - // return; - // } - - // let group_desc = desc::create_simple_group_desc(threshold - // , owners - // , get_objids_from_matches(matches, "members") - // , get_deviceids_from_matches(matches, "ood_list")); - - // let groupid = group_desc.desc().calculate_id(); - // let desc_file = Path::new(matches.value_of("save_path").unwrap_or("")).join(&groupid.to_string()).with_extension("desc"); - // if let Err(e) = group_desc.encode_to_file(&desc_file, true) { - // error!("write imple group desc file failed, err {}", e); - // } else { - // info!("write simple group desc file succ to {}", desc_file.display()); - // write_id_file(matches, &groupid); - // }; - // }, - // Err(_e) => { - // error!("threshold must number, detail info use --help"); - // return; - // } - // } - } + ("group", Some(matches)) => create_group_desc(matches).await, ("people", Some(matches)) => { - let owner_id = matches.value_of("owner").map(|str| { - ObjectId::from_str(str).unwrap() - }); + let owner_id = matches + .value_of("owner") + .map(|str| ObjectId::from_str(str).unwrap()); let ood_list = get_deviceids_from_matches(matches, "ood_list").unwrap_or(vec![]); let key_bits = get_key_bits(matches); let area = get_area(matches); let (people, secret) = create_people_desc(area, key_bits, owner_id, ood_list); let objid = people.desc().calculate_id(); - let file_path = Path::new(matches.value_of("save_path").unwrap_or("")).join(&objid.to_string()).with_extension("desc"); + let file_path = Path::new(matches.value_of("save_path").unwrap_or("")) + .join(&objid.to_string()) + .with_extension("desc"); if let Err(e) = people.encode_to_file(&file_path, true) { error!("write people file failed, err {}", e); } else { @@ -209,24 +201,66 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { let people_id = people.desc().calculate_id(); // 再创建ood,使用people为owner - let (mut ood_desc, ood_sec) = desc::create_device_desc(area.clone(), DeviceCategory::OOD, key_bits, "ood", Some(people_id.clone()) - , vec![], vec![], None).unwrap(); + let (mut ood_desc, ood_sec) = desc::create_device_desc( + area.clone(), + DeviceCategory::OOD, + key_bits, + "ood", + Some(people_id.clone()), + vec![], + vec![], + None, + ) + .unwrap(); // 修改people的ood_list people.ood_list_mut().push(ood_desc.desc().device_id()); // 再创建client,使用people为owner - let (mut client_desc, client_sec) = desc::create_device_desc(area, DeviceCategory::PC, key_bits, "client", Some(people_id.clone()) - , vec![], vec![], None).unwrap(); + let (mut client_desc, client_sec) = desc::create_device_desc( + area, + DeviceCategory::PC, + key_bits, + "client", + Some(people_id.clone()), + vec![], + vec![], + None, + ) + .unwrap(); let signer = RsaCPUObjectSigner::new(people_sec.public(), people_sec.clone()); // 给desc签名 - sign_and_set_named_object_desc(&signer, &mut people, &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF)).await.unwrap(); - sign_and_set_named_object_desc(&signer, &mut ood_desc, &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER)).await.unwrap(); - sign_and_set_named_object_desc(&signer, &mut client_desc, &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER)).await.unwrap(); + sign_and_set_named_object_desc( + &signer, + &mut people, + &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); + sign_and_set_named_object_desc( + &signer, + &mut ood_desc, + &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + sign_and_set_named_object_desc( + &signer, + &mut client_desc, + &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); let file_path = Path::new(matches.value_of("save_path").unwrap_or("")); // 存储这些对象 let mut postfix = String::from(""); - if Path::new(&file_path.join(format!("device{}", &postfix)).with_extension("desc")).exists() { + if Path::new( + &file_path + .join(format!("device{}", &postfix)) + .with_extension("desc"), + ) + .exists() + { postfix = chrono::Local::now().format("-%F-%H-%M-%S").to_string(); } let people_file = file_path.join(format!("people{}", &postfix)); @@ -255,11 +289,94 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { if let Err(e) = client_sec.encode_to_file(&client_file.with_extension("sec"), false) { error!("write client sec failed, err {}", e); } - } v @ _ => { error!("not support create type {}", v.0); return; } } -} \ No newline at end of file +} + +pub async fn create_group_desc(matches: &ArgMatches<'_>) { + let admins = match get_group_members_from_matches(matches, "admins") { + Ok(admins) => { + if admins.len() == 0 { + log::error!("empty admins."); + return; + } + admins + } + Err(e) => { + log::error!("invalid admins: {}", e.msg()); + return; + } + }; + + let area = match get_area_no_default(matches) { + Ok(area) => match area { + Some(area) => area, + None => { + log::error!("area is expected, detail info use --help"); + return; + } + }, + Err(_) => return, + }; + + let founder = match matches.value_of("founder") { + Some(str) => match ObjectId::from_str(str) { + Ok(id) => Some(id), + Err(_) => { + log::error!("invalid founder: {}", str); + return; + } + }, + None => None, + }; + + let members = match get_group_members_from_matches(matches, "members") { + Ok(members) => members, + Err(e) => { + log::error!("invalid members: {}", e.msg()); + return; + } + }; + + let ood_list = get_deviceids_from_matches(matches, "ood_list").unwrap_or(vec![]); + if ood_list.len() == 0 { + log::error!("no valid ood found."); + return; + } + + let name = matches.value_of("name").map(|s| s.into()); + let icon = matches.value_of("icon").map(|s| s.into()); + let description = matches.value_of("description").map(|s| s.into()); + let is_org = matches.is_present("org"); + + let group_desc = desc::create_group_desc( + founder, + admins, + members, + ood_list, + area, + name, + icon, + description, + is_org, + ); + + let groupid = group_desc.desc().calculate_id(); + let desc_file = Path::new(matches.value_of("save_path").unwrap_or("")) + .join(&groupid.to_string()) + .with_extension("desc"); + if let Err(e) = group_desc.encode_to_file(&desc_file, true) { + error!("write group desc file failed, err {}", e); + } else { + info!( + "write group({}) desc file succ to {}", + groupid, + desc_file.display() + ); + write_id_file(matches, &groupid); + }; +} diff --git a/src/tools/desc-tool/src/desc.rs b/src/tools/desc-tool/src/desc.rs index 58b6a250e..42b971d19 100644 --- a/src/tools/desc-tool/src/desc.rs +++ b/src/tools/desc-tool/src/desc.rs @@ -3,19 +3,30 @@ use log::*; use std::path::Path; use std::str::FromStr; -pub fn create_simple_group_desc( - founder_id: ObjectId, +pub fn create_group_desc( + founder_id: Option, admins: Vec, - conclusion_limit: Option, + members: Vec, + oods: Vec, area: Area, + name: Option, + icon: Option, + description: Option, + is_org: bool, ) -> Group { - let area_info = Area::default(); - Group::new_simple_group(founder_id, admins, conclusion_limit, area).build() -} - -pub fn create_org_desc(founder_id: ObjectId, area: Area) -> Group { - let area_info = Area::default(); - Group::new_org(founder_id, area).build() + let mut group = if is_org { + let mut group = Group::new_org(founder_id, area).build(); + group.check_org_body_content_mut().set_admins(admins); + group + } else { + Group::new_simple_group(founder_id, admins, area).build() + }; + group.set_members(members); + group.set_ood_list(oods); + group.set_name(name); + group.set_icon(icon); + group.set_description(description); + group } pub fn create_people_desc( diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index 8f97b3f8a..cec413f4c 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -1,8 +1,9 @@ use clap::{App, SubCommand, Arg, ArgMatches}; -use crate::util::{get_objids_from_matches, get_eps_from_matches, get_deviceids_from_matches}; +use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches}; use log::*; -use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc}; +use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId}; use cyfs_core::{CoreObjectType, DecApp, DecAppObj, AppList, AppStatus, AppListObj, AppStatusObj, DecAppId}; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::str::FromStr; @@ -11,11 +12,17 @@ pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { .arg(Arg::with_name("desc").required(true).index(1).help("desc file to modify")) .arg(Arg::with_name("sn").short("s").long("sn").value_delimiter(";").help("new sn list")) .arg(Arg::with_name("eps").long("eps").short("e").value_delimiter(";").help("new endpoint list")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("members set to simple group")) - .arg(Arg::with_name("add_members").long("add").short("a").value_delimiter(";").help("members append to simple group")) - .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people")) - .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people")) - .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("people name")) + .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("administrators set to group")) + .arg(Arg::with_name("add_admins").long("add_admin").short("aA").value_delimiter(";").help("administrators append to group")) + .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("members set to group")) + .arg(Arg::with_name("add_members").long("add_member").short("am").value_delimiter(";").help("members append to group")) + .arg(Arg::with_name("description").short("d").long("description").takes_value(true).help("description of group")) + .arg(Arg::with_name("version").short("v").long("version").takes_value(true).help("version of group")) + .arg(Arg::with_name("prev_blob_id").short("p").long("prev").takes_value(true).help("prev-blob-id of group")) + .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people or group")) + .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people or group")) + .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("name of people or group")) + .arg(Arg::with_name("icon").short("I").long("icon").takes_value(true).help("icon of people or group")) .arg(Arg::with_name("source").long("source").value_delimiter(";").help("add source to app, {ver}:{id}")) .arg(Arg::with_name("app_id").long("appid").takes_value(true).help("app id add to app list")) .arg(Arg::with_name("app_ver").long("appver").takes_value(true).help("app ver add to app list")) @@ -42,23 +49,9 @@ pub fn modify_desc(matches: &ArgMatches) { info!("modify success"); }, StandardObject::Group(mut g) => { - // TODO - // let content = g.body_mut().as_mut().unwrap().content_mut(); - // if let Some(members) = get_objids_from_matches(matches, "members") { - // content.members_mut().clone_from(&members); - // } - - // if let Some(members) = get_objids_from_matches(matches, "add_members") { - // for member in members { - // if !content.members_mut().contains(&member) { - // content.members_mut().push(member); - // } else { - // info!("obj {} already in group, skip.", &member); - // } - // } - // } - - // g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + if modify_group_desc(&mut g, matches).is_ok() { + g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + } } StandardObject::People(mut p) => { let content = p.body_mut().as_mut().unwrap().content_mut(); @@ -71,7 +64,7 @@ pub fn modify_desc(matches: &ArgMatches) { if !content.ood_list_mut().contains(&ood) { content.ood_list_mut().push(ood); } else { - info!("obj {} already in group, skip.", &ood); + info!("obj {} already exist, skip.", &ood); } } } @@ -80,6 +73,15 @@ pub fn modify_desc(matches: &ArgMatches) { content.set_name(name.to_owned()); } + if let Some(icon) = matches.value_of("icon") { + match FileId::from_str(icon) { + Ok(icon) => content.set_icon(icon), + Err(_) => { + warn!("invalid icon {}", icon); + }, + } + } + p.encode_to_file(path.as_ref(), false).expect("write desc file err"); } _ => { @@ -127,4 +129,112 @@ pub fn modify_desc(matches: &ArgMatches) { error!("read desc from file {} failed, err {}", path, e); }, } +} + +fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> { + let group_id = group.desc().object_id(); + + match get_group_members_from_matches(matches, "members") { + Ok(members) => { + group.set_members(members); + }, + Err(err) => { + log::error!("update group({}) failed for invalid member.", group_id); + return Err(err); + } + } + + match get_group_members_from_matches(matches, "add_members") { + Ok(additional_members) => { + let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); + additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); + group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + }, + Err(err) => { + log::error!("update group({}) failed for invalid member.", group_id); + return Err(err); + } + } + + match get_group_members_from_matches(matches, "admins") { + Ok(admins) => { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + org.set_admins(admins); + }, + Err(err) => { + log::error!("update group({}) failed for invalid administrator.", group_id); + return Err(err); + } + } + + match get_group_members_from_matches(matches, "add_admins") { + Ok(additional_admins) => { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); + additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); + org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + }, + Err(err) => { + log::error!("update group({}) failed for invalid administrator.", group_id); + return Err(err); + } + } + + match get_deviceids_from_matches(matches, "ood_lists") { + Some(oods) => { + group.set_ood_list(oods); + }, + None => { + group.set_ood_list(vec![]); + } + } + if let Some(additional_oods) = get_deviceids_from_matches(matches, "add_oods") { + let mut oods = HashSet::::from_iter(group.ood_list().iter().map(|id| id.clone())); + additional_oods.into_iter().for_each(|id| {oods.insert(id);}); + group.set_ood_list(oods.into_iter().collect()); + } + + if let Some(description) = matches.value_of("description") { + group.set_description(Some(description.to_string())); + } + + if let Some(icon) = matches.value_of("icon") { + group.set_icon(Some(icon.to_string())); + } + + if let Some(version) = matches.value_of("version") { + let version = match version.parse::() { + Ok(v) => v, + Err(e) => { + let msg = format!("update group({}) failed for invalid version {}, err: {:?}", group_id, version, e); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + group.set_version(version); + } + + if let Some(prev_blob_id) = matches.value_of("prev_blob_id") { + let prev_blob_id = match ObjectId::from_str(prev_blob_id) { + Ok(prev_blob_id) => prev_blob_id, + Err(e) => { + let msg = format!("update group({}) failed for invalid prev-blob-id {}", group_id, prev_blob_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + group.set_prev_blob_id(Some(prev_blob_id)); + } + + Ok(()) } \ No newline at end of file diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index 3db58180d..5125ee948 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -1,5 +1,9 @@ use clap::{App, Arg, ArgMatches, SubCommand}; -use cyfs_base::{AnyNamedObject, ChunkList, Dir, DirBodyContent, File, FileDecoder, InnerNode, NDNObjectInfo, NamedObject, ObjectDesc, RawEncode, RawFrom, SignatureSource, SingleKeyObjectDesc, StandardObject, AreaObjectDesc}; +use cyfs_base::{ + AnyNamedObject, AreaObjectDesc, ChunkList, Dir, DirBodyContent, File, FileDecoder, Group, + InnerNode, NDNObjectInfo, NamedObject, ObjectDesc, RawEncode, RawFrom, SignatureSource, + SingleKeyObjectDesc, StandardObject, +}; use cyfs_core::{AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj}; use std::convert::TryFrom; use std::path::Path; @@ -41,13 +45,19 @@ pub fn show_desc_subcommand<'a, 'b>() -> App<'a, 'b> { Arg::with_name("show_members") .short("m") .long("member") - .help("show members in simple group"), + .help("show members in group"), + ) + .arg( + Arg::with_name("show_admins") + .short("A") + .long("admins") + .help("show administrators in group"), ) .arg( Arg::with_name("show_oodlist") .short("l") .long("ood_list") - .help("show ood_list in people"), + .help("show ood_list in people or group"), ) .arg( Arg::with_name("all") @@ -159,6 +169,66 @@ fn show_dir(dir: &Dir, matches: &ArgMatches) { } } +fn show_group(group: &Group, matches: &ArgMatches) { + println!("desc type: Group"); + let is_all = matches.is_present("all"); + + if is_all { + println!("name: {}", group.name().as_ref().map_or("", |n| n.as_str())); + println!( + "founder: {}", + group.founder_id().map_or("".to_string(), |f| f.to_string()) + ); + println!("icon: {}", group.icon().as_ref().map_or("", |icon| icon.as_str())); + println!( + "description: {}", + group.description().as_ref().map_or("", |d| d.as_str()) + ); + println!( + "area: {}", + group.desc().area().as_ref().map_or("None".to_string(), |a| a.to_string()) + ); + println!("version: {}", group.version()); + println!( + "prev-blob-id: {}", + group + .prev_blob_id() + .map_or("None".to_string(), |prev| prev.to_string()) + ); + } + + if is_all || matches.is_present("show_admins") { + print!( + "administrators({}): [", + if group.is_org() { + "mutable" + } else { + "immutable" + } + ); + for member in group.admins() { + print!("{}, ", member.to_string()); + } + println!("]"); + } + + if is_all || matches.is_present("show_members") { + print!("members: ["); + for member in group.members() { + print!("{}, ", member.to_string()); + } + println!("]"); + } + + if is_all || matches.is_present("show_oodlist") { + print!("ood_list: ["); + for ood in group.ood_list() { + print!("{}, ", ood); + } + println!("]"); + } +} + pub fn show_desc(matches: &ArgMatches) { let path = Path::new(matches.value_of("desc_file").unwrap()); let mut file_buf = vec![]; @@ -216,7 +286,6 @@ pub fn show_desc(matches: &ArgMatches) { if let Some(area) = p.desc().area() { println!("area: {}", area) } - } if matches.is_present("all") || matches.is_present("show_endpoint") { print!("endpoint: ["); @@ -237,7 +306,9 @@ pub fn show_desc(matches: &ArgMatches) { let pubkey = p.desc().public_key(); let mut buf = vec![]; buf.resize(pubkey.raw_measure(&None).unwrap(), 0); - pubkey.raw_encode(&mut buf, &None).expect("encode pubkey err"); + pubkey + .raw_encode(&mut buf, &None) + .expect("encode pubkey err"); println!("pubkey: {}", hex::encode(&buf)); println!("createtime: {}", p.desc().create_time()); println!("device catelogy: {}", p.category().unwrap()) @@ -251,16 +322,7 @@ pub fn show_desc(matches: &ArgMatches) { ua.desc().content().right() ); } - StandardObject::Group(g) => { - println!("desc type: Group"); - if matches.is_present("all") || matches.is_present("show_members") { - print!("members: ["); - for owner in g.body().as_ref().unwrap().content().members() { - print!("{}, ", owner.id); - } - println!("]"); - } - } + StandardObject::Group(g) => show_group(g, matches), StandardObject::File(f) => { show_file(f, matches); } diff --git a/src/tools/desc-tool/src/util.rs b/src/tools/desc-tool/src/util.rs index 6111220dd..c25854018 100644 --- a/src/tools/desc-tool/src/util.rs +++ b/src/tools/desc-tool/src/util.rs @@ -1,20 +1,18 @@ use clap::ArgMatches; +use cyfs_base::{DeviceId, Endpoint, GroupMember, ObjectId, BuckyResult}; use log::*; -use std::str::FromStr; -use cyfs_base::{ObjectId, Endpoint, DeviceId}; use std::convert::TryFrom; +use std::str::FromStr; pub fn get_objids_from_matches(matches: &ArgMatches, name: &str) -> Option> { if let Some(strs) = matches.values_of_lossy(name) { let mut ret = vec![]; for str in &strs { match ObjectId::from_str(str) { - Ok(obj) => { - ret.push(obj) - }, + Ok(obj) => ret.push(obj), Err(_) => { error!("{} not valid objid, ignore", str); - }, + } } } Some(ret) @@ -24,7 +22,7 @@ pub fn get_objids_from_matches(matches: &ArgMatches, name: &str) -> Option Option> { - get_objids_from_matches(matches, name).map(|objs|{ + get_objids_from_matches(matches, name).map(|objs| { let mut ret = vec![]; for obj in &objs { if let Ok(device_id) = DeviceId::try_from(obj) { @@ -42,16 +40,29 @@ pub fn get_eps_from_matches(matches: &ArgMatches, name: &str) -> Option { - ret.push(obj) - }, + Ok(obj) => ret.push(obj), Err(_) => { error!("{} not valid endpoint, ignore", str); - }, + } } } Some(ret) } else { None } -} \ No newline at end of file +} + +pub fn get_group_members_from_matches( + matches: &ArgMatches, + name: &str, +) -> BuckyResult> { + if let Some(strs) = matches.values_of_lossy(name) { + let mut ret = vec![]; + for str in &strs { + ret.push(GroupMember::from_str(str)?); + } + Ok(ret) + } else { + Ok(vec![]) + } +} From 22dbb749fa9d7b3bdbef7e1e4d10192acc352514 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 11 Apr 2023 17:30:12 +0800 Subject: [PATCH 433/553] `desc-tool` for `Group`: debug --- src/tools/desc-tool/src/create.rs | 32 +++++----- src/tools/desc-tool/src/modify.rs | 97 ++++++++++++++++++++----------- src/tools/desc-tool/src/show.rs | 6 +- src/tools/desc-tool/src/util.rs | 6 +- 4 files changed, 88 insertions(+), 53 deletions(-) diff --git a/src/tools/desc-tool/src/create.rs b/src/tools/desc-tool/src/create.rs index 0671520f5..b00612d7a 100644 --- a/src/tools/desc-tool/src/create.rs +++ b/src/tools/desc-tool/src/create.rs @@ -1,7 +1,7 @@ use crate::desc; use crate::desc::create_people_desc; use crate::util::{ - get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches, + get_deviceids_from_matches, get_group_members_from_matches, }; use clap::{App, Arg, ArgMatches, SubCommand}; use cyfs_base::{ @@ -14,6 +14,8 @@ use std::io::Write; use std::path::Path; use std::str::FromStr; +// .\desc-tool.exe create group -F=5r4MYfFfTakY1h6vdEuMurpkawk4MZpB5RmY9CFqSj99 -A=5r4MYfFfTakY1h6vdEuMurpkawk4MZpB5RmY9CFqSj99:;5r4MYfFPPRDNNcJdvve4XVx3FE355PUDpqaA5Mm9UcFh:;5r4MYfFAiXjbEkHZvc1NtHgJkZ4A7LJQcrY7cJeMz5YB:;5r4MYfFKmpMT2u2P13p3bLC6KtGEVsp42X85h5e2onhZ:; -M=5r4MYfF5r9cUfL9JemVXwLWJjufXETYSjfXqEsR3Qwn5:;5r4MYfF8ZaksbXfnZbdjiYJuJv8U4FfvyBgdHq7RiPhY:;5r4MYfFQxUB7okJMvia5yGksrkMBzPrUrwCFgja4Djv3:;5r4MYfFXjPJ9BBYvvdP5QHudAWLNrMzuzZpNpr45pYEc:;5r4MYfFXuCNgbhRPaqtUKsNvNH1RNGF5prFXg7UqiWDS:;5r4MYfFJHxPCYqwLWrHQ24jjv3ZvCbK4dPhBCNn8r3aE:;5r4MYfFXAtLvsW52oCRRAALEt7rEJB7qUdRDEEKAgPJJ:;5r4MYfFdFYt8ytAw9noVjg1aXfeQvHWpaChax73wWKwJ:;5r4MYfFbDWG8jibePJhSoL25mv6tv6ZMDaMZHRzKVEEB:; -l=5aSixgN8tVt1SAM4xBfc1dYvdrU7d5fVeZrzNFpx8FiB;5aSixgMxgNuMQFcG41fW1CN7MTsKMqEuVjW16BnJWrGW;5aSixgN64mtdhmNvKZ681P3iPZbnQPyQsezTFNB2HSdx;5aSixgNS8ij1mkjjNe2UWHVgVYFhr4dJF5BuxxpTb1m8; -n="group" -I="icon" -d="description" -a=0:0:0:0 -O --savepath="./" --idfile="./group.id.txt" + pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { let id_file_arg = Arg::with_name("id_file") .long("idfile") @@ -36,19 +38,19 @@ pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { .help("Object area info, if not set,will calc base ip. format [county:carrier:city:inner]")) .arg(id_file_arg.clone()).arg(save_path.clone())) .subcommand(SubCommand::with_name("group").about("create group desc") - .arg(Arg::with_name("founder").long("founder").short("f") + .arg(Arg::with_name("founder").long("founder").short("F").takes_value(true) .help("founder of group")) .arg(Arg::with_name("admins").required(true).long("admins").short("A").value_delimiter(";") - .help("admins in group. format [peopleid:title]")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";") - .help("members in group. format [peopleid:title]")) + .help("admins in group. format [PeopleId:title]")) + .arg(Arg::with_name("members").long("members").short("M").value_delimiter(";") + .help("members in group. format [PeopleId:title]")) .arg(Arg::with_name("ood_list").long("oodlist").short("l").value_delimiter(";") .help("oods in group")) - .arg(Arg::with_name("name").long("name").short("n") + .arg(Arg::with_name("name").long("name").short("n").takes_value(true) .help("name of group")) - .arg(Arg::with_name("icon").long("icon").short("I") + .arg(Arg::with_name("icon").long("icon").short("I").takes_value(true) .help("icon of group")) - .arg(Arg::with_name("description").long("description").short("d") + .arg(Arg::with_name("description").long("description").short("d").takes_value(true) .help("description of group")) .arg(Arg::with_name("area").required(true).long("area").short("a").takes_value(true) .help("Object area info. format [county:carrier:city:inner]")) @@ -300,11 +302,13 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { pub async fn create_group_desc(matches: &ArgMatches<'_>) { let admins = match get_group_members_from_matches(matches, "admins") { Ok(admins) => { - if admins.len() == 0 { - log::error!("empty admins."); - return; + match admins { + Some(admins) if admins.len() > 0 => admins, + _ => { + log::error!("empty admins."); + return; + } } - admins } Err(e) => { log::error!("invalid admins: {}", e.msg()); @@ -335,7 +339,7 @@ pub async fn create_group_desc(matches: &ArgMatches<'_>) { }; let members = match get_group_members_from_matches(matches, "members") { - Ok(members) => members, + Ok(members) => members.unwrap_or(vec![]), Err(e) => { log::error!("invalid members: {}", e.msg()); return; @@ -370,7 +374,7 @@ pub async fn create_group_desc(matches: &ArgMatches<'_>) { .join(&groupid.to_string()) .with_extension("desc"); if let Err(e) = group_desc.encode_to_file(&desc_file, true) { - error!("write group desc file failed, err {}", e); + error!("write group desc file({:?}) failed, err {}", desc_file, e); } else { info!( "write group({}) desc file succ to {}", diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index cec413f4c..d86672a0a 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -1,7 +1,7 @@ use clap::{App, SubCommand, Arg, ArgMatches}; -use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches}; +use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches}; use log::*; -use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId}; +use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId, bucky_time_now}; use cyfs_core::{CoreObjectType, DecApp, DecAppObj, AppList, AppStatus, AppListObj, AppStatusObj, DecAppId}; use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; @@ -12,13 +12,15 @@ pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { .arg(Arg::with_name("desc").required(true).index(1).help("desc file to modify")) .arg(Arg::with_name("sn").short("s").long("sn").value_delimiter(";").help("new sn list")) .arg(Arg::with_name("eps").long("eps").short("e").value_delimiter(";").help("new endpoint list")) - .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("administrators set to group")) - .arg(Arg::with_name("add_admins").long("add_admin").short("aA").value_delimiter(";").help("administrators append to group")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("members set to group")) - .arg(Arg::with_name("add_members").long("add_member").short("am").value_delimiter(";").help("members append to group")) + .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("set administrators to group. format [PeopleId:title]")) + .arg(Arg::with_name("add_admins").long("add_admin").value_delimiter(";").help("append administrators to group. format [PeopleId:title]")) + .arg(Arg::with_name("remove_admins").long("rm_admin").value_delimiter(";").help("remove administrators from group. format [PeopleId]")) + .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("set members to group. format [PeopleId:title]")) + .arg(Arg::with_name("add_members").long("add_member").value_delimiter(";").help("append members to group. format [PeopleId:title]")) + .arg(Arg::with_name("remove_members").long("rm_member").value_delimiter(";").help("remove members from group. format [PeopleId]")) .arg(Arg::with_name("description").short("d").long("description").takes_value(true).help("description of group")) .arg(Arg::with_name("version").short("v").long("version").takes_value(true).help("version of group")) - .arg(Arg::with_name("prev_blob_id").short("p").long("prev").takes_value(true).help("prev-blob-id of group")) + .arg(Arg::with_name("prev_blob_id").long("prev_blob").takes_value(true).help("prev-blob-id of group")) .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people or group")) .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people or group")) .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("name of people or group")) @@ -51,6 +53,7 @@ pub fn modify_desc(matches: &ArgMatches) { StandardObject::Group(mut g) => { if modify_group_desc(&mut g, matches).is_ok() { g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + info!("modify success"); } } StandardObject::People(mut p) => { @@ -136,7 +139,9 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "members") { Ok(members) => { - group.set_members(members); + if let Some(members) = members { + group.set_members(members); + } }, Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); @@ -146,25 +151,35 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "add_members") { Ok(additional_members) => { - let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); - additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); - group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + if let Some(additional_members) = additional_members { + let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); + additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); + group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + } }, Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); return Err(err); } } + + if let Some(remove_members) = get_objids_from_matches(matches, "remove_members") { + let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); + remove_members.iter().for_each(|m| {members.remove(m);}); + group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + } match get_group_members_from_matches(matches, "admins") { Ok(admins) => { - if group.is_simple_group() { - let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); - log::error!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + if let Some(admins) = admins { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + org.set_admins(admins); } - let org = group.check_org_body_content_mut(); - org.set_admins(admins); }, Err(err) => { log::error!("update group({}) failed for invalid administrator.", group_id); @@ -174,15 +189,17 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "add_admins") { Ok(additional_admins) => { - if group.is_simple_group() { - let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); - log::error!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + if let Some(additional_admins) = additional_admins { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); + additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); + org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); } - let org = group.check_org_body_content_mut(); - let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); - additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); - org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); }, Err(err) => { log::error!("update group({}) failed for invalid administrator.", group_id); @@ -190,13 +207,15 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> } } - match get_deviceids_from_matches(matches, "ood_lists") { - Some(oods) => { - group.set_ood_list(oods); - }, - None => { - group.set_ood_list(vec![]); - } + if let Some(remove_members) = get_objids_from_matches(matches, "remove_admins") { + let org = group.check_org_body_content_mut(); + let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); + remove_members.iter().for_each(|m| {admins.remove(m);}); + org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + } + + if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { + group.set_ood_list(oods); } if let Some(additional_oods) = get_deviceids_from_matches(matches, "add_oods") { let mut oods = HashSet::::from_iter(group.ood_list().iter().map(|id| id.clone())); @@ -212,6 +231,10 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> group.set_icon(Some(icon.to_string())); } + if let Some(name) = matches.value_of("name") { + group.set_name(Some(name.to_string())); + } + if let Some(version) = matches.value_of("version") { let version = match version.parse::() { Ok(v) => v, @@ -227,7 +250,7 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> if let Some(prev_blob_id) = matches.value_of("prev_blob_id") { let prev_blob_id = match ObjectId::from_str(prev_blob_id) { Ok(prev_blob_id) => prev_blob_id, - Err(e) => { + Err(_) => { let msg = format!("update group({}) failed for invalid prev-blob-id {}", group_id, prev_blob_id); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); @@ -236,5 +259,13 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> group.set_prev_blob_id(Some(prev_blob_id)); } + if group.admins().is_empty() { + let msg = format!("update group({}) failed for no administrators", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); + } + + group.body_mut().as_mut().unwrap().set_update_time(bucky_time_now()); + Ok(()) } \ No newline at end of file diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index 5125ee948..d9376b401 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -207,7 +207,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { } ); for member in group.admins() { - print!("{}, ", member.to_string()); + print!("{};", member.to_string()); } println!("]"); } @@ -215,7 +215,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_members") { print!("members: ["); for member in group.members() { - print!("{}, ", member.to_string()); + print!("{};", member.to_string()); } println!("]"); } @@ -223,7 +223,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_oodlist") { print!("ood_list: ["); for ood in group.ood_list() { - print!("{}, ", ood); + print!("{};", ood); } println!("]"); } diff --git a/src/tools/desc-tool/src/util.rs b/src/tools/desc-tool/src/util.rs index c25854018..44d4d9a9c 100644 --- a/src/tools/desc-tool/src/util.rs +++ b/src/tools/desc-tool/src/util.rs @@ -55,14 +55,14 @@ pub fn get_eps_from_matches(matches: &ArgMatches, name: &str) -> Option BuckyResult> { +) -> BuckyResult>> { if let Some(strs) = matches.values_of_lossy(name) { let mut ret = vec![]; for str in &strs { ret.push(GroupMember::from_str(str)?); } - Ok(ret) + Ok(Some(ret)) } else { - Ok(vec![]) + Ok(None) } } From bc486b04a55fc6e1bffa698ee8c21482dd8bb41c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 11 Apr 2023 19:16:45 +0800 Subject: [PATCH 434/553] `desc-tool` read signer from `.desc` --- src/tools/desc-tool/src/sign.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/desc-tool/src/sign.rs b/src/tools/desc-tool/src/sign.rs index d245a74a9..9f57a5654 100644 --- a/src/tools/desc-tool/src/sign.rs +++ b/src/tools/desc-tool/src/sign.rs @@ -109,6 +109,11 @@ pub async fn sign_desc(matches: &ArgMatches<'_>) { }) } else if let Ok(index) = str.parse::() { SignatureSource::RefIndex(index) + } else if let Ok((obj, _)) = AnyNamedObject::decode_from_file(str.as_ref(), &mut vec![]) { + SignatureSource::Object(ObjectLink { + obj_id: obj.object_id(), + obj_owner: None, + }) } else { SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER) } From 63d44e143d20d22f8e5c91fd6404d7c28716b485 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 11 Apr 2023 21:02:18 +0800 Subject: [PATCH 435/553] Sort members by id for encode --- src/component/cyfs-base-meta/src/group.rs | 45 +- .../cyfs-base/protos/standard_objects.proto | 8 +- src/component/cyfs-base/src/codec/format.rs | 29 +- src/component/cyfs-base/src/objects/group.rs | 163 ++++--- .../cyfs-stack/src/resolver/device_manager.rs | 4 +- src/tools/desc-tool/src/modify.rs | 424 ++++++++++++------ src/tools/desc-tool/src/show.rs | 4 +- 7 files changed, 463 insertions(+), 214 deletions(-) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index 34ee769e9..aa986a9b0 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -114,7 +114,22 @@ impl GroupVerifier for Group { return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } - (latest_group.admins(), latest_group.members()) + ( + HashSet::::from_iter( + latest_group + .admins() + .keys() + .filter(|m| m.obj_type_code() == ObjectTypeCode::People) + .map(|m| *m), + ), + HashSet::::from_iter( + latest_group + .members() + .keys() + .filter(|m| m.obj_type_code() == ObjectTypeCode::People) + .map(|m| *m), + ), + ) } None => match self.prev_blob_id() { Some(prev_blob_id) => { @@ -127,7 +142,7 @@ impl GroupVerifier for Group { } None => { if let Some(founder) = self.founder_id() { - if self.admins().iter().find(|m| &m.id == founder).is_none() { + if self.admins().values().find(|m| &m.id == founder).is_none() { let msg = format!( "Update group({}) the founder({}) must be an administrator.", group_id, founder @@ -136,7 +151,7 @@ impl GroupVerifier for Group { return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } } - ([].as_slice(), [].as_slice()) + (HashSet::new(), HashSet::new()) } }, }; @@ -144,33 +159,21 @@ impl GroupVerifier for Group { // admins: > 1/2 // new members: all - let last_admins = HashSet::::from_iter( - last_admins - .iter() - .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) - .map(|m| m.id), - ); - let last_members = HashSet::::from_iter( - last_members - .iter() - .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) - .map(|m| m.id), - ); let add_admins = HashSet::::from_iter( self.admins() - .iter() + .keys() .filter(|m| { - m.id.obj_type_code() == ObjectTypeCode::People && !last_admins.contains(&m.id) + m.obj_type_code() == ObjectTypeCode::People && !last_admins.contains(*m) }) - .map(|m| m.id), + .map(|m| *m), ); let add_members = HashSet::::from_iter( self.members() - .iter() + .keys() .filter(|m| { - m.id.obj_type_code() == ObjectTypeCode::People && !last_members.contains(&m.id) + m.obj_type_code() == ObjectTypeCode::People && !last_members.contains(*m) }) - .map(|m| m.id), + .map(|m| *m), ); if add_admins.len() != self.admins().len() - last_admins.len() { diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index e025fd753..9395f996c 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -70,9 +70,9 @@ message CommonGroupBodyContent { optional string icon = 2; optional string description = 3; - repeated GroupMember members = 4; + repeated GroupMember members = 4; // sort by id deduplicated ascending order - repeated bytes ood_list = 5; + repeated bytes ood_list = 5; // sort by id deduplicated ascending order optional bytes prev_blob_id = 6; uint64 version = 7; @@ -82,7 +82,7 @@ message CommonGroupBodyContent { message SimpleGroupDescContent { bytes unique_id = 1; optional bytes founder_id = 2; - repeated GroupMember admins = 3; + repeated GroupMember admins = 3; // sort by id deduplicated ascending order } message SimpleGroupBodyContent { @@ -96,7 +96,7 @@ message OrgDescContent { } message OrgBodyContent { - repeated GroupMember admins = 1; + repeated GroupMember admins = 1; // sort by id deduplicated ascending order CommonGroupBodyContent common = 2; } diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index 162f5066a..54ea3638d 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -575,7 +575,15 @@ impl ObjectFormat for GroupDescContent { self.founder_id().as_ref(), ); if let GroupDescContent::SimpleGroup(simple_group) = self { - JsonCodecHelper::encode_str_array_field(&mut map, "admins", simple_group.admins()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "admins", + &simple_group + .admins() + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .collect::>(), + ); } map.into() @@ -595,9 +603,24 @@ impl ObjectFormat for GroupBodyContent { ); if let GroupBodyContent::Org(org) = self { - JsonCodecHelper::encode_str_array_field(&mut map, "admins", org.admins()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "admins", + &org.admins() + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .collect::>(), + ); } - JsonCodecHelper::encode_str_array_field(&mut map, "members", self.members()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "members", + &self + .members() + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .collect::>(), + ); JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", self.ood_list()); JsonCodecHelper::encode_option_string_field( &mut map, diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 70c3c0342..57fa54356 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -1,6 +1,10 @@ +use itertools::Itertools; + use crate::codec as cyfs_base; +use crate::protos::standard_objects; use crate::*; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::str::FromStr; @@ -61,11 +65,11 @@ impl GroupBodyContent { &self.common().description } - pub fn members(&self) -> &Vec { + pub fn members(&self) -> &HashMap { &self.common().members } - pub fn members_mut(&mut self) -> &mut Vec { + pub fn members_mut(&mut self) -> &mut HashMap { &mut self.common_mut().members } @@ -121,7 +125,7 @@ impl Group { ) -> GroupBuilder { let desc_content = SimpleGroupDescContent { unique_id: UniqueId::create_with_random(), - admins, + admins: HashMap::from_iter(admins.into_iter().map(|m| (m.id, m))), founder_id, }; @@ -180,52 +184,54 @@ impl Group { self.common_mut().description = description; } - pub fn admins(&self) -> &[GroupMember] { + pub fn admins(&self) -> &HashMap { if self.is_org() { - self.check_org_body_content().admins.as_slice() + &self.check_org_body_content().admins } else { - self.check_simple_group_desc_content().admins.as_slice() + &self.check_simple_group_desc_content().admins } } - pub fn members(&self) -> &[GroupMember] { - self.common().members.as_slice() + pub fn members(&self) -> &HashMap { + &self.common().members } pub fn set_members(&mut self, members: Vec) { - self.common_mut().members = members; + self.common_mut().members = HashMap::from_iter(members.into_iter().map(|m| (m.id, m))); } - pub fn ood_list(&self) -> &[DeviceId] { - self.common().ood_list.as_slice() + pub fn ood_list(&self) -> &Vec { + &self.common().ood_list } pub fn set_ood_list(&mut self, oods: Vec) { - self.common_mut().ood_list = oods; + self.common_mut().ood_list = HashSet::::from_iter(oods.into_iter()) + .into_iter() + .sorted() + .collect(); } pub fn contain_ood(&self, ood_id: &ObjectId) -> bool { - self.ood_list() - .iter() - .find(|id| id.object_id() == ood_id) - .is_some() + match DeviceId::try_from(ood_id) { + Ok(device_id) => self.ood_list().contains(&device_id), + Err(_) => false, + } } pub fn is_same_ood_list(&self, other: &Group) -> bool { let my_oods = self.ood_list(); let other_oods = other.ood_list(); + if my_oods.len() != other_oods.len() { + return false; + } + for id in my_oods { if !other_oods.contains(id) { return false; } } - for id in other_oods { - if !my_oods.contains(id) { - return false; - } - } true } @@ -307,11 +313,11 @@ impl Group { scope: GroupMemberScope, ) -> Vec<&ObjectId> { let mut members = match scope { - GroupMemberScope::Admin => self.admins().iter().map(|m| &m.id).collect::>(), - GroupMemberScope::Member => self.members().iter().map(|m| &m.id).collect::>(), + GroupMemberScope::Admin => self.admins().keys().collect::>(), + GroupMemberScope::Member => self.members().keys().collect::>(), GroupMemberScope::All => [ - self.admins().iter().map(|m| &m.id).collect::>(), - self.members().iter().map(|m| &m.id).collect::>(), + self.admins().keys().collect::>(), + self.members().keys().collect::>(), ] .concat(), }; @@ -325,16 +331,16 @@ impl Group { } pub fn ood_list_with_distance(&self, target: &ObjectId) -> Vec<&ObjectId> { - let mut oods = self + let oods = self .ood_list() .iter() .map(|id| id.object_id()) + .sorted_unstable_by(|l, r| { + let dl = l.distance_of(target); + let dr = r.distance_of(target); + dl.cmp(&dr) + }) .collect::>(); - oods.sort_unstable_by(|l, r| { - let dl = l.distance_of(target); - let dr = r.distance_of(target); - dl.cmp(&dr) - }); oods } @@ -415,7 +421,7 @@ impl FromStr for GroupMember { } } -impl ToString for GroupMember { +impl ToString for &GroupMember { fn to_string(&self) -> String { format!("{}:{}", self.id, self.title) } @@ -427,7 +433,7 @@ struct CommonGroupBodyContent { icon: Option, description: Option, - members: Vec, + members: HashMap, ood_list: Vec, @@ -447,8 +453,11 @@ impl CommonGroupBodyContent { name, icon, description, - members, - ood_list, + members: HashMap::from_iter(members.into_iter().map(|m| (m.id, m))), + ood_list: HashSet::::from_iter(ood_list.into_iter()) + .into_iter() + .sorted() + .collect::>(), version: 0, prev_blob_id: None, } @@ -459,6 +468,9 @@ impl TryFrom for CommonGroupBodyContent { type Error = BuckyError; fn try_from(mut value: protos::CommonGroupBodyContent) -> BuckyResult { + let mut ood_list = ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?; + ood_list.sort(); + let ret = Self { name: if value.has_name() { Some(value.take_name()) @@ -475,8 +487,16 @@ impl TryFrom for CommonGroupBodyContent { } else { None }, - members: ProtobufCodecHelper::decode_value_list(value.take_members())?, - ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, + members: + HashMap::from_iter( + ProtobufCodecHelper::decode_value_list::< + GroupMember, + standard_objects::GroupMember, + >(value.take_members())? + .into_iter() + .map(|m| (m.id, m)), + ), + ood_list, version: value.version, prev_blob_id: if value.has_prev_blob_id() { Some(ProtobufCodecHelper::decode_buf(value.take_prev_blob_id())?) @@ -505,10 +525,21 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { ret.set_description(description.clone()); } - ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); - ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( - value.ood_list.as_slice(), - )?); + let members = value + .members + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .map(|m| m.clone()) + .collect::>(); + ret.set_members(ProtobufCodecHelper::encode_nested_list(&members)?); + + let oods = value + .ood_list + .iter() + .sorted() + .map(|id| id.clone()) + .collect::>(); + ret.set_ood_list(ProtobufCodecHelper::encode_buf_list(oods.as_slice())?); ret.version = value.version; if let Some(prev_blob_id) = &value.prev_blob_id { @@ -523,11 +554,11 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { pub struct SimpleGroupDescContent { unique_id: UniqueId, founder_id: Option, - admins: Vec, + admins: HashMap, } impl SimpleGroupDescContent { - pub fn admins(&self) -> &Vec { + pub fn admins(&self) -> &HashMap { &self.admins } } @@ -543,7 +574,15 @@ impl TryFrom for SimpleGroupDescContent { None }, unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, - admins: ProtobufCodecHelper::decode_value_list(value.admins)?, + admins: + HashMap::from_iter( + ProtobufCodecHelper::decode_value_list::< + GroupMember, + standard_objects::GroupMember, + >(value.admins)? + .into_iter() + .map(|m| (m.id, m)), + ), }; Ok(ret) @@ -560,7 +599,14 @@ impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { if let Some(founder_id) = value.founder_id.as_ref() { ret.set_founder_id(founder_id.to_vec()?); } - ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); + + let admins = value + .admins + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .map(|m| m.clone()) + .collect::>(); + ret.set_admins(ProtobufCodecHelper::encode_nested_list(&admins)?); Ok(ret) } @@ -649,7 +695,7 @@ impl TryFrom<&OrgDescContent> for protos::OrgDescContent { #[derive(Clone, Debug, Default)] pub struct OrgBodyContent { - admins: Vec, + admins: HashMap, common: CommonGroupBodyContent, } @@ -664,16 +710,16 @@ impl OrgBodyContent { ) -> Self { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), - admins, + admins: HashMap::from_iter(admins.into_iter().map(|m| (m.id, m))), } } - pub fn admins(&self) -> &Vec { + pub fn admins(&self) -> &HashMap { &self.admins } pub fn set_admins(&mut self, admins: Vec) { - self.admins = admins; + self.admins = HashMap::from_iter(admins.into_iter().map(|m| (m.id, m))); } } @@ -682,7 +728,15 @@ impl TryFrom for OrgBodyContent { fn try_from(mut value: protos::OrgBodyContent) -> BuckyResult { let ret = Self { - admins: ProtobufCodecHelper::decode_value_list(value.take_admins())?, + admins: + HashMap::from_iter( + ProtobufCodecHelper::decode_value_list::< + GroupMember, + standard_objects::GroupMember, + >(value.take_admins())? + .into_iter() + .map(|m| (m.id, m)), + ), common: ProtobufCodecHelper::decode_value(value.take_common())?, }; @@ -696,7 +750,14 @@ impl TryFrom<&OrgBodyContent> for protos::OrgBodyContent { fn try_from(value: &OrgBodyContent) -> BuckyResult { let mut ret = Self::new(); - ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); + let admins = value + .admins + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .map(|m| m.clone()) + .collect::>(); + + ret.set_admins(ProtobufCodecHelper::encode_nested_list(&admins)?); ret.set_common(ProtobufCodecHelper::encode_nested_item(&value.common)?); Ok(ret) diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 7deeb0083..93652f59c 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -141,8 +141,8 @@ impl DeviceInfoManagerImpl { let group = object.as_group(); let sign_object_ids = HashSet::::from_iter( [ - group.admins().iter().map(|m| m.id).collect::>(), - group.members().iter().map(|m| m.id).collect::>(), + group.admins().iter().map(|m| m.1.id).collect::>(), + group.members().iter().map(|m| m.1.id).collect::>(), ] .concat() .into_iter(), diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index d86672a0a..256d9f9d7 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -1,136 +1,267 @@ -use clap::{App, SubCommand, Arg, ArgMatches}; -use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches}; +use crate::util::{ + get_deviceids_from_matches, get_eps_from_matches, get_group_members_from_matches, + get_objids_from_matches, +}; +use clap::{App, Arg, ArgMatches, SubCommand}; +use cyfs_base::{ + bucky_time_now, AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, DeviceId, FileDecoder, + FileEncoder, FileId, Group, GroupMember, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + StandardObject, +}; +use cyfs_core::{ + AppList, AppListObj, AppStatus, AppStatusObj, CoreObjectType, DecApp, DecAppId, DecAppObj, +}; use log::*; -use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId, bucky_time_now}; -use cyfs_core::{CoreObjectType, DecApp, DecAppObj, AppList, AppStatus, AppListObj, AppStatusObj, DecAppId}; use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::str::FromStr; pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("modify").about("modify desc") - .arg(Arg::with_name("desc").required(true).index(1).help("desc file to modify")) - .arg(Arg::with_name("sn").short("s").long("sn").value_delimiter(";").help("new sn list")) - .arg(Arg::with_name("eps").long("eps").short("e").value_delimiter(";").help("new endpoint list")) - .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("set administrators to group. format [PeopleId:title]")) - .arg(Arg::with_name("add_admins").long("add_admin").value_delimiter(";").help("append administrators to group. format [PeopleId:title]")) - .arg(Arg::with_name("remove_admins").long("rm_admin").value_delimiter(";").help("remove administrators from group. format [PeopleId]")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("set members to group. format [PeopleId:title]")) - .arg(Arg::with_name("add_members").long("add_member").value_delimiter(";").help("append members to group. format [PeopleId:title]")) - .arg(Arg::with_name("remove_members").long("rm_member").value_delimiter(";").help("remove members from group. format [PeopleId]")) - .arg(Arg::with_name("description").short("d").long("description").takes_value(true).help("description of group")) - .arg(Arg::with_name("version").short("v").long("version").takes_value(true).help("version of group")) - .arg(Arg::with_name("prev_blob_id").long("prev_blob").takes_value(true).help("prev-blob-id of group")) - .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people or group")) - .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people or group")) - .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("name of people or group")) - .arg(Arg::with_name("icon").short("I").long("icon").takes_value(true).help("icon of people or group")) - .arg(Arg::with_name("source").long("source").value_delimiter(";").help("add source to app, {ver}:{id}")) - .arg(Arg::with_name("app_id").long("appid").takes_value(true).help("app id add to app list")) - .arg(Arg::with_name("app_ver").long("appver").takes_value(true).help("app ver add to app list")) - .arg(Arg::with_name("app_status").long("appstart").help("start app, default false")) + SubCommand::with_name("modify") + .about("modify desc") + .arg( + Arg::with_name("desc") + .required(true) + .index(1) + .help("desc file to modify"), + ) + .arg( + Arg::with_name("sn") + .short("s") + .long("sn") + .value_delimiter(";") + .help("new sn list"), + ) + .arg( + Arg::with_name("eps") + .long("eps") + .short("e") + .value_delimiter(";") + .help("new endpoint list"), + ) + .arg( + Arg::with_name("admins") + .long("admins") + .short("A") + .value_delimiter(";") + .help("set administrators to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("add_admins") + .long("add_admin") + .value_delimiter(";") + .help("append administrators to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("remove_admins") + .long("rm_admin") + .value_delimiter(";") + .help("remove administrators from group. format [PeopleId]"), + ) + .arg( + Arg::with_name("members") + .long("members") + .short("m") + .value_delimiter(";") + .help("set members to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("add_members") + .long("add_member") + .value_delimiter(";") + .help("append members to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("remove_members") + .long("rm_member") + .value_delimiter(";") + .help("remove members from group. format [PeopleId]"), + ) + .arg( + Arg::with_name("description") + .short("d") + .long("description") + .takes_value(true) + .help("description of group"), + ) + .arg( + Arg::with_name("version") + .short("v") + .long("version") + .takes_value(true) + .help("version of group"), + ) + .arg( + Arg::with_name("prev_blob_id") + .long("prev_blob") + .takes_value(true) + .help("prev-blob-id of group"), + ) + .arg( + Arg::with_name("add_oods") + .long("add_ood") + .short("o") + .value_delimiter(";") + .help("device id append to people or group"), + ) + .arg( + Arg::with_name("ood_lists") + .long("ood_lists") + .short("l") + .value_delimiter(";") + .help("device id set to people or group"), + ) + .arg( + Arg::with_name("name") + .short("n") + .long("name") + .takes_value(true) + .help("name of people or group"), + ) + .arg( + Arg::with_name("icon") + .short("I") + .long("icon") + .takes_value(true) + .help("icon of people or group"), + ) + .arg( + Arg::with_name("source") + .long("source") + .value_delimiter(";") + .help("add source to app, {ver}:{id}"), + ) + .arg( + Arg::with_name("app_id") + .long("appid") + .takes_value(true) + .help("app id add to app list"), + ) + .arg( + Arg::with_name("app_ver") + .long("appver") + .takes_value(true) + .help("app ver add to app list"), + ) + .arg( + Arg::with_name("app_status") + .long("appstart") + .help("start app, default false"), + ) } pub fn modify_desc(matches: &ArgMatches) { let path = matches.value_of("desc").unwrap(); match AnyNamedObject::decode_from_file(path.as_ref(), &mut vec![]) { - Ok((desc, _)) => { - match desc { - AnyNamedObject::Standard(mut obj) => { - match obj { - StandardObject::Device(ref mut p) => { - if let Some(sn_list) = get_deviceids_from_matches(matches, "sn") { - p.body_mut().as_mut().unwrap().content_mut().mut_sn_list().clone_from(&sn_list); - } - - if let Some(ep_list) = get_eps_from_matches(matches, "eps") { - p.body_mut().as_mut().unwrap().content_mut().mut_endpoints().clone_from(&ep_list); - } - - p.encode_to_file(path.as_ref(), false).expect("write desc file err"); - info!("modify success"); - }, - StandardObject::Group(mut g) => { - if modify_group_desc(&mut g, matches).is_ok() { - g.encode_to_file(path.as_ref(), false).expect("write desc file err"); - info!("modify success"); - } - } - StandardObject::People(mut p) => { - let content = p.body_mut().as_mut().unwrap().content_mut(); - if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { - content.ood_list_mut().clone_from(&oods); - } + Ok((desc, _)) => match desc { + AnyNamedObject::Standard(mut obj) => match obj { + StandardObject::Device(ref mut p) => { + if let Some(sn_list) = get_deviceids_from_matches(matches, "sn") { + p.body_mut() + .as_mut() + .unwrap() + .content_mut() + .mut_sn_list() + .clone_from(&sn_list); + } - if let Some(oods) = get_deviceids_from_matches(matches, "add_oods") { - for ood in oods { - if !content.ood_list_mut().contains(&ood) { - content.ood_list_mut().push(ood); - } else { - info!("obj {} already exist, skip.", &ood); - } - } - } + if let Some(ep_list) = get_eps_from_matches(matches, "eps") { + p.body_mut() + .as_mut() + .unwrap() + .content_mut() + .mut_endpoints() + .clone_from(&ep_list); + } - if let Some(name) = matches.value_of("name") { - content.set_name(name.to_owned()); - } + p.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + info!("modify success"); + } + StandardObject::Group(mut g) => { + if modify_group_desc(&mut g, matches).is_ok() { + g.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + info!("modify success"); + } + } + StandardObject::People(mut p) => { + let content = p.body_mut().as_mut().unwrap().content_mut(); + if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { + content.ood_list_mut().clone_from(&oods); + } - if let Some(icon) = matches.value_of("icon") { - match FileId::from_str(icon) { - Ok(icon) => content.set_icon(icon), - Err(_) => { - warn!("invalid icon {}", icon); - }, - } + if let Some(oods) = get_deviceids_from_matches(matches, "add_oods") { + for ood in oods { + if !content.ood_list_mut().contains(&ood) { + content.ood_list_mut().push(ood); + } else { + info!("obj {} already exist, skip.", &ood); } - - p.encode_to_file(path.as_ref(), false).expect("write desc file err"); - } - _ => { - error!("unsupport desc type"); } } - } - AnyNamedObject::Core(obj) => { - match CoreObjectType::from(obj.desc().obj_type()) { - CoreObjectType::DecApp => { - let mut app = DecApp::try_from(obj).unwrap(); - if let Some(values) = matches.values_of_lossy("source") { - for value in &values { - let sources: Vec<&str> = value.split(":").collect(); - app.set_source(sources[0].to_owned(), ObjectId::from_str(sources[1]).unwrap(), None); - } - } - app.encode_to_file(path.as_ref(), false).expect("write desc file err"); - }, - CoreObjectType::AppList => { - let mut list = AppList::try_from(obj).unwrap(); - let owner = list.desc().owner().unwrap(); - if let Some(id_str) = matches.value_of("app_id") { - let dec_id = DecAppId::from_str(id_str).unwrap(); - let version = matches.value_of("app_ver").unwrap().to_owned(); - let app_status = matches.is_present("app_status"); - let status = AppStatus::create(owner, dec_id, version, app_status); + if let Some(name) = matches.value_of("name") { + content.set_name(name.to_owned()); + } - list.put(status); - } else { - list.clear(); + if let Some(icon) = matches.value_of("icon") { + match FileId::from_str(icon) { + Ok(icon) => content.set_icon(icon), + Err(_) => { + warn!("invalid icon {}", icon); } + } + } - list.encode_to_file(path.as_ref(), false).expect("write desc file err"); + p.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + } + _ => { + error!("unsupport desc type"); + } + }, + AnyNamedObject::Core(obj) => match CoreObjectType::from(obj.desc().obj_type()) { + CoreObjectType::DecApp => { + let mut app = DecApp::try_from(obj).unwrap(); + if let Some(values) = matches.values_of_lossy("source") { + for value in &values { + let sources: Vec<&str> = value.split(":").collect(); + app.set_source( + sources[0].to_owned(), + ObjectId::from_str(sources[1]).unwrap(), + None, + ); } - _ => {} } + + app.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); } - AnyNamedObject::DECApp(_) => {} - } + CoreObjectType::AppList => { + let mut list = AppList::try_from(obj).unwrap(); + let owner = list.desc().owner().unwrap(); + if let Some(id_str) = matches.value_of("app_id") { + let dec_id = DecAppId::from_str(id_str).unwrap(); + let version = matches.value_of("app_ver").unwrap().to_owned(); + let app_status = matches.is_present("app_status"); + let status = AppStatus::create(owner, dec_id, version, app_status); + list.put(status); + } else { + list.clear(); + } + + list.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + } + _ => {} + }, + AnyNamedObject::DECApp(_) => {} }, Err(e) => { error!("read desc from file {} failed, err {}", path, e); - }, + } } } @@ -142,7 +273,7 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> if let Some(members) = members { group.set_members(members); } - }, + } Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); return Err(err); @@ -152,11 +283,13 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "add_members") { Ok(additional_members) => { if let Some(additional_members) = additional_members { - let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); - additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); - group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut members = group.members().clone(); + additional_members.into_iter().for_each(|m| { + members.insert(m.id, m); + }); + group.set_members(members.into_iter().map(|(_, m)| m).collect()); } - }, + } Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); return Err(err); @@ -164,11 +297,13 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> } if let Some(remove_members) = get_objids_from_matches(matches, "remove_members") { - let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); - remove_members.iter().for_each(|m| {members.remove(m);}); - group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut members = group.members().clone(); + remove_members.iter().for_each(|m| { + members.remove(m); + }); + group.set_members(members.into_iter().map(|(_, m)| m).collect()); } - + match get_group_members_from_matches(matches, "admins") { Ok(admins) => { if let Some(admins) = admins { @@ -178,11 +313,14 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } let org = group.check_org_body_content_mut(); - org.set_admins(admins); + org.set_admins(admins); } - }, + } Err(err) => { - log::error!("update group({}) failed for invalid administrator.", group_id); + log::error!( + "update group({}) failed for invalid administrator.", + group_id + ); return Err(err); } } @@ -196,22 +334,34 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } let org = group.check_org_body_content_mut(); - let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); - additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); - org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut admins = org.admins().clone(); + additional_admins.into_iter().for_each(|m| { + admins.insert(m.id, m); + }); + org.set_admins(admins.into_iter().map(|(_, m)| m).collect()); } - }, + } Err(err) => { - log::error!("update group({}) failed for invalid administrator.", group_id); + log::error!( + "update group({}) failed for invalid administrator.", + group_id + ); return Err(err); } } if let Some(remove_members) = get_objids_from_matches(matches, "remove_admins") { let org = group.check_org_body_content_mut(); - let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); - remove_members.iter().for_each(|m| {admins.remove(m);}); - org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut admins = org.admins().clone(); + remove_members.iter().for_each(|m| { + admins.remove(m); + }); + org.set_admins( + admins + .into_iter() + .map(|(_, m)| m) + .collect(), + ); } if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { @@ -219,7 +369,9 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> } if let Some(additional_oods) = get_deviceids_from_matches(matches, "add_oods") { let mut oods = HashSet::::from_iter(group.ood_list().iter().map(|id| id.clone())); - additional_oods.into_iter().for_each(|id| {oods.insert(id);}); + additional_oods.into_iter().for_each(|id| { + oods.insert(id); + }); group.set_ood_list(oods.into_iter().collect()); } @@ -239,7 +391,10 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> let version = match version.parse::() { Ok(v) => v, Err(e) => { - let msg = format!("update group({}) failed for invalid version {}, err: {:?}", group_id, version, e); + let msg = format!( + "update group({}) failed for invalid version {}, err: {:?}", + group_id, version, e + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); } @@ -251,7 +406,10 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> let prev_blob_id = match ObjectId::from_str(prev_blob_id) { Ok(prev_blob_id) => prev_blob_id, Err(_) => { - let msg = format!("update group({}) failed for invalid prev-blob-id {}", group_id, prev_blob_id); + let msg = format!( + "update group({}) failed for invalid prev-blob-id {}", + group_id, prev_blob_id + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); } @@ -262,10 +420,14 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> if group.admins().is_empty() { let msg = format!("update group({}) failed for no administrators", group_id); log::error!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); + return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); } - group.body_mut().as_mut().unwrap().set_update_time(bucky_time_now()); + group + .body_mut() + .as_mut() + .unwrap() + .set_update_time(bucky_time_now()); Ok(()) -} \ No newline at end of file +} diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index d9376b401..6014a8f38 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -206,7 +206,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { "immutable" } ); - for member in group.admins() { + for (_, member) in group.admins() { print!("{};", member.to_string()); } println!("]"); @@ -214,7 +214,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_members") { print!("members: ["); - for member in group.members() { + for (_, member) in group.members() { print!("{};", member.to_string()); } println!("]"); From 510347ccef5eff71be5f2e8fe83d40a1ecc0c3d7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 12 Apr 2023 15:37:16 +0800 Subject: [PATCH 436/553] Issue #199: Put the closure in heap to avoid the stack overflowed in `Debug` --- src/meta/cyfs-meta/src/creator.rs | 415 ++++++++++++++++++------------ 1 file changed, 249 insertions(+), 166 deletions(-) diff --git a/src/meta/cyfs-meta/src/creator.rs b/src/meta/cyfs-meta/src/creator.rs index d6a9da392..33fcf5b57 100644 --- a/src/meta/cyfs-meta/src/creator.rs +++ b/src/meta/cyfs-meta/src/creator.rs @@ -1,24 +1,27 @@ -use std::path::{Path, PathBuf}; -use std::fs::File; -use serde_json; -use serde::{Serialize, Deserialize}; -use cyfs_base::*; -use cyfs_base_meta::*; -use crate::state_storage::*; use crate::chain::*; -use log::*; use crate::executor::context::Config; -use crate::mint::btc_mint::BTCMint; -use crate::network::{HttpTcpChainNetwork}; -use async_std::sync::Arc; use crate::http_get_request; +use crate::mint::btc_mint::BTCMint; use crate::mint::subchain_mint::SubChainMint; +use crate::network::HttpTcpChainNetwork; +use crate::stat::StatConfig; +use crate::state_storage::*; use crate::*; +use async_std::sync::Arc; +use cyfs_base::*; +use cyfs_base_meta::*; +use log::*; +use serde::{Deserialize, Serialize}; +use serde_json; +use std::fs::File; +use std::path::{Path, PathBuf}; use std::sync::Mutex; -use crate::stat::StatConfig; pub struct ChainCreator { - reserved: (std::marker::PhantomData, std::marker::PhantomData) + reserved: ( + std::marker::PhantomData, + std::marker::PhantomData, + ), } #[derive(Serialize, Deserialize)] @@ -38,8 +41,12 @@ lazy_static::lazy_static! { } impl ChainCreator { - pub fn create_chain(config_path: &Path, output_path: &Path, new_storage: fn (path: &Path) -> StorageRef) -> BuckyResult { - async_std::task::block_on(async move { + pub fn create_chain( + config_path: &Path, + output_path: &Path, + new_storage: fn(path: &Path) -> StorageRef, + ) -> BuckyResult { + let runner_fut = Box::pin(async move { let config_file = File::open(config_path).map_err(|err| { error!("open file {} failed, err {}", config_path.display(), err); crate::meta_err!(ERROR_NOT_FOUND) @@ -55,99 +62,125 @@ impl ChainCreator { let header = BlockDesc::new(BlockDescContent::new(config.coinbase, None)).build(); let mut block_body = BlockBody::new(); { - let state = storage.create_state(false).await; - state.init_genesis(&config.coins).await?; - state.init().await?; - let meta_config = Config::new(&state)?; - state.create_cycle_event_table(meta_config.get_rent_cycle()).await?; - let state_hash = storage.state_hash().await?; + let state = storage.create_state(false).await; + state.init_genesis(&config.coins).await?; + state.init().await?; + let meta_config = Config::new(&state)?; + state + .create_cycle_event_table(meta_config.get_rent_cycle()) + .await?; + let state_hash = storage.state_hash().await?; - info!("create state_hash:{}", state_hash.to_string()); + info!("create state_hash:{}", state_hash.to_string()); - if config.chain_type.is_none() || config.chain_type.as_ref().unwrap() == "standalone" { + if config.chain_type.is_none() + || config.chain_type.as_ref().unwrap() == "standalone" + { let btc_mint = BTCMint::new(&state, &meta_config, config.bfc_spv_node.as_str()); - if let Ok(coinage_tx) = btc_mint.create_btc_genesis_tx() { - let tx = MetaTx::new(1, TxCaller::Miner(ObjectId::default()), 0, 0, 0 - , None, MetaTxBody::BTCCoinageRecord(coinage_tx), Vec::new()).build(); - block_body.add_transaction(tx).unwrap(); - } - } - else if config.chain_type.as_ref().unwrap() == "bft" { - let miner_key_path = { - let path = PathBuf::from(config.miner_key_path.as_ref().unwrap()); - if path.is_absolute() { - path - } else { - let mut root_path = PathBuf::from(root_path); - root_path.push(path); - root_path - } - }; + if let Ok(coinage_tx) = btc_mint.create_btc_genesis_tx() { + let tx = MetaTx::new( + 1, + TxCaller::Miner(ObjectId::default()), + 0, + 0, + 0, + None, + MetaTxBody::BTCCoinageRecord(coinage_tx), + Vec::new(), + ) + .build(); + block_body.add_transaction(tx).unwrap(); + } + } else if config.chain_type.as_ref().unwrap() == "bft" { + let miner_key_path = { + let path = PathBuf::from(config.miner_key_path.as_ref().unwrap()); + if path.is_absolute() { + path + } else { + let mut root_path = PathBuf::from(root_path); + root_path.push(path); + root_path + } + }; - let miner_group_path = { - let path = PathBuf::from(config.mg_path.as_ref().unwrap()); - if path.is_absolute() { - path - } else { - let mut root_path = PathBuf::from(root_path); - root_path.push(path); - root_path - } - }; + let miner_group_path = { + let path = PathBuf::from(config.mg_path.as_ref().unwrap()); + if path.is_absolute() { + path + } else { + let mut root_path = PathBuf::from(root_path); + root_path.push(path); + root_path + } + }; - let miner_desc_path = { - let path = PathBuf::from(config.miner_desc_path.as_ref().unwrap()); - if path.is_absolute() { - path - } else { - let mut root_path = PathBuf::from(root_path); - root_path.push(path); - root_path - } - }; + let miner_desc_path = { + let path = PathBuf::from(config.miner_desc_path.as_ref().unwrap()); + if path.is_absolute() { + path + } else { + let mut root_path = PathBuf::from(root_path); + root_path.push(path); + root_path + } + }; - let (miner_key, _) = PrivateKey::decode_from_file( - miner_key_path.as_path(), &mut Vec::new())?; - let (miner_group, _) = MinerGroup::decode_from_file( - miner_group_path.as_path(), &mut Vec::new())?; - let (desc, _) = Device::decode_from_file( - miner_desc_path.as_path(), &mut Vec::new())?; + let (miner_key, _) = + PrivateKey::decode_from_file(miner_key_path.as_path(), &mut Vec::new())?; + let (miner_group, _) = + MinerGroup::decode_from_file(miner_group_path.as_path(), &mut Vec::new())?; + let (desc, _) = + Device::decode_from_file(miner_desc_path.as_path(), &mut Vec::new())?; - let meta_create_tx = MetaTxBody::CreateMinerGroup(miner_group); - let mut tx = MetaTx::new(1, - TxCaller::Device(desc.desc().clone()), - 0, - 0, - 0, - None, - meta_create_tx, - Vec::new()).build(); - tx.sign(miner_key.clone())?; - block_body.add_transaction(tx).unwrap(); + let meta_create_tx = MetaTxBody::CreateMinerGroup(miner_group); + let mut tx = MetaTx::new( + 1, + TxCaller::Device(desc.desc().clone()), + 0, + 0, + 0, + None, + meta_create_tx, + Vec::new(), + ) + .build(); + tx.sign(miner_key.clone())?; + block_body.add_transaction(tx).unwrap(); let btc_mint = BTCMint::new(&state, &meta_config, config.bfc_spv_node.as_str()); - if let Ok(coinage_tx) = btc_mint.create_btc_genesis_tx() { - let mut tx = MetaTx::new(2, - TxCaller::Device(desc.desc().clone()), - 0, - 0, - 0, - None, - MetaTxBody::BTCCoinageRecord(coinage_tx), - Vec::new()).build(); - tx.sign(miner_key)?; - block_body.add_transaction(tx).unwrap(); - } - } else if config.chain_type.as_ref().unwrap() == "bft_sub" { - let url = format!("{}/tx_full/{}", config.bfc_spv_node, config.sub_chain_tx.unwrap()); - let tx_full_info = Result::::clone_from_slice(http_get_request(url.as_str()).await?.as_slice())?; + if let Ok(coinage_tx) = btc_mint.create_btc_genesis_tx() { + let mut tx = MetaTx::new( + 2, + TxCaller::Device(desc.desc().clone()), + 0, + 0, + 0, + None, + MetaTxBody::BTCCoinageRecord(coinage_tx), + Vec::new(), + ) + .build(); + tx.sign(miner_key)?; + block_body.add_transaction(tx).unwrap(); + } + } else if config.chain_type.as_ref().unwrap() == "bft_sub" { + let url = format!( + "{}/tx_full/{}", + config.bfc_spv_node, + config.sub_chain_tx.unwrap() + ); + let tx_full_info = Result::::clone_from_slice( + http_get_request(url.as_str()).await?.as_slice(), + )?; if tx_full_info.is_err() { log::error!("get creat tx info failed"); - return Err(meta_err!(*tx_full_info.as_ref().err().unwrap())) + return Err(meta_err!(*tx_full_info.as_ref().err().unwrap())); } let tx_full_info = tx_full_info.unwrap(); - if let MetaTxBody::CreateSubChainAccount(miner_group) = &tx_full_info.tx.desc().content().body.get_obj()[0] { + if let MetaTxBody::CreateSubChainAccount(miner_group) = + &tx_full_info.tx.desc().content().body.get_obj()[0] + { let miner_key_path = { let path = PathBuf::from(config.miner_key_path.as_ref().unwrap()); if path.is_absolute() { @@ -171,33 +204,45 @@ impl ChainCreator { }; let (miner_key, _) = PrivateKey::decode_from_file( - miner_key_path.as_path(), &mut Vec::new())?; - let (desc, _) = Device::decode_from_file( - miner_desc_path.as_path(), &mut Vec::new())?; + miner_key_path.as_path(), + &mut Vec::new(), + )?; + let (desc, _) = + Device::decode_from_file(miner_desc_path.as_path(), &mut Vec::new())?; let meta_create_tx = MetaTxBody::CreateMinerGroup(miner_group.clone()); - let mut tx = MetaTx::new(1, - TxCaller::Device(desc.desc().clone()), - 0, - 0, - 0, - None, - meta_create_tx, - Vec::new()).build(); + let mut tx = MetaTx::new( + 1, + TxCaller::Device(desc.desc().clone()), + 0, + 0, + 0, + None, + meta_create_tx, + Vec::new(), + ) + .build(); tx.sign(miner_key.clone())?; block_body.add_transaction(tx).unwrap(); - let sub_chain_mint = SubChainMint::new(miner_group.desc().calculate_id(), - &state, &meta_config, config.bfc_spv_node.clone()); + let sub_chain_mint = SubChainMint::new( + miner_group.desc().calculate_id(), + &state, + &meta_config, + config.bfc_spv_node.clone(), + ); if let Ok(coinage_tx) = sub_chain_mint.create_genesis_tx().await { - let mut tx = MetaTx::new(2, - TxCaller::Device(desc.desc().clone()), - 0, - 0, - 0, - None, - MetaTxBody::SubChainCoinageRecord(coinage_tx), - Vec::new()).build(); + let mut tx = MetaTx::new( + 2, + TxCaller::Device(desc.desc().clone()), + 0, + 0, + 0, + None, + MetaTxBody::SubChainCoinageRecord(coinage_tx), + Vec::new(), + ) + .build(); tx.sign(miner_key)?; block_body.add_transaction(tx).unwrap(); } @@ -205,38 +250,48 @@ impl ChainCreator { log::error!("tx type error"); return Err(meta_err!(ERROR_EXCEPTION)); } - } + } - // state.being_transaction().await?; - let ret = BlockExecutor::execute_block(&header, - &mut block_body, - &state, - &meta_config, - None, - config.bfc_spv_node.clone(), - None, - ObjectId::default(), None).await; + // state.being_transaction().await?; + let ret = BlockExecutor::execute_block( + &header, + &mut block_body, + &state, + &meta_config, + None, + config.bfc_spv_node.clone(), + None, + ObjectId::default(), + None, + ) + .await; if ret.is_ok() { - // state.commit().await?; - } else { - // state.rollback().await?; - ret?; - } - } + // state.commit().await?; + } else { + // state.rollback().await?; + ret?; + } + } let state_hash = storage.state_hash().await?; info!("create state_hash2:{}", state_hash.to_string()); let mut block = Block::new(config.coinbase, None, state_hash, block_body)?.build(); - let ret: BuckyResult = if config.chain_type.is_none() || config.chain_type.as_ref().unwrap() == "standalone" { - let chain = Chain::new(output_path.to_path_buf(), Some(block), storage, None).await?; + let ret: BuckyResult = if config.chain_type.is_none() + || config.chain_type.as_ref().unwrap() == "standalone" + { + let chain = + Chain::new(output_path.to_path_buf(), Some(block), storage, None).await?; let miner = StandaloneMiner::new( config.coinbase.clone(), config.interval, chain, - config.bfc_spv_node.clone())?; + config.bfc_spv_node.clone(), + )?; Ok(Arc::new(miner)) - } else if config.chain_type.as_ref().unwrap() == "bft" || config.chain_type.as_ref().unwrap() == "bft_sub" { + } else if config.chain_type.as_ref().unwrap() == "bft" + || config.chain_type.as_ref().unwrap() == "bft_sub" + { let miner_key_path = { let path = PathBuf::from(config.miner_key_path.unwrap()); if path.is_absolute() { @@ -247,11 +302,17 @@ impl ChainCreator { root_path } }; - let (miner_key, _) = PrivateKey::decode_from_file( - miner_key_path.as_path(), &mut Vec::new())?; + let (miner_key, _) = + PrivateKey::decode_from_file(miner_key_path.as_path(), &mut Vec::new())?; let public_key = miner_key.public(); - block.sign(miner_key.clone(), &SignatureSource::Key(PublicKeyValue::Single(public_key))).await?; - let chain = Chain::new(output_path.to_path_buf(), Some(block), storage, None).await?; + block + .sign( + miner_key.clone(), + &SignatureSource::Key(PublicKeyValue::Single(public_key)), + ) + .await?; + let chain = + Chain::new(output_path.to_path_buf(), Some(block), storage, None).await?; let miner = BFTMiner::new( "bft".to_owned(), config.coinbase.clone(), @@ -259,31 +320,45 @@ impl ChainCreator { chain, config.bfc_spv_node.clone(), HttpTcpChainNetwork::new(0, Vec::new()), - miner_key)?; + miner_key, + )?; Ok(Arc::new(miner)) } else { - Err(BuckyError::new(BuckyErrorCode::InvalidParam, "InvalidParam")) + Err(BuckyError::new( + BuckyErrorCode::InvalidParam, + "InvalidParam", + )) }; ret - }) + }); + async_std::task::block_on(runner_fut) } - pub fn start_miner_instance(dir: &Path, new_storage: fn (path: &Path) -> StorageRef) -> BuckyResult> { + pub fn start_miner_instance( + dir: &Path, + new_storage: fn(path: &Path) -> StorageRef, + ) -> BuckyResult> { async_std::task::block_on(async move { let config_file = File::open(dir.join("config.json")).map_err(|err| { error!("open config.json at {} failed, err {}", dir.display(), err); - meta_err!(ERROR_NOT_FOUND)})?; + meta_err!(ERROR_NOT_FOUND) + })?; let config: MinerConfig = serde_json::from_reader(config_file).map_err(|err| { error!("invalid config.json, err {}", err); - meta_err!(ERROR_PARAM_ERROR)})?; - let ret: BuckyResult> = if config.chain_type.is_none() || config.chain_type.as_ref().unwrap() == "standalone" { + meta_err!(ERROR_PARAM_ERROR) + })?; + let ret: BuckyResult> = if config.chain_type.is_none() + || config.chain_type.as_ref().unwrap() == "standalone" + { let miner = StandaloneMiner::load( - config.coinbase.clone(), - config.interval, + config.coinbase.clone(), + config.interval, config.bfc_spv_node.clone(), dir, new_storage, - config.stat).await?; + config.stat, + ) + .await?; let miner_ref = Arc::new(miner); let mut miner_lock = MINER.lock().unwrap(); *miner_lock = Some(miner_ref.clone()); @@ -291,7 +366,9 @@ impl ChainCreator { miner_ref.run()?; // let miner_ref: MinerRef = miner_ref; Ok(miner_ref) - } else if config.chain_type.as_ref().unwrap() == "bft" || config.chain_type.as_ref().unwrap() == "bft_sub" { + } else if config.chain_type.as_ref().unwrap() == "bft" + || config.chain_type.as_ref().unwrap() == "bft_sub" + { let miner_key_path = { let path = PathBuf::from(config.miner_key_path.unwrap()); if path.is_absolute() { @@ -302,22 +379,25 @@ impl ChainCreator { root_path } }; - let (miner_key, _) = PrivateKey::decode_from_file( - miner_key_path.as_path(), &mut Vec::new())?; + let (miner_key, _) = + PrivateKey::decode_from_file(miner_key_path.as_path(), &mut Vec::new())?; let mut node_list = Vec::new(); for node in &config.bft_node_list.unwrap() { node_list.push(("unknown".to_owned(), node.clone())) } let network = HttpTcpChainNetwork::new(config.bft_port.unwrap(), node_list); - let miner = BFTMiner::load(config.chain_type.as_ref().unwrap().to_owned(), - config.coinbase.clone(), - config.interval, - config.bfc_spv_node.clone(), - dir, - new_storage, - config.stat, - network, - miner_key).await?; + let miner = BFTMiner::load( + config.chain_type.as_ref().unwrap().to_owned(), + config.coinbase.clone(), + config.interval, + config.bfc_spv_node.clone(), + dir, + new_storage, + config.stat, + network, + miner_key, + ) + .await?; let miner_ref = Arc::new(miner); let mut miner_lock = MINER.lock().unwrap(); *miner_lock = Some(miner_ref.clone()); @@ -325,7 +405,10 @@ impl ChainCreator { log::info!("miner {} startup", config.coinbase.to_string()); Ok(miner_ref) } else { - Err(BuckyError::new(BuckyErrorCode::InvalidParam, "InvalidParam")) + Err(BuckyError::new( + BuckyErrorCode::InvalidParam, + "InvalidParam", + )) }; ret }) @@ -335,10 +418,10 @@ impl ChainCreator { // Ok(Box::new(miner)) } - pub fn start_chain_instance(_dir: &Path, _new_storage: fn (path: &Path) -> StorageRef) -> BuckyResult { + pub fn start_chain_instance( + _dir: &Path, + _new_storage: fn(path: &Path) -> StorageRef, + ) -> BuckyResult { unimplemented!() } } - - - From 9c69afe18450b8be38473ca290111a629261f745 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:13:38 +0800 Subject: [PATCH 437/553] merge from buckyos --- src/component/cyfs-group/Cargo.toml | 2 +- src/component/cyfs-noc/src/blob/file.rs | 1 - src/component/cyfs-stack/Cargo.toml | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 599e13b51..aaab4ed76 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -28,7 +28,7 @@ async-recursion = '1.0' rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } -cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index 13838c174..9417d1377 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -4,7 +4,6 @@ use cyfs_lib::*; use std::borrow::Cow; use std::path::{Path, PathBuf}; -use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 37142e968..d005147ec 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -15,6 +15,7 @@ cyfs-bdt = { path = "../../component/cyfs-bdt" } cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } +cyfs-group = { path = "../../component/cyfs-group" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } From e37b4ee1674e18f44fadbc6a88bb8ea32c25c5ec Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:22:30 +0800 Subject: [PATCH 438/553] rename GroupRPathMgr to GroupManager --- .../src/dec/{rpath_mgr.rs => group_manager.rs} | 4 ++-- src/component/cyfs-group/src/dec/mod.rs | 4 ++-- src/component/cyfs-group/src/network/listener.rs | 6 +++--- src/component/cyfs-stack/src/stack/cyfs_stack.rs | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_mgr.rs => group_manager.rs} (99%) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/group_manager.rs similarity index 99% rename from src/component/cyfs-group/src/dec/rpath_mgr.rs rename to src/component/cyfs-group/src/dec/group_manager.rs index 644fc2fcf..56ef5e7d9 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -34,9 +34,9 @@ struct LocalInfo { } #[derive(Clone)] -pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); +pub struct GroupManager(Arc<(LocalInfo, RwLock)>); -impl GroupRPathMgr { +impl GroupManager { pub fn new( signer: RsaCPUObjectSigner, non_driver: Box, diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index a1f964e95..b4e753a27 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod delegate_factory; mod rpath_client; mod rpath_control; -mod rpath_mgr; +mod group_manager; pub use delegate_factory::*; pub use rpath_client::*; pub use rpath_control::*; -pub use rpath_mgr::*; +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6a6d7b549..e66ef8a43 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; -use crate::{GroupRPathMgr, HotstuffPackage}; +use crate::{GroupManager, HotstuffPackage}; pub struct Listener; impl Listener { pub fn spawn( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { async_std::task::spawn(async move { @@ -20,7 +20,7 @@ impl Listener { async fn run( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { loop { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 96eaad5cf..d208f57cf 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,9 +35,9 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; -use cyfs_group::GroupRPathMgr; +use cyfs_bdt::{DeviceCache, SnStatus, StackGuard}; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; +use cyfs_group::GroupManager; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -105,7 +105,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupRPathMgr, + group_manager: GroupManager, } impl CyfsStackImpl { @@ -431,7 +431,7 @@ impl CyfsStackImpl { config.clone(), ); - let group_manager = GroupRPathMgr::new( + let group_manager = GroupManager::new( signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), @@ -1162,7 +1162,7 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupRPathMgr { + pub fn group_mgr(&self) -> &GroupManager { &self.stack.group_manager } From e107bdff6c9c9ae9a76084a490afe5d64621f5d1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 21:19:34 +0800 Subject: [PATCH 439/553] integrate GroupState, not finish --- .../cyfs-base/src/objects/object_map/mod.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 4 + .../cyfs-group/src/statepath/design.md | 26 +-- .../src/storage/engine/group_state_path.rs | 178 +++++++++++++++ .../cyfs-group/src/storage/engine/mod.rs | 9 + .../src/storage/engine/storage_engine.rs | 23 ++ .../engine/storage_engine_group_state.rs | 207 ++++++++++++++++++ .../storage_engine_mock.rs} | 53 ++--- .../cyfs-group/src/storage/group_storage.rs | 71 +++++- src/component/cyfs-group/src/storage/mod.rs | 4 +- 12 files changed, 524 insertions(+), 70 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs create mode 100644 src/component/cyfs-group/src/storage/engine/mod.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs rename src/component/cyfs-group/src/storage/{storage_engine.rs => engine/storage_engine_mock.rs} (76%) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index be52c2ea5..3bbc5f131 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -2,6 +2,7 @@ mod access; mod cache; mod check; mod diff; +mod isolate_path_env; mod iterator; mod lock; mod object_map; @@ -13,7 +14,6 @@ mod path_iterator; mod root; mod single_env; mod visitor; -mod isolate_path_env; pub use access::*; pub use cache::*; @@ -25,4 +25,5 @@ pub use path::*; pub use path_env::*; pub use path_iterator::*; pub use root::*; +pub use single_env::*; pub use visitor::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ff4e06380..e89498b83 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -18,7 +18,7 @@ use crate::{ consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** @@ -1461,12 +1461,13 @@ impl HotstuffRunner { continue; } - if let Some(ending) = proposal.effective_ending() { - if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.desc().object_id()); - timeout_proposals.push(proposal); - continue; - } + let ending = proposal.effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), + |ending| bucky_time_to_system_time(ending)); + if now >= ending { + remove_proposals.push(proposal.desc().object_id()); + timeout_proposals.push(proposal); + continue; } match self.delegate.on_execute(&proposal, result_state_id).await { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index aa7babc44..1170176b2 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,6 +14,7 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 56ef5e7d9..95c931720 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,6 +6,7 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, @@ -31,6 +32,7 @@ struct LocalInfo { non_driver: Arc>, datagram: DatagramTunnelGuard, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl GroupManager { signer: RsaCPUObjectSigner, non_driver: Box, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); @@ -50,6 +53,7 @@ impl GroupManager { non_driver: Arc::new(non_driver), datagram: datagram.clone(), bdt_stack, + global_state_mgr, }; let raw = GroupRPathMgrRaw { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index b73a46939..7ec71d4d5 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -7,22 +7,18 @@ | |--list-->Set | |--option-->GroupOption | -|--.dec-state // for dec;各Group的dec状态放这里 -| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 -| |--${dec-id} | .group // 一个dec管理的${r-path}状态 -| | | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | -| -|--.link // 区块链结构,记录状态变更链条 -| |--${group-id} -| |--${dec-id} | .group // .group表示group本身的演变共识 +|--${group-id} +| |--${dec-id} +| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 +| | // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-chunk-->Chunk(Group) +| |--group-blob-->BLOB(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs new file mode 100644 index 000000000..4e67d6e1f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/group_state_path.rs @@ -0,0 +1,178 @@ +use cyfs_base::ObjectId; + +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; + +pub struct GroupStatePath { + rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, +} + +impl GroupStatePath { + pub fn new(rpath: String) -> Self { + Self { + rpath, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.rpath.as_str() + } + + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() + } + + pub fn link(&self) -> &str { + self.link.as_str() + } + + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() + } + + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() + } + + pub fn range(&self) -> &str { + self.range.as_str() + } + + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) + } + + pub fn commit_block(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn commit_proposals(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_PROPOSALS, + ]) + } + + pub fn prepares(&self) -> &str { + self.prepares.as_str() + } + + pub fn prepare_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() + } + + pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.pre_commits.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() + } + + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() + } + + pub fn recycle(&self) -> &str { + self.recycle.as_str() + } + + pub fn adding(&self) -> &str { + self.adding.as_str() + } +} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs new file mode 100644 index 000000000..71d5cc49f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -0,0 +1,9 @@ +mod group_state_path; +mod storage_engine; +mod storage_engine_group_state; +mod storage_engine_mock; + +pub(super) use group_state_path::*; +pub(super) use storage_engine::*; +pub(super) use storage_engine_group_state::*; +pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs new file mode 100644 index 000000000..e48e607bc --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -0,0 +1,23 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Send + Sync + Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs new file mode 100644 index 000000000..3aba73e31 --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -0,0 +1,207 @@ +use std::{collections::HashSet, sync::Arc}; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, +}; + +use crate::StatePath; + +use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; + +const ACCESS: Option = None; + +#[derive(Clone)] +pub struct StorageEngineGroupState { + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, +} + +impl StorageEngineGroupState { + pub async fn load( + dec_group_state: ObjectMapRootManagerRef, + state_path: GroupStatePath, + ) -> BuckyResult { + Ok(Self { + state_mgr: todo!(), + state_path: Arc::new(state_path), + }) + } + + pub async fn create_writer(&self) -> BuckyResult { + Ok( + StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) + .await?, + ) + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineGroupState { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + let op_env = self.state_mgr.create_op_env(ACCESS)?; + let block_id = op_env + .get_by_path(self.state_path.commit_block(height).as_str()) + .await?; + block_id.map_or( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), + |block_id| Ok(block_id), + ) + } +} + +#[derive(Clone)] +pub struct StorageEngineGroupStateWriter { + state_mgr: ObjectMapRootManagerRef, + op_env: ObjectMapPathOpEnvRef, + prepare_op_env: ObjectMapSingleOpEnvRef, + prepare_map_id: Option, + state_path: Arc, +} + +impl StorageEngineGroupStateWriter { + async fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; + let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; + match prepare_map_id.as_ref() { + Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, + None => { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await? + } + }; + + Ok(Self { + op_env, + prepare_op_env, + state_path, + state_mgr, + prepare_map_id, + }) + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; + new_prepare + .create_new(ObjectMapSimpleContentType::Map) + .await?; + new_prepare + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + let new_prepare_block = new_prepare.commit().await?; + + self.prepare_op_env + .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .await + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str()) + .await? + .is_some() + { + assert!(false); + } + + // TODO + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineGroupStateWriter<'a> { + fn drop(&mut self) {} +} diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs similarity index 76% rename from src/component/cyfs-group/src/storage/storage_engine.rs rename to src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b9376618b..6208b0680 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -2,28 +2,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -#[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; - async fn push_proposals( - &mut self, - proposal_ids: &[ObjectId], - timestamp: u64, - ) -> BuckyResult<()>; - - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; -} - -#[async_trait::async_trait] -pub trait StorageEngine { - async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult; - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; -} +use super::{StorageEngine, StorageWriter}; struct StorageEngineMockFinishProposalMgr { flip_timestamp: u64, @@ -58,6 +37,10 @@ impl StorageEngineMock { }, } } + + pub async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) + } } #[async_trait::async_trait] @@ -69,19 +52,15 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult { - Ok(StorageEngineMockWriter { engine: self }) - } - - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { - let is_finished = self - .finish_proposals - .adding - .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) - .is_some(); - Ok(is_finished) - } + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + // let is_finished = self + // .finish_proposals + // .adding + // .get(proposal_id) + // .or(self.finish_proposals.over.get(proposal_id)) + // .is_some(); + // Ok(is_finished) + // } } pub struct StorageEngineMockWriter<'a> { @@ -164,9 +143,9 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: u64, + timestamp: Option, ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + if let Some(timestamp) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 440613f51..bc9fc6009 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, time::SystemTime}; +use std::{ + collections::{HashMap, HashSet}, + time::SystemTime, +}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, @@ -6,10 +9,13 @@ use cyfs_base::{ }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; + +use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; +use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; -use super::{storage_engine::StorageEngineMock, StorageEngine}; +const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; pub enum BlockLinkState { Expired, @@ -23,6 +29,12 @@ pub enum BlockLinkState { InvalidBranch, } +struct FinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -39,6 +51,8 @@ pub struct GroupStorage { prepares: HashMap, pre_commits: HashMap, + finish_proposals: FinishProposalMgr, + storage_engine: StorageEngineMock, } @@ -50,11 +64,19 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + // let group_state = root_state_mgr + // .load_root_state(group_id, Some(group_id.clone()), true) + // .await? + // .expect("create group state failed."); + + // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + Ok(Self { group, group_id: group_id.clone(), @@ -70,6 +92,11 @@ impl GroupStorage { pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), local_device_id, + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, }) } @@ -78,6 +105,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -240,10 +268,17 @@ impl GroupStorage { .iter() .map(|p| p.proposal.clone()) .collect(); - writer.push_proposals( - finish_proposals.as_slice(), - new_header.named_object().desc().create_time(), - ); + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + writer + .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } // update memory @@ -276,6 +311,20 @@ impl GroupStorage { if self.first_block.is_none() { self.first_block = self.header_block.clone(); } + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.finish_proposals.over); + self.finish_proposals.flip_timestamp = timestamp; + } + + for proposal in new_header.proposals() { + let is_new = self.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -551,7 +600,13 @@ impl GroupStorage { // find in storage - self.storage_engine.is_proposal_finished(proposal_id).await + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d95cf7ddd..d4440419e 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,7 @@ mod dec_storage; +mod engine; mod group_storage; -mod storage_engine; pub use dec_storage::*; +use engine::*; pub use group_storage::*; -pub(crate) use storage_engine::*; From 33d229d66d8a45ec297b9ae9d900903b89a26e8c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 17:28:17 +0800 Subject: [PATCH 440/553] integrate GroupState update --- .../cyfs-group/src/statepath/design.md | 11 +- .../src/statepath/group_statepath.rs | 257 +++++------- .../src/storage/engine/group_state_path.rs | 178 --------- .../cyfs-group/src/storage/engine/mod.rs | 2 - .../src/storage/engine/storage_engine.rs | 17 +- .../engine/storage_engine_group_state.rs | 367 +++++++++++++----- .../src/storage/engine/storage_engine_mock.rs | 30 +- .../cyfs-group/src/storage/group_storage.rs | 30 +- .../cyfs-stack/src/stack/cyfs_stack.rs | 1 + 9 files changed, 439 insertions(+), 454 deletions(-) delete mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 7ec71d4d5..70a61e428 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -25,15 +25,10 @@ | |--last-vote-round-->u64 // 最后一次投票的轮次 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height}) -| | |--block-->GroupConsensusBlock +| |--str(${height})->block | | -| |--prepares // Prepare状态的block -| | |--${block.id} -| | |--block -| |--pre-commits // pre-commit状态的block -| | |--${block.id} -| | |--block +| |--prepares->Set // Prepare状态的block +| |--pre-commits->Set // pre-commit状态的block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index c0daef478..eade0f9e4 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,19 +1,17 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; -pub const STATEPATH_SEPARATOR: &str = "/"; - -pub const STATEPATH_GROUPS: &str = "groups"; - -pub const STATEPATH_DEC_STATE: &str = ".dec-state"; - -pub const STATEPATH_LINK: &str = ".link"; -pub const STATEPATH_GROUP_HASH: &str = "group-hash"; -pub const STATEPATH_USERS: &str = "users"; -pub const STATEPATH_USERS_NONCE: &str = "nonce"; -pub const STATEPATH_RANGE: &str = "range"; -pub const STATEPATH_BLOCK: &str = "block"; - -pub const STATEPATH_RPATHS: &str = ".r-paths"; +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; @@ -23,180 +21,131 @@ lazy_static::lazy_static! { pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } -pub struct StatePath { - group_id: ObjectId, - group_id_str: String, - dec_id: ObjectId, - dec_id_str: String, +pub struct GroupStatePath { rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, } -impl StatePath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { +impl GroupStatePath { + pub fn new(rpath: String) -> Self { Self { - group_id_str: group_id.to_string(), - group_id, - dec_id_str: dec_id.to_string(), - dec_id, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), rpath, } } pub fn join(fields: &[&str]) -> String { - fields.join(STATEPATH_SEPARATOR) - } - - pub fn dec_state() -> String { - STATEPATH_DEC_STATE.to_string() - } - - pub fn dec_state_group(&self) -> String { - Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) - } - - pub fn dec_state_dec(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + fields.join(STATE_PATH_SEPARATOR) } - pub fn dec_state_rpath(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn root(&self) -> &str { + self.rpath.as_str() } - pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - sub_path, - ]) + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() } - pub fn link() -> String { - STATEPATH_LINK.to_string() + pub fn link(&self) -> &str { + self.link.as_str() } - pub fn link_group(&self) -> String { - Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() } - pub fn link_dec(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() } - pub fn link_rpath(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn range(&self) -> &str { + self.range.as_str() } - pub fn link_group_hash(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_GROUP_HASH, - ]) + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) } - pub fn link_users(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - ]) + pub fn prepares(&self) -> &str { + self.prepares.as_str() } - pub fn link_user(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - ]) + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() } - pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - STATEPATH_USERS_NONCE, - ]) + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() } - pub fn link_range(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_RANGE, - ]) - } - - pub fn link_height(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - ]) - } - - pub fn link_block(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - STATEPATH_BLOCK, - ]) - } - - pub fn rpaths(&self) -> String { - STATEPATH_RPATHS.to_string() - } -} - -pub struct GroupUpdateStatePath; - -impl GroupUpdateStatePath { - pub fn latest_version() -> &'static str { - STATEPATH_GROUP_DEC_LATEST_VERSION + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() } - pub fn version_seq(version_seq: u64) -> String { - version_seq.to_string() + pub fn recycle(&self) -> &str { + self.recycle.as_str() } - pub fn group_hash(group_hash: &ObjectId) -> String { - group_hash.to_string() + pub fn adding(&self) -> &str { + self.adding.as_str() } } diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs deleted file mode 100644 index 4e67d6e1f..000000000 --- a/src/component/cyfs-group/src/storage/engine/group_state_path.rs +++ /dev/null @@ -1,178 +0,0 @@ -use cyfs_base::ObjectId; - -pub const STATE_PATH_SEPARATOR: &str = "/"; -pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; -pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; -pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; -pub const GROUP_STATE_PATH_RANGE: &str = "range"; -pub const GROUP_STATE_PATH_BLOCK: &str = "block"; -pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; -pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; -pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; -pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; -pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; -pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; -pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; -pub const GROUP_STATE_PATH_ADDING: &str = "adding"; - -pub struct GroupStatePath { - rpath: String, - dec_state: String, - link: String, - group_blob: String, - last_vote_round: String, - range: String, - prepares: String, - pre_commits: String, - finish_proposals: String, - flip_time: String, - recycle: String, - adding: String, -} - -impl GroupStatePath { - pub fn new(rpath: String) -> Self { - Self { - rpath, - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, - ]), - last_vote_round: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, - ]), - range: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_RANGE, - ]), - prepares: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PREPARES, - ]), - pre_commits: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PRE_COMMITS, - ]), - finish_proposals: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - ]), - flip_time: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_FLIP_TIME, - ]), - recycle: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_RECYCLE, - ]), - adding: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_ADDING, - ]), - } - } - - pub fn join(fields: &[&str]) -> String { - fields.join(STATE_PATH_SEPARATOR) - } - - pub fn root(&self) -> &str { - self.rpath.as_str() - } - - pub fn dec_state(&self) -> &str { - self.dec_state.as_str() - } - - pub fn link(&self) -> &str { - self.link.as_str() - } - - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() - } - - pub fn last_vote_round(&self) -> &str { - self.last_vote_round.as_str() - } - - pub fn range(&self) -> &str { - self.range.as_str() - } - - pub fn commit_height(&self, height: u64) -> String { - Self::join(&[self.link.as_str(), height.to_string().as_str()]) - } - - pub fn commit_block(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn commit_proposals(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_PROPOSALS, - ]) - } - - pub fn prepares(&self) -> &str { - self.prepares.as_str() - } - - pub fn prepare_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.prepares.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn pre_commits(&self) -> &str { - self.pre_commits.as_str() - } - - pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.pre_commits.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn finish_proposals(&self) -> &str { - self.finish_proposals.as_str() - } - - pub fn flip_time(&self) -> &str { - self.flip_time.as_str() - } - - pub fn recycle(&self) -> &str { - self.recycle.as_str() - } - - pub fn adding(&self) -> &str { - self.adding.as_str() - } -} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs index 71d5cc49f..c185cb24c 100644 --- a/src/component/cyfs-group/src/storage/engine/mod.rs +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -1,9 +1,7 @@ -mod group_state_path; mod storage_engine; mod storage_engine_group_state; mod storage_engine_mock; -pub(super) use group_state_path::*; pub(super) use storage_engine::*; pub(super) use storage_engine_group_state::*; pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e48e607bc..e19c46b81 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,19 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { +pub trait StorageWriter: Send + Sync { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()>; async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()>; - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + + async fn commit(mut self) -> BuckyResult<()>; } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 3aba73e31..731725e95 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use crate::StatePath; +use crate::{ + GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, +}; -use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; +use super::{StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -41,7 +44,7 @@ impl StorageEngine for StorageEngineGroupState { async fn find_block_by_height(&self, height: u64) -> BuckyResult { let op_env = self.state_mgr.create_op_env(ACCESS)?; let block_id = op_env - .get_by_path(self.state_path.commit_block(height).as_str()) + .get_by_path(self.state_path.commit_height(height).as_str()) .await?; block_id.map_or( Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), @@ -57,6 +60,7 @@ pub struct StorageEngineGroupStateWriter { prepare_op_env: ObjectMapSingleOpEnvRef, prepare_map_id: Option, state_path: Arc, + write_result: BuckyResult<()>, } impl StorageEngineGroupStateWriter { @@ -65,16 +69,20 @@ impl StorageEngineGroupStateWriter { state_path: Arc, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; - let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; - match prepare_map_id.as_ref() { - Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, - None => { - prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await? - } - }; + let prepare_map_id = + if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { + if err.code() == BuckyErrorCode::NotFound { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + None + } else { + return Err(err); + } + } else { + prepare_op_env.get_current_root().await + }; Ok(Self { op_env, @@ -82,126 +90,299 @@ impl StorageEngineGroupStateWriter { state_path, state_mgr, prepare_map_id, + write_result: Ok(()), }) } -} - -#[async_trait::async_trait] -impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { - let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; - new_prepare - .create_new(ObjectMapSimpleContentType::Map) - .await?; - new_prepare - .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) - .await?; - let new_prepare_block = new_prepare.commit().await?; + async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { self.prepare_op_env - .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .insert(block_id) .await + .map(|is_changed| assert!(is_changed)) } - async fn insert_pre_commit( + async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, is_instead: bool, ) -> BuckyResult<()> { - if !self - .prepare_op_env - .remove_with_key(block_id.to_string().as_str()) - .await? - .is_some() - { - assert!(false); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); - // TODO if is_instead { - self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); - } else { - if !self.engine.pre_commit_blocks.insert(block_id.clone()) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block pre-commit twice", - )); - } + self.op_env + .remove_with_path(self.state_path.pre_commits(), &None) + .await?; } - Ok(()) + self.op_env + .insert_with_path(self.state_path.pre_commits(), block_id) + .await } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if self - .engine - .commit_blocks - .insert(height, block_id.clone()) - .is_some() - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block commit twice", - )); - } + async fn push_commit_inner( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.op_env + .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) + .await?; - self.engine.block_height_range.1 = height; + let range_obj = make_range_obj(min_height, height); + if height == 1 { + self.op_env + .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) + .await?; + } else { + let prev_range = make_range_obj(min_height, height - 1); + let prev_value = self + .op_env + .set_with_key( + self.state_path.link(), + GROUP_STATE_PATH_RANGE, + &range_obj, + &Some(prev_range), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_range); + }; + + // update state from dec-app + if result_state_id == prev_result_state_id { + return Ok(()); + } else { + match result_state_id { + Some(result_state_id) => { + if prev_result_state_id.is_none() { + self.op_env + .insert_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + ) + .await?; + } else { + let prev_value = self + .op_env + .set_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + prev_result_state_id, + false, + ) + .await?; + assert_eq!(&prev_value, prev_result_state_id); + } + } + None => { + self.op_env + .remove_with_path(self.state_path.dec_state(), prev_result_state_id) + .await?; + } + } + } Ok(()) } - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - if !self.engine.prepare_blocks.remove(block_id) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "try remove prepare not exists", - )); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); } Ok(()) } - async fn push_proposals( + async fn push_proposals_inner( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); - self.engine.finish_proposals.flip_timestamp = timestamp; + if proposal_ids.is_empty() { + return Ok(()); } - for proposal_id in proposal_ids { - if !self - .engine - .finish_proposals - .adding - .insert(proposal_id.clone()) - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "dup finish proposal", - )); + let add_single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + + if let Some((timestamp, prev_timestamp)) = timestamp { + let new_over = self + .op_env + .remove_with_path(self.state_path.adding(), &None) + .await?; + + if let Some(new_over) = new_over.as_ref() { + self.op_env + .set_with_path(self.state_path.recycle(), new_over, &None, true) + .await?; } + + let timestamp_obj = make_u64_obj(timestamp); + if prev_timestamp != 0 { + let prev_timestamp_obj = make_u64_obj(prev_timestamp); + let prev_value = self + .op_env + .set_with_path( + self.state_path.flip_time(), + ×tamp_obj, + &Some(prev_timestamp_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_timestamp_obj); + } else { + self.op_env + .insert_with_key( + self.state_path.finish_proposals(), + GROUP_STATE_PATH_FLIP_TIME, + ×tamp_obj, + ) + .await?; + } + + add_single_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + } else { + add_single_op_env + .load_by_path(self.state_path.adding()) + .await?; } + for proposal_id in proposal_ids { + let is_new = add_single_op_env.insert(proposal_id).await?; + assert!(is_new); + } + let adding_set_id = add_single_op_env.commit().await?; + let prev_value = self + .op_env + .set_with_path(self.state_path.adding(), &adding_set_id, &None, true) + .await?; + Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - self.engine.last_vote_round = round; + async fn set_last_vote_round_inner(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert!(round > prev_value); + if round == prev_value { + return Ok(()); + } - Ok(()) + let round_obj = make_u64_obj(round); + + if prev_value == 0 { + self.op_env + .insert_with_path(self.state_path.last_vote_round(), &round_obj) + .await + } else { + let prev_obj = make_u64_obj(prev_value); + let prev_value = self + .op_env + .set_with_path( + self.state_path.last_vote_round(), + &round_obj, + &Some(prev_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_obj); + Ok(()) + } + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result.clone() + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result.clone() + } + + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self + .push_commit_inner( + height, + block_id, + result_state_id, + prev_result_state_id, + min_height, + ) + .await; + self.write_result.clone() + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.remove_prepares_inner(block_ids).await; + self.write_result.clone() + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.push_proposals_inner(proposal_ids, timestamp).await; + self.write_result.clone() + } + + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.set_last_vote_round_inner(round, prev_value).await; + self.write_result.clone() + } + + async fn commit(mut self) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + + let prepare_map_id = self.prepare_op_env.commit().await?; + self.op_env + .set_with_path( + self.state_path.prepares(), + &prepare_map_id, + &self.prepare_map_id, + self.prepare_map_id.is_none(), + ) + .await?; + self.op_env.commit().await.map(|_| ()) } } -impl<'a> Drop for StorageEngineGroupStateWriter<'a> { - fn drop(&mut self) {} +fn make_range_obj(min: u64, max: u64) -> ObjectId { + let mut range_buf = [0u8; 24]; + let (low, high) = range_buf.split_at_mut(12); + low.copy_from_slice(&min.to_le_bytes()); + high.copy_from_slice(&max.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() +} + +fn make_u64_obj(value: u64) -> ObjectId { + let mut range_buf = [0u8; 8]; + range_buf.copy_from_slice(&value.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 6208b0680..b944d3735 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -13,6 +13,7 @@ struct StorageEngineMockFinishProposalMgr { pub struct StorageEngineMock { last_vote_round: u64, + result_state_id: Option, block_height_range: (u64, u64), commit_blocks: HashMap, @@ -30,6 +31,7 @@ impl StorageEngineMock { commit_blocks: HashMap::new(), prepare_blocks: HashSet::new(), pre_commit_blocks: HashSet::new(), + result_state_id: None, finish_proposals: StorageEngineMockFinishProposalMgr { flip_timestamp: 0, over: HashSet::new(), @@ -108,7 +110,18 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + assert!(height > min_height); + assert_eq!(height, self.engine.block_height_range.1 + 1); + assert_eq!(prev_result_state_id, &self.engine.result_state_id); + if self .engine .commit_blocks @@ -123,6 +136,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } self.engine.block_height_range.1 = height; + self.engine.result_state_id = result_state_id.clone(); Ok(()) } @@ -143,12 +157,13 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if let Some(timestamp) = timestamp { + if let Some((timestamp, prev_timestamp)) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + assert_eq!(prev_timestamp, self.engine.finish_proposals.flip_timestamp); self.engine.finish_proposals.flip_timestamp = timestamp; } @@ -170,13 +185,14 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert_eq!(self.engine.last_vote_round, prev_value); self.engine.last_vote_round = round; Ok(()) } -} -impl<'a> Drop for StorageEngineMockWriter<'a> { - fn drop(&mut self) {} + async fn commit(mut self) -> BuckyResult<()> { + Ok(()) + } } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index bc9fc6009..a7284f403 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -13,7 +13,7 @@ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; +use super::{engine::StorageEngineMock, StorageEngine}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -42,15 +42,14 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, + group_chunk_id: ObjectId, dec_state_id: Option, // commited/header state id - group_chunk_id: ObjectId, last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, prepares: HashMap, pre_commits: HashMap, - finish_proposals: FinishProposalMgr, storage_engine: StorageEngineMock, @@ -258,7 +257,15 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit(new_header.height(), new_header.block_id().object_id()) + .push_commit( + new_header.height(), + new_header.block_id().object_id(), + new_header.result_state_id(), + self.header_block + .as_ref() + .map_or(&None, |b| b.result_state_id()), + self.first_block.as_ref().map_or(0, |b| b.height()), + ) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -272,7 +279,10 @@ impl GroupStorage { let timestamp = new_header.named_object().desc().create_time(); if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer - .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.finish_proposals.flip_timestamp)), + ) .await?; } else { writer @@ -281,6 +291,8 @@ impl GroupStorage { } } + writer.commit().await?; + // update memory if self .prepares @@ -293,7 +305,6 @@ impl GroupStorage { match new_header { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); - self.header_block = Some(new_header); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); self.prepares.remove(&new_pre_commit.0); @@ -309,7 +320,7 @@ impl GroupStorage { } if self.first_block.is_none() { - self.first_block = self.header_block.clone(); + self.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); @@ -325,6 +336,7 @@ impl GroupStorage { assert!(is_new); } + self.header_block = Some(new_header); return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -359,7 +371,9 @@ impl GroupStorage { // storage let mut writer = self.storage_engine.create_writer().await?; - writer.set_last_vote_round(round).await?; + writer + .set_last_vote_round(round, self.last_vote_round) + .await?; self.last_vote_round = round; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index d208f57cf..8cf9bcad0 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -435,6 +435,7 @@ impl CyfsStackImpl { signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), + global_state_manager.clone_processor(), )?; let mut stack = Self { From 09b6a6701dbabf747cceb355fec03f1150c98524 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 20:15:19 +0800 Subject: [PATCH 441/553] integrate GroupState load --- .../cyfs-group/src/dec/group_manager.rs | 12 +- .../src/storage/engine/storage_engine.rs | 37 ++++ .../engine/storage_engine_group_state.rs | 180 ++++++++++++++-- .../cyfs-group/src/storage/group_storage.rs | 198 ++++++++++-------- 4 files changed, 327 insertions(+), 100 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95c931720..5ecfcdba2 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -372,6 +372,7 @@ impl GroupManager { let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -379,7 +380,15 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; + let store = GroupStorage::load( + group_id, + dec_id, + rpath, + non_driver.clone(), + local_device_id.object_id().clone(), + &root_state_mgr, + ) + .await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -430,6 +439,7 @@ impl GroupManager { init_state, non_driver.clone(), local_device_id.object_id().clone(), + &root_state_mgr, ) .await? } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e19c46b81..735277a3a 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,4 +1,41 @@ +use std::collections::{HashMap, HashSet}; + use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct FinishProposalMgr { + pub flip_timestamp: u64, + pub over: HashSet, + pub adding: HashSet, +} + +pub struct StorageCacheInfo { + pub dec_state_id: Option, // commited/header state id + pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub header_block: Option, + pub first_block: Option, + pub prepares: HashMap, + pub pre_commits: HashMap, + pub finish_proposals: FinishProposalMgr, +} + +impl StorageCacheInfo { + pub fn new(init_state_id: Option) -> Self { + Self { + dec_state_id: init_state_id, + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 731725e95..ee429a78f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,16 +1,18 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, - ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, + ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_RANGE, }; -use super::{StorageEngine, StorageWriter}; +use super::{StorageCacheInfo, StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -21,14 +23,110 @@ pub struct StorageEngineGroupState { } impl StorageEngineGroupState { - pub async fn load( - dec_group_state: ObjectMapRootManagerRef, - state_path: GroupStatePath, - ) -> BuckyResult { - Ok(Self { - state_mgr: todo!(), + pub(crate) async fn load_cache( + state_mgr: &ObjectMapRootManagerRef, + non_driver: &NONDriverHelper, + state_path: &GroupStatePath, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; + + let last_vote_round = op_env + .get_by_path(state_path.last_vote_round()) + .await? + .map(|id| parse_u64_obj(&id)); + + let mut first_header_block_ids: Vec = vec![]; + let commit_range = op_env + .get_by_path(state_path.range()) + .await? + .map(|id| parse_range_obj(&id)); + let commit_block = match commit_range { + Some((first_height, header_height)) => { + let first_block_id = op_env + .get_by_path(state_path.commit_height(first_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(first_block_id); + + if header_height == first_height { + Some((first_block_id, first_block_id)) + } else { + let header_block_id = op_env + .get_by_path(state_path.commit_height(header_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(header_block_id); + Some((first_block_id, header_block_id)) + } + } + None => None, + }; + + let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let pre_commit_block_ids = + load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + + let flip_timestamp = op_env + .get_by_path(state_path.flip_time()) + .await? + .map_or(0, |id| parse_u64_obj(&id)); + + let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; + let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + + let load_block_ids = [ + first_header_block_ids.as_slice(), + prepare_block_ids.as_slice(), + pre_commit_block_ids.as_slice(), + ] + .concat(); + + let load_blocks = futures::future::join_all( + load_block_ids + .iter() + .map(|id| non_driver.get_block(id, None)), + ) + .await; + + let mut cache = StorageCacheInfo::new(dec_state_id); + cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); + cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); + cache.finish_proposals.flip_timestamp = flip_timestamp; + + let prepare_block_pos = match commit_block { + Some((first_block_id, header_block_id)) => { + cache.first_block = Some(load_blocks.get(0).unwrap().clone()?); + if header_block_id == first_block_id { + cache.header_block = cache.first_block.clone(); + 1 + } else { + cache.header_block = Some(load_blocks.get(1).unwrap().clone()?); + 2 + } + } + None => 0, + }; + + let (prepare_blocks, pre_commit_blocks) = + load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); + for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { + cache.prepares.insert(block_id, block.clone()?); + } + for (block, block_id) in pre_commit_blocks.iter().zip(pre_commit_block_ids) { + cache.pre_commits.insert(block_id, block.clone()?); + } + + Ok(cache) + } + + pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + Self { + state_mgr, state_path: Arc::new(state_path), - }) + } } pub async fn create_writer(&self) -> BuckyResult { @@ -132,12 +230,14 @@ impl StorageEngineGroupStateWriter { .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) .await?; - let range_obj = make_range_obj(min_height, height); if height == 1 { + let range_obj = make_range_obj(1, height); self.op_env .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) .await?; } else { + assert!(min_height < height); + let range_obj = make_range_obj(min_height, height); let prev_range = make_range_obj(min_height, height - 1); let prev_value = self .op_env @@ -376,13 +476,63 @@ impl StorageWriter for StorageEngineGroupStateWriter { fn make_range_obj(min: u64, max: u64) -> ObjectId { let mut range_buf = [0u8; 24]; let (low, high) = range_buf.split_at_mut(12); - low.copy_from_slice(&min.to_le_bytes()); - high.copy_from_slice(&max.to_le_bytes()); + low[..8].copy_from_slice(&min.to_le_bytes()); + high[..8].copy_from_slice(&max.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } +fn parse_range_obj(obj: &ObjectId) -> (u64, u64) { + let range_buf = obj.data(); + assert_eq!(range_buf.len(), 24); + let (low_buf, high_buf) = range_buf.split_at(12); + let mut low = [0u8; 8]; + low.copy_from_slice(&low_buf[..8]); + let mut high = [0u8; 8]; + high.copy_from_slice(&high_buf[..8]); + + (u64::from_le_bytes(low), u64::from_le_bytes(high)) +} + fn make_u64_obj(value: u64) -> ObjectId { let mut range_buf = [0u8; 8]; range_buf.copy_from_slice(&value.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } + +fn parse_u64_obj(obj: &ObjectId) -> u64 { + let mut buf = [0u8; 8]; + buf.copy_from_slice(obj.data()); + u64::from_le_bytes(buf) +} + +async fn load_object_ids_with_path( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Set(id) => object_ids.push(id.clone()), + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a7284f403..5ad19ea15 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -11,9 +11,14 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::GlobalStateManagerRawProcessorRef; -use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; +use crate::{ + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, +}; -use super::{engine::StorageEngineMock, StorageEngine}; +use super::{ + engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + StorageEngine, +}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -29,12 +34,6 @@ pub enum BlockLinkState { InvalidBranch, } -struct FinishProposalMgr { - flip_timestamp: u64, - over: HashSet, - adding: HashSet, -} - pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -44,15 +43,9 @@ pub struct GroupStorage { non_driver: NONDriverHelper, group_chunk_id: ObjectId, - dec_state_id: Option, // commited/header state id - last_vote_round: u64, // 参与投票的最后一个轮次 - header_block: Option, - first_block: Option, - prepares: HashMap, - pre_commits: HashMap, - finish_proposals: FinishProposalMgr, + cache: StorageCacheInfo, - storage_engine: StorageEngineMock, + storage_engine: StorageEngineGroupState, } impl GroupStorage { @@ -63,18 +56,18 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); - // let group_state = root_state_mgr - // .load_root_state(group_id, Some(group_id.clone()), true) - // .await? - // .expect("create group state failed."); + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); - // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; Ok(Self { group, @@ -82,20 +75,13 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - dec_state_id: init_state_id, group_chunk_id: group_chunk_id.object_id(), - last_vote_round: 0, - header_block: None, - first_block: None, - prepares: HashMap::new(), - pre_commits: HashMap::new(), - storage_engine: StorageEngineMock::new(), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + GroupStatePath::new(rpath.to_string()), + ), local_device_id, - finish_proposals: FinishProposalMgr { - flip_timestamp: 0, - over: HashSet::new(), - adding: HashSet::new(), - }, + cache: StorageCacheInfo::new(init_state_id), }) } @@ -104,37 +90,62 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - // unimplemented!() - Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); + + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + + let state_path = GroupStatePath::new(rpath.to_string()); + let cache = + StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + group_chunk_id: group_chunk_id.object_id(), + storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + local_device_id, + cache: cache, + }) } pub fn header_block(&self) -> &Option { - &self.header_block + &self.cache.header_block } pub fn header_round(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.round()) + self.cache.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.height()) + self.cache.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - &self.first_block + &self.cache.first_block } pub fn prepares(&self) -> &HashMap { - &self.prepares + &self.cache.prepares } pub fn pre_commits(&self) -> &HashMap { - &self.pre_commits + &self.cache.pre_commits } pub fn group(&self) -> &Group { @@ -146,34 +157,37 @@ impl GroupStorage { } pub fn dec_state_id(&self) -> &Option { - &self.dec_state_id + &self.cache.dec_state_id } pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { let header_height = self.header_height(); let block = match height.cmp(&header_height) { std::cmp::Ordering::Less => { - if height == self.first_block.as_ref().map_or(0, |b| b.height()) { - self.first_block.clone() + if height == self.cache.first_block.as_ref().map_or(0, |b| b.height()) { + self.cache.first_block.clone() } else { // find in storage let block_id = self.storage_engine.find_block_by_height(height).await?; Some(self.non_driver.get_block(&block_id, None).await?) } } - std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Equal => self.cache.header_block.clone(), std::cmp::Ordering::Greater => { if height == header_height + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.height() == height) .or(self + .cache .prepares .iter() .find(|(_, block)| block.height() == height)) .map(|(_, block)| block.clone()) } else if height == header_height + 2 { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.height() == height) .map(|(_, block)| block.clone()) @@ -202,16 +216,17 @@ impl GroupStorage { // prepare update memory if let Some(prev_block_id) = prev_block_id { - if let Some(prev_block) = self.prepares.get(prev_block_id) { + if let Some(prev_block) = self.cache.prepares.get(prev_block_id) { new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); if let Some(prev_prev_block_id) = prev_block.prev_block_id() { - if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + if let Some(prev_prev_block) = self.cache.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); assert_eq!( prev_prev_block.prev_block_id(), - self.header_block + self.cache + .header_block .as_ref() .map(|b| b.block_id().object_id().clone()) .as_ref() @@ -220,7 +235,7 @@ impl GroupStorage { new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.block_id().object_id(); - for (id, block) in self.prepares.iter() { + for (id, block) in self.cache.prepares.iter() { if block.prev_block_id().map(|prev_id| { assert_ne!(prev_id, prev_block_id); prev_id == new_header_id @@ -261,10 +276,11 @@ impl GroupStorage { new_header.height(), new_header.block_id().object_id(), new_header.result_state_id(), - self.header_block + self.cache + .header_block .as_ref() .map_or(&None, |b| b.result_state_id()), - self.first_block.as_ref().map_or(0, |b| b.height()), + self.cache.first_block.as_ref().map_or(0, |b| b.height()), ) .await?; @@ -277,11 +293,11 @@ impl GroupStorage { .collect(); let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer .push_proposals( finish_proposals.as_slice(), - Some((timestamp, self.finish_proposals.flip_timestamp)), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), ) .await?; } else { @@ -295,6 +311,7 @@ impl GroupStorage { // update memory if self + .cache .prepares .insert(block_id.object_id().clone(), block) .is_some() @@ -304,53 +321,60 @@ impl GroupStorage { match new_header { Some(new_header) => { - self.dec_state_id = new_header.result_state_id().clone(); + self.cache.dec_state_id = new_header.result_state_id().clone(); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); - self.prepares.remove(&new_pre_commit.0); + self.cache.prepares.remove(&new_pre_commit.0); let mut removed_blocks = HashMap::from([new_pre_commit]); - std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + std::mem::swap(&mut self.cache.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = removed_blocks.into_values().collect(); for id in remove_prepares.iter() { - removed_blocks.push(self.prepares.remove(id).unwrap()); + removed_blocks.push(self.cache.prepares.remove(id).unwrap()); } - if self.first_block.is_none() { - self.first_block = Some(new_header.clone()); + if self.cache.first_block.is_none() { + self.cache.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MS + { let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.finish_proposals.over); - self.finish_proposals.flip_timestamp = timestamp; + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; } for proposal in new_header.proposals() { - let is_new = self.finish_proposals.adding.insert(proposal.proposal); + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); assert!(is_new); } - self.header_block = Some(new_header); - return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + self.cache.header_block = Some(new_header); + return Ok(Some(( + self.cache.header_block.as_ref().unwrap(), + removed_blocks, + ))); } None => { if let Some(new_pre_commit) = new_pre_commit { assert!(remove_prepares.is_empty()); if self + .cache .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) .is_some() { assert!(false); } - self.prepares + self.cache + .prepares .remove(&new_pre_commit.0) .expect("any block in pre-commit should be from prepare"); } @@ -361,21 +385,21 @@ impl GroupStorage { } pub fn last_vote_round(&self) -> u64 { - self.last_vote_round + self.cache.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - if round <= self.last_vote_round { + if round <= self.cache.last_vote_round { return Ok(()); } // storage let mut writer = self.storage_engine.create_writer().await?; writer - .set_last_vote_round(round, self.last_vote_round) + .set_last_vote_round(round, self.cache.last_vote_round) .await?; - self.last_vote_round = round; + self.cache.last_vote_round = round; Ok(()) } @@ -533,15 +557,16 @@ impl GroupStorage { } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { - if let Some(block) = self.header_block.as_ref() { + if let Some(block) = self.cache.header_block.as_ref() { if block.block_id().object_id() == block_id { return Ok(block.clone()); } } - self.prepares + self.cache + .prepares .get(block_id) - .or(self.pre_commits.get(block_id)) + .or(self.cache.pre_commits.get(block_id)) .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) .map(|block| block.clone()) } @@ -553,20 +578,24 @@ impl GroupStorage { std::cmp::Ordering::Less => { return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Equal => self.cache.header_block.as_ref(), std::cmp::Ordering::Greater => if round == header_round + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .prepares .iter() .find(|(_, block)| block.round() == round)) } else { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .pre_commits .iter() .find(|(_, block)| block.round() == round)) @@ -615,10 +644,11 @@ impl GroupStorage { // find in storage let is_finished = self + .cache .finish_proposals .adding .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) + .or(self.cache.finish_proposals.over.get(proposal_id)) .is_some(); Ok(is_finished) } @@ -647,7 +677,7 @@ impl GroupStorage { &self, round: u64, ) -> (BuckyResult, Vec) { - if self.header_block.is_none() { + if self.cache.header_block.is_none() { return ( Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), vec![], @@ -655,7 +685,7 @@ impl GroupStorage { } let mut blocks = vec![]; - let mut block = self.header_block.clone().unwrap(); + let mut block = self.cache.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; let mut max_height = block.height(); From 7e739f67456fc06c15c3e93b57c80df85bb54491 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 15:20:55 +0800 Subject: [PATCH 442/553] update example for GroupState --- src/tests/group-example/src/main.rs | 479 +++++++++++++++++++--------- 1 file changed, 332 insertions(+), 147 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ffb45ccec..e7948f740 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -3,27 +3,28 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, }; use cyfs_stack::CyfsStack; -use Common::{ - create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, - EXAMPLE_RPATH, -}; +use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; + mod Common { - use std::sync::Arc; + use std::{fmt::format, io::ErrorKind, sync::Arc}; + use async_std::{fs, stream::StreamExt}; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, - UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -35,113 +36,109 @@ mod Common { CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, }; - use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members( + fn create_member( name_prefix: &str, - count: usize, - ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + index: usize, + port: u16, + ) -> ((People, PrivateKey), (Device, PrivateKey)) { log::info!("create members"); - let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); - let mut members = vec![]; + let name = format!("{}-{}", name_prefix, index); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); + endpoint.mut_addr().set_port(port); + endpoint.set_area(EndpointArea::Wan); + + let mut device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + device_private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); - for i in 0..count { - let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_rsa(1024).unwrap(); - let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); - let mut owner = - People::new(None, vec![], private_key.public(), None, Some(name), None).build(); - - let mut endpoint = Endpoint::default(); - endpoint.set_protocol(Protocol::Udp); - endpoint - .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); - endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_area(EndpointArea::Wan); - - let mut device = Device::new( - Some(owner.desc().object_id()), - UniqueId::create_with_random(), - vec![endpoint], - vec![], // TODO: 当前版本是否支持无SN? - vec![], - device_private_key.public(), - Area::default(), - DeviceCategory::PC, - ) - .build(); - - owner - .ood_list_mut() - .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - - let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); - let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); - let device_desc_hash = device.desc().raw_hash_value().unwrap(); - let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); - - let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = - async_std::task::block_on(async move { - let owner_desc_signature = signer - .sign( - owner_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let owner_body_signature = signer - .sign( - owner_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let desc_signature = signer - .sign( - device_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - let body_signature = signer - .sign( - device_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - ( - owner_desc_signature, - owner_body_signature, - desc_signature, - body_signature, + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), ) - }); + .await + .unwrap(); - device.signs_mut().set_desc_sign(desc_signature.clone()); - device.signs_mut().set_body_sign(body_signature); + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); - log::info!( + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", owner.name().unwrap(), owner.desc().object_id(), @@ -152,12 +149,9 @@ mod Common { owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() ); - owner.signs_mut().set_desc_sign(owner_desc_signature); - owner.signs_mut().set_body_sign(owner_body_signature); - members.push(((owner, private_key), (device, device_private_key))); - } - - members + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + ((owner, private_key), (device, device_private_key)) } fn create_group( @@ -194,16 +188,167 @@ mod Common { group } + // (succ, not-found) + fn check_read_buf(file_path: &str, result: &std::io::Result>) -> (bool, bool) { + match result.as_ref() { + Ok(b) => { + if b.len() == 0 { + (false, true) + } else { + (true, false) + } + } + Err(err) if ErrorKind::NotFound == err.kind() => (false, true), + Err(err) => { + log::warn!("read file {} failed: {:?}", file_path, err); + (false, false) + } + } + } + + async fn init_member_from_dir( + save_path: &str, + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + fs::create_dir_all(save_path) + .await + .expect(format!("create dir {} failed", save_path).as_str()); + + let min_port = 30217_u16; + + let mut members = vec![]; + + for i in 0..count { + let index = i + 1; + let people_desc_file_path = format!("{}/people-{}.desc", save_path, index); + let people_sec_file_path = format!("{}/people-{}.sec", save_path, index); + let device_desc_file_path = format!("{}/device-{}.desc", save_path, index); + let device_sec_file_path = format!("{}/device-{}.sec", save_path, index); + + let people_desc_r = fs::read(people_desc_file_path.clone()).await; + let people_sec_r = fs::read(people_sec_file_path.clone()).await; + let device_desc_r = fs::read(device_desc_file_path.clone()).await; + let device_sec_r = fs::read(device_sec_file_path.clone()).await; + + let (is_people_desc_succ, is_people_desc_not_found) = + check_read_buf(people_desc_file_path.as_str(), &people_desc_r); + let (is_people_sec_succ, is_people_sec_not_found) = + check_read_buf(people_sec_file_path.as_str(), &people_sec_r); + let (is_device_desc_succ, is_device_desc_not_found) = + check_read_buf(device_desc_file_path.as_str(), &device_desc_r); + let (is_device_sec_succ, is_device_sec_not_found) = + check_read_buf(device_sec_file_path.as_str(), &device_sec_r); + + if is_people_desc_succ + && is_people_sec_succ + && is_device_desc_succ + && is_device_sec_succ + { + // decode + let people_desc = People::raw_decode(people_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_desc_file_path).as_str()) + .0; + let people_sec = PrivateKey::raw_decode(people_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_sec_file_path).as_str()) + .0; + let device_desc = Device::raw_decode(device_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_desc_file_path).as_str()) + .0; + let device_sec = PrivateKey::raw_decode(device_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_sec_file_path).as_str()) + .0; + members.push(((people_desc, people_sec), (device_desc, device_sec))); + } else if is_people_desc_not_found + && is_people_sec_not_found + && is_device_desc_not_found + && is_device_sec_not_found + { + // create & save + let member = create_member(name_prefix, index, min_port + i as u16); + fs::write( + people_desc_file_path.as_str(), + member.0 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", people_desc_file_path).as_str()); + fs::write(people_sec_file_path.as_str(), member.0 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", people_sec_file_path).as_str()); + fs::write( + device_desc_file_path.as_str(), + member.1 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", device_desc_file_path).as_str()); + fs::write(device_sec_file_path.as_str(), member.1 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", device_sec_file_path).as_str()); + + members.push(member); + } else { + println!("read members failed!"); + std::process::exit(-1); + } + } + + members + } + + pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/admins", "admin", 4).await + } + + pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/members", "member", 9).await + } + + pub async fn init_group( + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + fs::create_dir_all("./test-group") + .await + .expect("create dir ./test-group failed"); + + let read_group_r = fs::read("./test-group/group.desc").await; + match read_group_r { + Ok(buf) => { + if buf.len() > 0 { + return Group::raw_decode(buf.as_slice()) + .expect("decode ./test-group/group.desc failed") + .0; + } + } + Err(err) => { + if ErrorKind::NotFound != err.kind() { + println!("read group failed: {:?}", err); + std::process::exit(-1); + } + } + } + + let group = create_group(admins.get(0).unwrap(), admins, members, oods); + fs::write("./test-group/group.desc", group.to_vec().unwrap()) + .await + .expect("save file ./test-group/group.desc failed"); + group + } + fn init_stack_params( people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); - let mut member_device: Vec = - EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); + let mut admin_device: Vec = admins.iter().map(|m| m.1.clone()).collect(); + let mut member_device: Vec = members.iter().map(|m| m.1.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { @@ -242,7 +387,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { + for (member, device) in admins.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -260,7 +405,7 @@ mod Common { )); } - for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { + for (member, device) in members.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -279,17 +424,17 @@ mod Common { } known_objects.list.push(NONObjectInfo::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_GROUP.to_vec().unwrap(), + group.desc().object_id(), + group.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( - EXAMPLE_GROUP.clone(), + group.clone(), )))), )); - let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( - EXAMPLE_DEC_APP.desc().object_id(), + dec_app.desc().object_id(), dec_app_vec, Some(Arc::new(AnyNamedObject::Core(typeless))), )); @@ -301,8 +446,13 @@ mod Common { people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> CyfsStack { - let params = init_stack_params(people, private_key, device); + let params = + init_stack_params(people, private_key, device, admins, members, group, dec_app); log::info!("cyfs-stack.open"); @@ -316,10 +466,6 @@ mod Common { stack } - - pub fn dummy(people: People, device: Device) { - log::info!("common::dummy"); - } } mod Client { @@ -352,22 +498,21 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + GroupProposalObject, }; use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; use cyfs_stack::CyfsStack; - use crate::Common::EXAMPLE_DEC_APP_ID; - pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { let group_mgr = cyfs_stack.group_mgr(); group_mgr .register( - EXAMPLE_DEC_APP_ID.clone(), + dec_app_id.clone(), Box::new(GroupRPathDelegateFactory { local_name }), ) .await @@ -575,13 +720,14 @@ mod GroupDecService { } } -fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { +fn create_proposal( + delta: u64, + owner: ObjectId, + group_id: ObjectId, + dec_id: ObjectId, +) -> GroupProposal { GroupProposal::create( - GroupRPath::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id().clone(), - EXAMPLE_RPATH.clone(), - ), + GroupRPath::new(group_id, dec_id, EXAMPLE_RPATH.to_string()), "add".to_string(), Some(Vec::from(delta.to_be_bytes())), None, @@ -614,23 +760,57 @@ async fn main_run() { log::info!("will open stacks"); + let admins = init_admins().await; + let members = init_members().await; + let group = init_group( + admins.iter().map(|m| &m.0 .0).collect(), + members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| &m.1 .0).collect(), + ) + .await; + let group_id = group.desc().object_id(); + let dec_app = DecApp::create( + admins.get(0).unwrap().0 .0.desc().object_id(), + EXAMPLE_APP_NAME.as_str(), + ); + let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); + let mut admin_stacks: Vec = vec![]; - for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { - // dummy(admin.clone(), device.clone()); - let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; + for ((admin, _), (device, private_key)) in admins.iter() { + let cyfs_stack = create_stack( + admin.clone(), + private_key, + device.clone(), + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + group.clone(), + dec_app.clone(), + ) + .await; admin_stacks.push(cyfs_stack); } for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); - DecService::run(&stack, admin.name().unwrap().to_string()).await; + let ((admin, _), _) = admins.get(i).unwrap(); + DecService::run( + &stack, + admin.name().unwrap().to_string(), + dec_app_id.clone(), + ) + .await; let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group.desc().object_id(), + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -647,14 +827,19 @@ async fn main_run() { let PROPOSAL_COUNT = 1000usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; - let proposal = create_proposal(i as u64, owner.desc().object_id()); + let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let proposal = create_proposal( + i as u64, + owner.desc().object_id(), + group_id, + dec_app_id.object_id().clone(), + ); let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -676,7 +861,7 @@ async fn main_run() { zone: None, zone_category: DeviceZoneCategory::CurrentDevice, }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + dec: dec_app_id.object_id().clone(), verified: None, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), @@ -700,8 +885,8 @@ async fn main_run() { let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) From 8df36eb4635b4d6908e21a0a6b3ebc0f8aa59826 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 17:36:21 +0800 Subject: [PATCH 443/553] fix: path error --- .../src/statepath/group_statepath.rs | 13 ++++++++-- src/tests/group-example/src/main.rs | 26 +++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eade0f9e4..280fb6948 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -39,51 +39,60 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_GROUP_BLOB, ]), last_vote_round: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), range: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_RANGE, ]), prepares: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PREPARES, ]), pre_commits: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PRE_COMMITS, ]), finish_proposals: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, ]), flip_time: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_FLIP_TIME, ]), recycle: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_RECYCLE, ]), adding: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e7948f740..e29b1be6d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -337,13 +337,13 @@ mod Common { } fn init_stack_params( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -443,13 +443,13 @@ mod Common { } pub async fn create_stack( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> CyfsStack { let params = init_stack_params(people, private_key, device, admins, members, group, dec_app); @@ -778,9 +778,9 @@ async fn main_run() { let mut admin_stacks: Vec = vec![]; for ((admin, _), (device, private_key)) in admins.iter() { let cyfs_stack = create_stack( - admin.clone(), + admin, private_key, - device.clone(), + device, admins .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) @@ -789,8 +789,8 @@ async fn main_run() { .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) .collect(), - group.clone(), - dec_app.clone(), + &group, + &dec_app, ) .await; admin_stacks.push(cyfs_stack); @@ -898,7 +898,7 @@ async fn main_run() { }); if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(200)).await; + async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } From 5080df038a9beec64a81e43bc4248d3308e80508 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 18:34:11 +0800 Subject: [PATCH 444/553] fix: commit storage --- src/component/cyfs-group/src/storage/group_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 5ad19ea15..30fc08cad 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -398,6 +398,7 @@ impl GroupStorage { writer .set_last_vote_round(round, self.cache.last_vote_round) .await?; + writer.commit().await?; self.cache.last_vote_round = round; From dabb24914da53c7b90efa8044fc41cbabd931079 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 445/553] fix: type of pre-commits --- .../cyfs-group/src/dec/group_manager.rs | 21 ++++++++++--------- .../engine/storage_engine_group_state.rs | 20 +++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5ecfcdba2..7ba376368 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,16 +289,17 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - let rpath = header_block.r_path(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::StateChangeNotify(header_block, qc_block), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = header_block.r_path(); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::StateChangeNotify(header_block, qc_block), + // remote, + // ) + // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index ee429a78f..c6acb7b52 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,7 +5,6 @@ use cyfs_base::{ ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -213,9 +212,11 @@ impl StorageEngineGroupStateWriter { .await?; } - self.op_env - .insert_with_path(self.state_path.pre_commits(), block_id) - .await + let is_changed = self.op_env + .insert(self.state_path.pre_commits(), block_id) + .await?; + assert!(is_changed); + Ok(()) } async fn push_commit_inner( @@ -469,7 +470,16 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.prepare_map_id.is_none(), ) .await?; - self.op_env.commit().await.map(|_| ()) + self.op_env.commit().await.map_or_else( + |err| { + if err.code() == BuckyErrorCode::AlreadyExists { + Ok(()) + } else { + Err(err) + } + }, + |_| Ok(()), + ) } } From d505e3376f4603d7434238c29a2fb25f603faa25 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:42:12 +0800 Subject: [PATCH 446/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e29b1be6d..316630f6a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: None, + isolate: Some(device.desc().object_id()), sync_service: false, shared_stack: false, }, From eb2ec9d11aefcf44878d0c902a2c4c728e433ace Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:49:08 +0800 Subject: [PATCH 447/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 316630f6a..d69fcae2d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: Some(device.desc().object_id()), + isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: false, }, From d22470096f3d5c1e3d83d7f489e32a0ec0067ca9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 21 Feb 2023 19:52:57 +0800 Subject: [PATCH 448/553] fix: the round for the first block when restart --- src/component/cyfs-core/src/coreobj.rs | 1 + .../src/group/group_quorum_certificate.rs | 144 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 2 + .../src/consensus/hotstuff/hotstuff.rs | 60 +++++++- .../cyfs-group/src/dec/group_manager.rs | 34 +++-- .../cyfs-group/src/network/non_driver.rs | 30 +++- .../cyfs-group/src/statepath/design.md | 1 + .../src/statepath/group_statepath.rs | 16 +- .../src/storage/engine/storage_engine.rs | 5 +- .../engine/storage_engine_group_state.rs | 130 ++++++++++++---- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 136 ++++++++++++----- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- src/tests/group-example/src/main.rs | 24 +-- 14 files changed, 493 insertions(+), 100 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_quorum_certificate.rs diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 724f0debb..30bf0e013 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupRPathStatus = 703, GroupAction = 704, + GroupQuorumCertificate = 705, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs new file mode 100644 index 000000000..7c3ad77fc --- /dev/null +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -0,0 +1,144 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, DescContent, EmptyBodyContent, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBuilder, NamedObjectId, RawDecode, RawEncode, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_RAW, +}; + +use crate::{CoreObjectType, HotstuffBlockQC, HotstuffTimeout}; + +#[derive(Clone)] +pub enum GroupQuorumCertificateDescContent { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), +} + +impl DescContent for GroupQuorumCertificateDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupQuorumCertificate as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupQuorumCertificateDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +pub type GroupQuorumCertificateType = + NamedObjType; +pub type GroupQuorumCertificateBuilder = + NamedObjectBuilder; + +pub type GroupQuorumCertificateId = NamedObjectId; +pub type GroupQuorumCertificate = NamedObjectBase; + +pub trait GroupQuorumCertificateObject { + fn quorum_round(&self) -> u64; +} + +impl GroupQuorumCertificateObject for GroupQuorumCertificate { + fn quorum_round(&self) -> u64 { + match self.desc().content() { + GroupQuorumCertificateDescContent::QC(qc) => qc.round, + GroupQuorumCertificateDescContent::TC(tc) => tc.round, + } + } +} + +impl RawEncode for GroupQuorumCertificateDescContent { + fn raw_measure( + &self, + purpose: &Option, + ) -> cyfs_base::BuckyResult { + let len = match self { + GroupQuorumCertificateDescContent::QC(qc) => qc.raw_measure(purpose)?, + GroupQuorumCertificateDescContent::TC(tc) => tc.raw_measure(purpose)?, + }; + + Ok(len + 1) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> cyfs_base::BuckyResult<&'a mut [u8]> { + match self { + GroupQuorumCertificateDescContent::QC(qc) => { + buf[0] = 0; + let buf = &mut buf[1..]; + qc.raw_encode(buf, purpose) + } + GroupQuorumCertificateDescContent::TC(tc) => { + buf[0] = 1; + let buf = &mut buf[1..]; + tc.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for GroupQuorumCertificateDescContent { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let obj_type = buf[0]; + let buf = &buf[1..]; + match obj_type { + 0 => { + let (qc, remain) = HotstuffBlockQC::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::QC(qc), remain)) + } + 1 => { + let (qc, remain) = HotstuffTimeout::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::TC(qc), remain)) + } + _ => Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown qc")), + } + } +} + +impl From for GroupQuorumCertificate { + fn from(qc: HotstuffBlockQC) -> Self { + let desc = GroupQuorumCertificateDescContent::QC(qc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl From for GroupQuorumCertificate { + fn from(tc: HotstuffTimeout) -> Self { + let desc = GroupQuorumCertificateDescContent::TC(tc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::QC(qc) => Ok(qc), + GroupQuorumCertificateDescContent::TC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is tc, expect qc")) + } + } + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::TC(tc) => Ok(tc), + GroupQuorumCertificateDescContent::QC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is qc, expect tc")) + } + } + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4c315c090..c153ab1ba 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,6 +1,7 @@ mod group_consensus_block; mod group_proposal; mod group_proposal_decide_param; +mod group_quorum_certificate; mod group_rpath; mod group_rpath_status; mod group_update_group_proposal_param; @@ -8,6 +9,7 @@ mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; pub use group_proposal_decide_param::*; +pub use group_quorum_certificate::*; pub use group_rpath::*; pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e89498b83..7868a7f90 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,7 +9,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; @@ -238,11 +238,36 @@ impl HotstuffRunner { rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); + let last_qc = store.last_qc(); + let (tc, qc) = last_qc + .as_ref() + .map_or((None, None), |qc| { + match qc.desc().content() { + cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), + cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), + } + }); - let round = store - .last_vote_round() - .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let last_vote_round = store + .last_vote_round(); + let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); + let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); + + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" + , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + + let max_round_qc_round = max_round_block + .as_ref() + .map_or(0, |block| + block.qc().as_ref().map_or(0, |qc| qc.round) + ); + let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); + let high_qc = if max_round_qc_round >= last_qc_round { + max_round_block.map_or(None, |b| b.qc().clone()) + } else { + qc + }; let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); @@ -277,7 +302,7 @@ impl HotstuffRunner { rpath, proposal_consumer, rx_proposal_waiter: None, - tc: None, + tc, state_pusher, tx_block_gen, rx_block_gen, @@ -627,6 +652,16 @@ impl HotstuffRunner { * 验证过的块执行这个函数 */ + if let Err(err) = self.non_driver.put_block(block).await { + if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + log::warn!( + "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", + self, block.block_id(), block.height(), block.round() + ); + return Err(err); + } + } + log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", self, block.block_id(), block.height(), block.round() @@ -1072,6 +1107,10 @@ impl HotstuffRunner { let qc_round = qc.round; let qc_prev_block_id = qc.prev_block_id; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); + + self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.process_qc(&Some(qc)).await; let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { @@ -1211,10 +1250,14 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", @@ -1324,6 +1367,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1814,6 +1861,7 @@ impl HotstuffRunner { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id + && max_round_block.round() == self.round && latest_group.is_ok() && last_group.is_ok() && last_group diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7ba376368..70fb10ba6 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -302,22 +302,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.r_path(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); @@ -397,6 +398,7 @@ impl GroupManager { return Err(e); } if let BuckyErrorCode::NotFound = e.code() { + log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); None } else { return Err(e); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4212a0355..979451b79 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,7 +7,9 @@ use cyfs_base::{ TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, +}; use cyfs_lib::NONObjectInfo; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -106,6 +108,32 @@ impl NONDriverHelper { Ok(()) } + pub async fn get_qc( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupQuorumCertificate::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn put_qc(&self, qc: &GroupQuorumCertificate) -> BuckyResult<()> { + let buf = qc.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let qc = NONObjectInfo { + object_id: qc.desc().object_id(), + object_raw: qc.to_vec()?, + object: Some(block_any), + }; + self.put_object(qc).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 70a61e428..cb964e066 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -23,6 +23,7 @@ | | |--${user-id} | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 280fb6948..0e6a887b0 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -5,6 +5,7 @@ pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -23,10 +24,12 @@ lazy_static::lazy_static! { pub struct GroupStatePath { rpath: String, + root: String, dec_state: String, link: String, group_blob: String, last_vote_round: String, + last_qc: String, range: String, prepares: String, pre_commits: String, @@ -39,6 +42,7 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { + root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ @@ -53,6 +57,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), + last_qc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_QC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -107,7 +117,7 @@ impl GroupStatePath { } pub fn root(&self) -> &str { - self.rpath.as_str() + self.root.as_str() } pub fn dec_state(&self) -> &str { @@ -126,6 +136,10 @@ impl GroupStatePath { self.last_vote_round.as_str() } + pub fn last_qc(&self) -> &str { + self.last_qc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index 735277a3a..aebf6fb96 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,6 +12,7 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub last_qc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -33,6 +34,7 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, + last_qc: None, } } } @@ -58,6 +60,7 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index c6acb7b52..2b61dbc47 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, }; use crate::{ @@ -27,26 +27,35 @@ impl StorageEngineGroupState { non_driver: &NONDriverHelper, state_path: &GroupStatePath, ) -> BuckyResult { - let op_env = state_mgr.create_op_env(ACCESS)?; - - let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; - - let last_vote_round = op_env - .get_by_path(state_path.last_vote_round()) - .await? - .map(|id| parse_u64_obj(&id)); + let op_env = state_mgr.create_op_env(ACCESS).map_err(|err| { + log::warn!("create_op_env failed {:?}", err); + err + })?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await; + let dec_state_id = map_not_found_option_to_option(dec_state_id)?; + + let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; + let last_vote_round = + map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; + let last_qc = map_not_found_option_to_option(last_qc)?; + let last_qc = match last_qc.as_ref() { + Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + None => None, + }; let mut first_header_block_ids: Vec = vec![]; - let commit_range = op_env - .get_by_path(state_path.range()) - .await? - .map(|id| parse_range_obj(&id)); + let commit_range = op_env.get_by_path(state_path.range()).await; + let commit_range = + map_not_found_option_to_option(commit_range)?.map(|id| parse_range_obj(&id)); let commit_block = match commit_range { Some((first_height, header_height)) => { let first_block_id = op_env .get_by_path(state_path.commit_height(first_height).as_str()) - .await? - .expect("first block is lost"); + .await; + let first_block_id = + map_not_found_option_to_option(first_block_id)?.expect("first block is lost"); first_header_block_ids.push(first_block_id); if header_height == first_height { @@ -54,7 +63,8 @@ impl StorageEngineGroupState { } else { let header_block_id = op_env .get_by_path(state_path.commit_height(header_height).as_str()) - .await? + .await; + let header_block_id = map_not_found_option_to_option(header_block_id)? .expect("first block is lost"); first_header_block_ids.push(header_block_id); Some((first_block_id, header_block_id)) @@ -64,13 +74,27 @@ impl StorageEngineGroupState { }; let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + if prepare_block_ids.len() == 0 && commit_range.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "not found in storage", + )); + } + let pre_commit_block_ids = load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; - let flip_timestamp = op_env - .get_by_path(state_path.flip_time()) - .await? - .map_or(0, |id| parse_u64_obj(&id)); + let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; + let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { + let n = parse_u64_obj(&id); + // log::debug!( + // "load flip timestamp {}/{} -> {}", + // id, + // id.to_hex().unwrap(), + // n + // ); + n + }); let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; @@ -82,15 +106,18 @@ impl StorageEngineGroupState { ] .concat(); - let load_blocks = futures::future::join_all( - load_block_ids - .iter() - .map(|id| non_driver.get_block(id, None)), - ) + let load_blocks = futures::future::join_all(load_block_ids.iter().map(|id| async { + let id = id.clone(); + non_driver.get_block(&id, None).await.map_err(|err| { + log::warn!("get block {} failed {:?}", id, err); + err + }) + })) .await; let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.last_qc = last_qc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -212,7 +239,8 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self.op_env + let is_changed = self + .op_env .insert(self.state_path.pre_commits(), block_id) .await?; assert!(is_changed); @@ -326,6 +354,15 @@ impl StorageEngineGroupStateWriter { let timestamp_obj = make_u64_obj(timestamp); if prev_timestamp != 0 { let prev_timestamp_obj = make_u64_obj(prev_timestamp); + // log::debug!( + // "will update flip-time from {} -> {}/{} to {} -> {}/{}", + // prev_timestamp, + // prev_timestamp_obj, + // prev_timestamp_obj.to_hex().unwrap(), + // timestamp, + // timestamp_obj, + // timestamp_obj.to_hex().unwrap(), + // ); let prev_value = self .op_env .set_with_path( @@ -337,6 +374,7 @@ impl StorageEngineGroupStateWriter { .await?; assert_eq!(prev_value.unwrap(), prev_timestamp_obj); } else { + // log::debug!("will update flip-time from None to {}", timestamp); self.op_env .insert_with_key( self.state_path.finish_proposals(), @@ -395,6 +433,13 @@ impl StorageEngineGroupStateWriter { Ok(()) } } + + async fn save_last_qc_inner(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_qc(), qc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -458,6 +503,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_qc_inner(qc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; @@ -522,6 +573,7 @@ async fn load_object_ids_with_path( let content = match op_env.list(full_path).await { Ok(content) => content, Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); if err.code() == BuckyErrorCode::NotFound { return Ok(vec![]); } else { @@ -546,3 +598,29 @@ async fn load_object_ids_with_path( Ok(object_ids) } + +fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { + match r { + Ok(t) => Ok(Some(t)), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} + +fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult> { + match r { + Ok(t) => Ok(t), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b944d3735..79491b186 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -192,6 +192,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 30fc08cad..3f9fc9910 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -8,7 +8,10 @@ use cyfs_base::{ ObjectDesc, ObjectId, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupQuorumCertificateObject, HotstuffTimeout, +}; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ @@ -20,7 +23,7 @@ use super::{ StorageEngine, }; -const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; +const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() as u64; pub enum BlockLinkState { Expired, @@ -96,16 +99,32 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver.get_group(group_id, None, None).await?; + let group = non_driver + .get_group(group_id, None, None) + .await + .map_err(|err| { + log::warn!("get group {} from noc failed {:?}", group_id, err); + err + })?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) - .await? + .await + .map_err(|err| { + log::warn!("load root state for group {} failed {:?}", group_id, err); + err + })? .expect("create group state failed."); - let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state + .get_dec_root_manager(dec_id, true) + .await + .map_err(|err| { + log::warn!("get root state manager for dec {} failed {:?}", dec_id, err); + err + })?; let state_path = GroupStatePath::new(rpath.to_string()); let cache = @@ -120,7 +139,7 @@ impl GroupStorage { group_chunk_id: group_chunk_id.object_id(), storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, - cache: cache, + cache, }) } @@ -286,24 +305,33 @@ impl GroupStorage { writer.remove_prepares(remove_prepares.as_slice()).await?; - let finish_proposals: Vec = new_header - .proposals() - .iter() - .map(|p| p.proposal.clone()) - .collect(); - - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { - writer - .push_proposals( - finish_proposals.as_slice(), - Some((timestamp, self.cache.finish_proposals.flip_timestamp)), - ) - .await?; - } else { - writer - .push_proposals(finish_proposals.as_slice(), None) - .await?; + if new_header.proposals().len() > 0 { + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + + let timestamp = new_header.named_object().desc().create_time(); + // log::debug!( + // "push proposals storage flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + writer + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), + ) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } } @@ -340,19 +368,28 @@ impl GroupStorage { self.cache.first_block = Some(new_header.clone()); } - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp - > PROPOSAL_MAX_TIMEOUT_AS_MS - { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); - self.cache.finish_proposals.flip_timestamp = timestamp; - } + if new_header.proposals().len() > 0 { + let timestamp = new_header.named_object().desc().create_time(); + + // log::debug!( + // "push proposals flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; + } - for proposal in new_header.proposals() { - let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); - assert!(is_new); + for proposal in new_header.proposals() { + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } } self.cache.header_block = Some(new_header); @@ -405,6 +442,33 @@ impl GroupStorage { Ok(()) } + pub fn last_qc(&self) -> &Option { + &self.cache.last_qc + } + + pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { + let quorum_round = qc.quorum_round(); + if quorum_round < self.cache.last_vote_round + || quorum_round + <= self + .cache + .last_qc + .as_ref() + .map_or(0, |qc| qc.quorum_round()) + { + return Ok(()); + } + + self.non_driver.put_qc(&qc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_qc(&qc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_qc = Some(qc); + Ok(()) + } + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { log::debug!( "[group storage] {} block_linked {} step1", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9414cda7c..fcb0dd6da 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, @@ -55,6 +55,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { } async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let access = AccessString::full(); + log::debug!("put object {} with access {}", obj.object_id, access); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { @@ -76,7 +78,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { flags: 0, }, object: obj, - access: None, // TODO access + access: Some(AccessString::full()), // TODO access }) .await .map(|_| ()) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d69fcae2d..b5b6f4ce4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,7 +1,8 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ - AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; @@ -23,8 +24,8 @@ mod Common { AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, - TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, - SIGNATURE_SOURCE_REFINDEX_SELF, + TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -210,13 +211,12 @@ mod Common { save_path: &str, name_prefix: &str, count: usize, + min_port: u16, ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { fs::create_dir_all(save_path) .await .expect(format!("create dir {} failed", save_path).as_str()); - let min_port = 30217_u16; - let mut members = vec![]; for i in 0..count { @@ -296,11 +296,13 @@ mod Common { } pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/admins", "admin", 4).await + let min_port = 30217_u16; + init_member_from_dir("./test-group/admins", "admin", 4, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/members", "member", 9).await + let min_port = 31217_u16; + init_member_from_dir("./test-group/members", "member", 9, min_port).await } pub async fn init_group( @@ -369,7 +371,7 @@ mod Common { }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { - bdt_listeners: vec![], + bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], tcp_listeners: vec![], ws_listener: None, }, @@ -868,7 +870,7 @@ async fn main_run() { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: Some(AccessString::full().value()), }; noc.put_object(&req).await; proposals.push(proposal); @@ -878,8 +880,8 @@ async fn main_run() { log::info!("proposals prepared."); - for i in 0..(PROPOSAL_COUNT - 1) { - let proposal = proposals.get(i).unwrap().clone(); + for i in 1..PROPOSAL_COUNT { + let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let control = stack From 54df3a472242446771af3e6f513736449fc0f5ec Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 16:04:16 +0800 Subject: [PATCH 449/553] fix: first block with tc --- .../src/consensus/hotstuff/hotstuff.rs | 75 ++++++++++--------- .../src/statepath/group_statepath.rs | 12 +++ .../src/storage/engine/storage_engine.rs | 9 ++- .../engine/storage_engine_group_state.rs | 35 ++++++++- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 41 +++++++--- src/tests/group-example/src/main.rs | 2 + 7 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7868a7f90..a2a5e8f70 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -239,36 +239,30 @@ impl HotstuffRunner { ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); - let (tc, qc) = last_qc - .as_ref() - .map_or((None, None), |qc| { - match qc.desc().content() { - cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), - cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), - } - }); + let last_tc = store.last_tc(); let last_vote_round = store .last_vote_round(); - let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); - let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); + let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); + let quorum_round = block_quorum_round.max(timeout_quorum_round); + let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" - , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" + , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); - let max_round_qc_round = max_round_block - .as_ref() - .map_or(0, |block| - block.qc().as_ref().map_or(0, |qc| qc.round) - ); - let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); - let high_qc = if max_round_qc_round >= last_qc_round { + let high_qc = if max_round_qc_round >= block_quorum_round { max_round_block.map_or(None, |b| b.qc().clone()) } else { - qc + last_qc.clone() }; + let tc = last_tc.clone(); + let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; @@ -954,18 +948,22 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && qc_round - >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; if !is_valid_round { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {:?}", self, block.block_id(), block.round(), qc_round, - block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + block.tc().as_ref().map_or((0, 0), |tc| { + let qc_round = tc.votes.iter().map(|v| v.high_qc_round).max().unwrap(); + (tc.round, qc_round) + })); return None; } @@ -1109,7 +1107,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); - self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.store.save_qc(&qc).await?; self.process_qc(&Some(qc)).await; @@ -1125,7 +1123,7 @@ impl HotstuffRunner { })?; if self.local_device_id == new_leader { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } Ok(()) } @@ -1251,12 +1249,12 @@ impl HotstuffRunner { max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( @@ -1367,9 +1365,9 @@ impl HotstuffRunner { err })?; - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1535,7 +1533,7 @@ impl HotstuffRunner { self.remove_pending_proposals(remove_proposals).await; if self - .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .try_wait_proposals(executed_proposals.len(), &prev_block) .await { log::debug!( @@ -1739,12 +1737,12 @@ impl HotstuffRunner { async fn try_wait_proposals( &mut self, - executed_proposals: &[(GroupProposal, ExecuteResult)], + proposal_count: usize, pre_block: &Option, ) -> bool { // empty block, qc only, it's unuseful when no block to qc let mut will_wait_proposals = false; - if executed_proposals.len() == 0 { + if proposal_count == 0 { match pre_block.as_ref() { None => { log::warn!( @@ -1814,14 +1812,17 @@ impl HotstuffRunner { assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); - let tc = self.tc.as_ref().map_or(None, |tc| { + self.generate_block(self.with_tc()).await + } + + fn with_tc(&self) -> Option { + self.tc.as_ref().map_or(None, |tc| { if tc.round + 1 == self.round { Some(tc.clone()) } else { None } - }); - self.generate_block(tc).await + }) } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { @@ -1876,7 +1877,7 @@ impl HotstuffRunner { ); } _ => { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } } } diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0e6a887b0..72f48e601 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -6,6 +6,7 @@ pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; +pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -30,6 +31,7 @@ pub struct GroupStatePath { group_blob: String, last_vote_round: String, last_qc: String, + last_tc: String, range: String, prepares: String, pre_commits: String, @@ -63,6 +65,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_QC, ]), + last_tc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_TC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -140,6 +148,10 @@ impl GroupStatePath { self.last_qc.as_str() } + pub fn last_tc(&self) -> &str { + self.last_tc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index aebf6fb96..c4803d6ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,7 +12,8 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 - pub last_qc: Option, + pub last_qc: Option, + pub last_tc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -25,6 +26,8 @@ impl StorageCacheInfo { Self { dec_state_id: init_state_id, last_vote_round: 0, + last_qc: None, + last_tc: None, header_block: None, first_block: None, prepares: HashMap::new(), @@ -34,7 +37,6 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, - last_qc: None, } } } @@ -61,6 +63,7 @@ pub trait StorageWriter: Send + Sync { async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 2b61dbc47..b3a01fd60 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -38,10 +39,26 @@ impl StorageEngineGroupState { let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; let last_vote_round = map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; let last_qc = map_not_found_option_to_option(last_qc)?; let last_qc = match last_qc.as_ref() { - Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + Some(qc_id) => non_driver + .get_qc(qc_id, None) + .await? + .try_into() + .map_or(None, |qc| Some(qc)), + None => None, + }; + + let last_tc = op_env.get_by_path(state_path.last_tc()).await; + let last_tc = map_not_found_option_to_option(last_tc)?; + let last_tc = match last_tc.as_ref() { + Some(tc_id) => non_driver + .get_qc(tc_id, None) + .await? + .try_into() + .map_or(None, |tc| Some(tc)), None => None, }; @@ -118,6 +135,7 @@ impl StorageEngineGroupState { let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); cache.last_qc = last_qc; + cache.last_tc = last_tc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -440,6 +458,13 @@ impl StorageEngineGroupStateWriter { .await .map(|_| ()) } + + async fn save_last_tc_inner(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_tc(), tc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -509,6 +534,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_tc_inner(tc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 79491b186..ebeedd7ca 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -196,6 +196,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3f9fc9910..ee2618cde 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -10,7 +10,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffTimeout, + GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; @@ -442,30 +442,49 @@ impl GroupStorage { Ok(()) } - pub fn last_qc(&self) -> &Option { + pub fn last_qc(&self) -> &Option { &self.cache.last_qc } - pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { - let quorum_round = qc.quorum_round(); + pub async fn save_qc(&mut self, qc: &HotstuffBlockQC) -> BuckyResult<()> { + let quorum_round = qc.round; if quorum_round < self.cache.last_vote_round - || quorum_round - <= self - .cache - .last_qc - .as_ref() - .map_or(0, |qc| qc.quorum_round()) + || quorum_round <= self.cache.last_qc.as_ref().map_or(0, |qc| qc.round) { return Ok(()); } + let qc = GroupQuorumCertificate::from(qc.clone()); self.non_driver.put_qc(&qc).await?; let mut writer = self.storage_engine.create_writer().await?; writer.save_last_qc(&qc.desc().object_id()).await?; writer.commit().await?; - self.cache.last_qc = Some(qc); + self.cache.last_qc = Some(qc.try_into().unwrap()); + Ok(()) + } + + pub fn last_tc(&self) -> &Option { + &self.cache.last_tc + } + + pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + let quorum_round = tc.round; + if quorum_round < self.cache.last_vote_round + || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) + { + return Ok(()); + } + + let tc = GroupQuorumCertificate::from(tc.clone()); + self.non_driver.put_qc(&tc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_tc(&tc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_tc = Some(tc.try_into().unwrap()); Ok(()) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b5b6f4ce4..2ba99716e 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -798,6 +798,8 @@ async fn main_run() { admin_stacks.push(cyfs_stack); } + async_std::task::sleep(Duration::from_millis(10000)).await; + for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); From cea93a54bc6dc56fdd7f1cdbd4e15c3edc4a0542 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:23:03 +0800 Subject: [PATCH 450/553] prepare for verify --- .../cyfs-core/protos/core_objects.proto | 14 -- src/component/cyfs-core/src/coreobj.rs | 1 - .../src/group/group_consensus_block.rs | 23 +++ .../cyfs-core/src/group/group_rpath_status.rs | 17 --- src/component/cyfs-core/src/group/mod.rs | 2 - .../protos/group_bft_protocol.proto | 6 + src/component/cyfs-group/src/crypto/crypto.rs | 14 -- src/component/cyfs-group/src/crypto/mod.rs | 3 - .../cyfs-group/src/dec/group_manager.rs | 35 +++-- .../src/dec_state/dec_state_requestor.rs | 32 ++-- src/component/cyfs-group/src/helper/verify.rs | 6 +- src/component/cyfs-group/src/lib.rs | 2 - .../src/objects/group_rpath_status.rs | 89 +++++++++++ src/component/cyfs-group/src/objects/mod.rs | 2 + .../cyfs-group/src/objects/protocol.rs | 140 +++++++++++++----- .../cyfs-group/src/storage/dec_storage.rs | 6 +- 16 files changed, 259 insertions(+), 133 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs delete mode 100644 src/component/cyfs-group/src/crypto/crypto.rs delete mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/objects/group_rpath_status.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 164c6bcd6..487ece4bd 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -431,20 +431,6 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } -message GroupRPathSubStatus { - string sub_path = 1; - repeated bytes state_id = 2; // for set -} - -message GroupRPathStatusDescContent { - bytes block_id = 1; - optional bytes sub_status_hash = 2; -} - -message GroupRPathStatusBodyContent { - repeated GroupRPathSubStatus sub_status = 1; -} - message GroupActionDescContent { // target GroupRPath r_path = 1; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 30bf0e013..3d53a082f 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -64,7 +64,6 @@ pub enum CoreObjectType { GroupProposal = 700, GroupUpdateGroup = 701, GroupConsensusBlock = 702, - GroupRPathStatus = 703, GroupAction = 704, GroupQuorumCertificate = 705, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 5d6d114c0..35c418552 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -38,6 +38,28 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } +impl GroupConsensusBlockDescContent { + pub fn rpath(&self) -> &GroupRPath { + &self.r_path + } + + pub fn result_state_id(&self) -> &Option { + &self.result_state_id + } + + pub fn height(&self) -> u64 { + self.height + } + + pub fn round(&self) -> u64 { + self.round + } + + pub fn group_chunk_id(&self) -> &ObjectId { + &self.group_chunk_id + } +} + #[derive(Clone, ProtobufTransformType)] #[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] pub struct HotstuffBlockQCSign { @@ -175,6 +197,7 @@ impl BodyContent for GroupConsensusBlockBodyContent { } } +pub type GroupConsensusBlockDesc = NamedObjectDesc; type GroupConsensusBlockType = NamedObjType; type GroupConsensusBlockBuilder = diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs deleted file mode 100644 index c55c41243..000000000 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::atomic::{AtomicU8, Ordering}; - -use crate::CoreObjectType; -use cyfs_base::*; -use serde::Serialize; -use sha2::Digest; - -// TODO: 后面再封装这个对象 -#[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus { - pub value_object_id: ObjectId, - pub block_id: ObjectId, - pub qc_block_id: ObjectId, -} - -#[cfg(test)] -mod test {} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index c153ab1ba..b2885d637 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -3,7 +3,6 @@ mod group_proposal; mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_rpath_status; mod group_update_group_proposal_param; pub use group_consensus_block::*; @@ -11,5 +10,4 @@ pub use group_proposal::*; pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 6ed8c3afe..621186522 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -15,3 +15,9 @@ message HotstuffTimeoutVote { bytes voter = 3; bytes signature = 4; } + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs deleted file mode 100644 index 9949f7a67..000000000 --- a/src/component/cyfs-group/src/crypto/crypto.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cyfs_base::{HashValue, ObjectId, Signature}; - -#[derive(Clone)] -pub struct Crypto {} - -impl Crypto { - pub fn sign(&self, hash: &HashValue) -> Signature { - unimplemented!() - } - - pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs deleted file mode 100644 index 066e79b6b..000000000 --- a/src/component/cyfs-group/src/crypto/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod crypto; - -pub use crypto::*; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 70fb10ba6..2f2229890 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,7 +289,7 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - // TODO: 暂时不实现 + // TODO: unimplemented // let rpath = header_block.r_path(); // let client = self // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) @@ -302,23 +302,22 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - // TODO: 暂时不实现 - // let rpath = result.as_ref().map_or_else( - // |(_, target)| target.check_rpath(), - // |(_, block, _)| block.r_path(), - // ); - // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - // .await?; - // client - // .on_message( - // HotstuffMessage::ProposalResult( - // proposal_id, - // result.map_err(|(err, _)| err), - // ), - // remote, - // ) - // .await; + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) + .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e30c0a5a7..369b3db6e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,10 +3,13 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; -use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; +use crate::{ + helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + CHANNEL_CAPACITY, +}; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -143,7 +146,7 @@ impl DecStateRequestorRunner { let result = self .verify_verifiable_state(sub_path.as_str(), &result, &remote) .await - .map(|_| result.value_object_id); + .map(|_| unimplemented!()); // TODO: 搜索目标值 self.query_state_notifier.reply(&sub_path, result).await } @@ -157,25 +160,22 @@ impl DecStateRequestorRunner { result: &GroupRPathStatus, remote: &ObjectId, ) -> BuckyResult<()> { - let header_block = self - .non_driver - .get_block(&result.block_id, Some(remote)) - .await?; - let qc_block = self - .non_driver - .get_block(&result.qc_block_id, Some(remote)) - .await?; + // let header_block = self + // .non_driver + // .get_block(&result.block_id, Some(remote)) + // .await?; + // let qc_block = self + // .non_driver + // .get_block(&result.qc_block_id, Some(remote)) + // .await?; - let qc = match qc_block.qc() { - Some(qc) => qc, - None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), - }; + let qc = &result.certificate; let group = self .non_driver .get_group( self.rpath.group_id(), - Some(header_block.group_chunk_id()), + Some(result.block_desc.content().group_chunk_id()), Some(&remote), ) .await?; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 2a384d1cf..b8ab12b69 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; + +use crate::GroupRPathStatus; pub async fn verify_block( block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index fefe3f808..ba8e83569 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -1,6 +1,5 @@ mod consensus; mod constant; -mod crypto; mod dec; mod dec_state; mod helper; @@ -12,7 +11,6 @@ mod utils; pub use consensus::*; pub use constant::*; -pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs new file mode 100644 index 000000000..f266d3dbd --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use cyfs_base::*; +use cyfs_core::{GroupConsensusBlockDesc, HotstuffBlockQC}; +use cyfs_lib::NONObjectInfo; +use prost::Message; + +#[derive(Clone)] +pub struct GroupRPathStatus { + pub block_desc: GroupConsensusBlockDesc, + pub certificate: HotstuffBlockQC, + pub status_map: HashMap, +} + +impl RawEncode for GroupRPathStatus { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + Ok(proto.encoded_len()) + } + + fn raw_encode<'a>( + &self, + mut buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + proto.encode_raw(&mut buf); + + Ok(buf) + } +} + +impl<'de> RawDecode<'de> for GroupRPathStatus { + fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + let (block_desc, remain) = + GroupConsensusBlockDesc::raw_decode(proto.block_desc.as_slice())?; + assert_eq!(remain.len(), 0); + let (certificate, remain) = HotstuffBlockQC::raw_decode(proto.certificate.as_slice())?; + assert_eq!(remain.len(), 0); + let mut status_map = HashMap::new(); + for obj_buf in proto.status_list.iter() { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status_map.insert(status.object_id, status); + } + + Ok(( + Self { + block_desc, + certificate, + status_map, + }, + buf, + )) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs index d6de55d79..5d1a8b13f 100644 --- a/src/component/cyfs-group/src/objects/mod.rs +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -1,7 +1,9 @@ mod group_decide_proposal; +mod group_rpath_status; mod group_update_proposal; mod protocol; pub use group_decide_proposal::*; +pub use group_rpath_status::*; pub use group_update_proposal::*; pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 3e5f513df..6c9f89e96 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,16 +2,15 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } -use std::result; - use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; +use crate::GroupRPathStatus; + #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), @@ -163,20 +162,16 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::ProposalResult({}, {:?})", proposal_id, - result.as_ref().map_or_else( - |err| { Err(err) }, - |(obj, block, qc)| { - let ok = format!( - "({:?}, {}/{}, {}/{})", - obj.as_ref().map(|o| o.object_id), - block.block_id(), - block.round(), - qc.block_id(), - qc.round() - ); - Ok(ok) - } - ) + result.as_ref().map(|(obj, block, qc)| { + format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + }) ) } Self::QueryState(sub_path) => { @@ -187,7 +182,17 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map(|status| { + let desc = status.block_desc.content(); + format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ) + }) ) } } @@ -196,6 +201,7 @@ impl std::fmt::Debug for HotstuffMessage { const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; +const PACKAGE_FLAG_QUERY_STATE_RESULT_OK: u8 = 0x80u8; #[derive(Clone)] pub(crate) enum HotstuffPackage { @@ -220,7 +226,10 @@ pub(crate) enum HotstuffPackage { >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, String, BuckyResult), + VerifiableState( + String, + Result, + ), } impl std::fmt::Debug for HotstuffPackage { @@ -296,12 +305,26 @@ impl std::fmt::Debug for HotstuffPackage { Self::QueryState(_, sub_path) => { write!(f, "HotstuffPackage::QueryState({})", sub_path) } - Self::VerifiableState(_, sub_path, result) => { + Self::VerifiableState(sub_path, result) => { write!( f, "HotstuffPackage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |status| { + let desc = status.block_desc.content(); + let ok = format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ); + Ok(ok) + } + ) ) } } @@ -323,7 +346,10 @@ impl HotstuffPackage { |(_, block, _)| block.r_path(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), - HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |status| status.block_desc.content().rpath(), + ), } } } @@ -399,10 +425,14 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::QueryState(addr, sub_path) => { addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { - 2 + addr.raw_measure(purpose)? - + sub_path.raw_measure(purpose)? - + result.raw_measure(purpose)? + HotstuffPackage::VerifiableState(sub_path, result) => { + sub_path.raw_measure(purpose)? + + match result { + Ok(status) => status.raw_measure(purpose)?, + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } } }; @@ -459,7 +489,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; if result.is_ok() { - buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + buf[0] |= PACKAGE_FLAG_PROPOSAL_RESULT_OK; } let buf = &mut buf[1..]; @@ -482,12 +512,20 @@ impl RawEncode for HotstuffPackage { let buf = sub_path.raw_encode(buf, purpose)?; addr.raw_encode(buf, purpose) } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { + HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; + if result.is_ok() { + buf[0] |= PACKAGE_FLAG_QUERY_STATE_RESULT_OK; + } let buf = &mut buf[1..]; - let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = sub_path.raw_encode(buf, purpose)?; - result.raw_encode(buf, purpose) + match result { + Ok(status) => status.raw_encode(buf, purpose), + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } } } } @@ -502,24 +540,28 @@ impl<'de> RawDecode<'de> for HotstuffPackage { 0 => { let buf = &buf[1..]; let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { @@ -527,17 +569,20 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } 7 => { @@ -549,6 +594,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), buf, @@ -557,6 +603,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { false => { let (err, buf) = BuckyError::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } } @@ -565,17 +612,29 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let buf = &buf[1..]; let (sub_path, buf) = String::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } 9 => { + let is_ok = (buf[0] & PACKAGE_FLAG_QUERY_STATE_RESULT_OK) != 0; let buf = &buf[1..]; - let (addr, buf) = decode_with_length(buf, 3)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (result, buf) = BuckyResult::::raw_decode(buf)?; - Ok(( - HotstuffPackage::VerifiableState(addr, sub_path, result), - buf, - )) + match is_ok { + true => { + let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok(( + HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), + buf, + )) + } + } } _ => unreachable!("unknown protocol"), } @@ -613,9 +672,10 @@ impl HotstuffPackage { HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) } - HotstuffMessage::VerifiableState(sub_path, result) => { - HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) - } + HotstuffMessage::VerifiableState(sub_path, result) => HotstuffPackage::VerifiableState( + sub_path, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ), } } } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 12e3629d8..cce00e736 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use async_std::sync::RwLock; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; +use cyfs_core::GroupConsensusBlock; + +use crate::GroupRPathStatus; #[derive(Clone)] pub struct DecStorageCache { @@ -11,8 +13,6 @@ pub struct DecStorageCache { pub qc_block: GroupConsensusBlock, } -// TODO: storage - #[derive(Clone)] pub struct DecStorage { cache: Arc>>, From c7681f562bbd80f0ef0ae91c6efd298601469a32 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:28:28 +0800 Subject: [PATCH 451/553] compile --- .../cyfs-group/src/dec/group_manager.rs | 12 +++++++++--- .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 14 +++++++++----- src/component/cyfs-group/src/helper/verify.rs | 16 +++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 2f2229890..0d863e17b 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -328,13 +328,19 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - HotstuffPackage::VerifiableState(target, sub_path, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::VerifiableState(sub_path, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |status| status.block_desc.content().rpath(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .on_message( + HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), + remote, + ) .await; } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 369b3db6e..b5c3b107e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -180,7 +180,7 @@ impl DecStateRequestorRunner { ) .await?; - if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { Err(BuckyError::new( BuckyErrorCode::InvalidSignature, "verify failed", diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f33ec5fa..73afb0ad0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -315,10 +315,7 @@ impl DecStateSynchronizerRunner { remote: ObjectId, ) -> BuckyResult<()> { if qc_block.qc().is_none() { - log::warn!( - "the qc is none for qc-block({})", - qc_block.block_id() - ); + log::warn!("the qc is none for qc-block({})", qc_block.block_id()); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } @@ -365,7 +362,14 @@ impl DecStateSynchronizerRunner { } }; - if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + if header_block.check() + && verify_block( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + &group.1, + ) + .await? + { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index b8ab12b69..759bf2c4a 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,15 +1,17 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, +}; use crate::GroupRPathStatus; pub async fn verify_block( - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.block_id().object_id(); - if qc.round != block.round() || &qc.block_id != block_id { + let block_id = block_desc.object_id(); + if qc.round != block_desc.content().round() || qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, @@ -18,17 +20,13 @@ pub async fn verify_block( return Ok(false); } - if !block.check() { - return Ok(false); - } - unimplemented!() } pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { From d530cc28e0e019452d31566e8a8d95db66c13312 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 23 Feb 2023 21:02:07 +0800 Subject: [PATCH 452/553] Verify the value on sub-path from anyone OOD in group --- .../src/consensus/hotstuff/hotstuff.rs | 28 ++++- .../src/consensus/vote/committee.rs | 66 ++++++++++- .../cyfs-group/src/dec/group_manager.rs | 54 ++++++--- .../cyfs-group/src/dec/rpath_client.rs | 34 ++++-- .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../src/dec_state/dec_state_requestor.rs | 73 ++++++------ .../src/dec_state/dec_state_synchronizer.rs | 80 ++++++-------- src/component/cyfs-group/src/helper/verify.rs | 18 --- .../src/objects/group_rpath_status.rs | 4 +- .../cyfs-group/src/storage/dec_storage.rs | 76 ++++++++++++- .../src/storage/engine/storage_engine.rs | 4 +- .../engine/storage_engine_group_state.rs | 23 +++- .../cyfs-group/src/storage/group_storage.rs | 104 +++++++++++++++++- src/component/cyfs-group/src/utils.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 15 files changed, 410 insertions(+), 166 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index a2a5e8f70..667966a6c 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -187,6 +187,19 @@ impl Hotstuff { self.state_pusher.request_last_state(remote).await; } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_query_state: sub_path: {}, remote: {:?},", + self, + sub_path, + remote + ); + + self.tx_message + .send((HotstuffMessage::QueryState(sub_path), remote)) + .await; + } } struct HotstuffRunner { @@ -1834,6 +1847,19 @@ impl HotstuffRunner { Ok(()) } + async fn handle_query_state(&self, sub_path: String, remote: ObjectId) -> BuckyResult<()> { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + + Ok(()) + } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; @@ -1918,7 +1944,7 @@ impl HotstuffRunner { Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), - Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d3fbd489c..ad3a21e35 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,9 +10,13 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { @@ -136,6 +140,47 @@ impl Committee { Ok(()) } + pub async fn verify_block_desc_with_qc( + &self, + block_desc: &GroupConsensusBlockDesc, + qc: &HotstuffBlockQC, + from: ObjectId, + ) -> BuckyResult<()> { + let block_id = block_desc.object_id(); + + log::debug!( + "[group committee] {} verify block desc {} step1", + self.local_device_id, + block_id + ); + + if block_id != qc.block_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the block id is unmatch with the qc", + )); + } + + self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + .await?; + + log::debug!( + "[group committee] {} verify block desc {} step2", + self.local_device_id, + block_id + ); + + self.verify_qc_with_desc(qc, block_desc.content()).await?; + + log::debug!( + "[group committee] {} verify block desc {} step3", + self.local_device_id, + block_id + ); + + Ok(()) + } + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { let hash = vote.hash(); let device = self.non_driver.get_device(&vote.voter).await?; @@ -250,8 +295,17 @@ impl Committee { qc: &HotstuffBlockQC, prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { - if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); + self.verify_qc_with_desc(qc, prev_block.named_object().desc().content()) + .await + } + + pub async fn verify_qc_with_desc( + &self, + qc: &HotstuffBlockQC, + prev_block_desc: &GroupConsensusBlockDescContent, + ) -> BuckyResult<()> { + if qc.round != prev_block_desc.round() { + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block_desc.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, "round not match in qc", @@ -261,7 +315,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block.group_chunk_id()), + Some(prev_block_desc.group_chunk_id()), ) .await?; @@ -291,7 +345,7 @@ impl Committee { .map_or(Ok(()), |e| e) } - async fn check_group( + pub async fn check_group( &self, chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 0d863e17b..f7b7fbbbe 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -123,6 +123,7 @@ impl GroupManager { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); + let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), @@ -143,9 +144,13 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let state_proccessor = state_mgr + .load_root_state(local_device_id.object_id(), Some(local_id), true) + .await?; let client = RPathClient::load( - local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + state_proccessor.unwrap(), non_driver, network_sender, ) @@ -199,7 +204,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, Some(&block), Some(&remote), ) @@ -215,7 +220,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -231,7 +236,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -247,7 +252,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -263,7 +268,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -279,7 +284,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -321,12 +326,32 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message(HotstuffMessage::QueryState(sub_path), remote) + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + IsCreateRPath::No, + None, + Some(&remote), + ) .await; + + match control { + Ok(control) => { + control + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + _ => { + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + } } HotstuffPackage::VerifiableState(sub_path, result) => { let rpath = result.as_ref().map_or_else( @@ -436,15 +461,10 @@ impl GroupManager { let store = match store { Some(store) => store, None => { - let init_state = match is_auto_create { - IsCreateRPath::Yes(init_state) => init_state, - _ => unreachable!(), - }; GroupStorage::create( group_id, dec_id, rpath, - init_state, non_driver.clone(), local_device_id.object_id().clone(), &root_state_mgr, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 9f1d08579..8a1dd34a7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -5,18 +5,18 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, storage::DecStorage, - HotstuffMessage, CLIENT_POLL_TIMEOUT, + Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; struct RPathClientRaw { rpath: GroupRPath, - local_id: ObjectId, + local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, @@ -28,22 +28,31 @@ pub struct RPathClient(Arc); impl RPathClient { pub(crate) async fn load( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { - let dec_store = DecStorage::load().await?; + let dec_store = DecStorage::load(state_processor).await?; + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); + let state_sync = DecStateSynchronizer::new( - local_id, + local_device_id, rpath.clone(), + committee.clone(), non_driver.clone(), dec_store.clone(), ); let state_requestor = DecStateRequestor::new( - local_id, + local_device_id, rpath.clone(), + committee, network_sender.clone(), non_driver.clone(), dec_store.clone(), @@ -53,7 +62,7 @@ impl RPathClient { rpath, non_driver, network_sender, - local_id, + local_device_id, state_sync, state_requestor, }; @@ -77,7 +86,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -143,7 +152,7 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let random = rand::thread_rng().gen_range(0..oods.len()); let ood = oods.get(random).unwrap().clone(); @@ -154,14 +163,15 @@ impl RPathClient { Ok(()) } - pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 .non_driver .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); + let members = + group.select_members_with_distance(&self.0.local_device_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 101b34075..7abff1ec1 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -89,7 +89,9 @@ impl RPathControl { HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), HotstuffMessage::ProposalResult(_, _) => unreachable!(), - HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::QueryState(sub_path) => { + self.0.hotstuff.on_query_state(sub_path, remote).await + } HotstuffMessage::VerifiableState(_, _) => unreachable!(), } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index b5c3b107e..0a3544c09 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,10 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, CHANNEL_CAPACITY, }; @@ -19,9 +20,9 @@ enum DecStateRequestorMessage { } struct DecStateRequestorRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } #[derive(Clone)] @@ -29,8 +30,9 @@ pub struct DecStateRequestor(Arc); impl DecStateRequestor { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, store: DecStorage, @@ -39,8 +41,9 @@ impl DecStateRequestor { let notifier = CallReplyNotifier::new(); let mut runner = DecStateRequestorRunner::new( - local_id, + local_device_id, rpath, + committee, rx, store, network_sender, @@ -51,7 +54,7 @@ impl DecStateRequestor { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateRequestorRaw { - local_id, + local_device_id, tx_dec_state_req_message: tx, query_state_notifier: notifier, })) @@ -60,7 +63,7 @@ impl DecStateRequestor { pub async fn wait_query_state( &self, sub_path: String, - ) -> CallReplyWaiter> { + ) -> CallReplyWaiter>> { self.0.query_state_notifier.prepare(sub_path).await } @@ -88,21 +91,23 @@ impl DecStateRequestor { } struct DecStateRequestorRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, // timer: Timer, store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } impl DecStateRequestorRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<( DecStateRequestorMessage, ObjectId, @@ -110,10 +115,10 @@ impl DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, rx_dec_state_req_message, // timer: Timer::new(SYNCHRONIZER_TIMEOUT), @@ -121,6 +126,7 @@ impl DecStateRequestorRunner { query_state_notifier, network_sender, non_driver, + committee, } } @@ -144,9 +150,9 @@ impl DecStateRequestorRunner { match result { Ok(result) => { let result = self - .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .check_sub_path_value(sub_path.as_str(), &result, &remote) .await - .map(|_| unimplemented!()); // TODO: 搜索目标值 + .map(|r| r.cloned()); self.query_state_notifier.reply(&sub_path, result).await } @@ -154,40 +160,23 @@ impl DecStateRequestorRunner { } } - async fn verify_verifiable_state( + async fn check_sub_path_value<'a>( &self, sub_path: &str, - result: &GroupRPathStatus, + verifiable_status: &'a GroupRPathStatus, remote: &ObjectId, - ) -> BuckyResult<()> { - // let header_block = self - // .non_driver - // .get_block(&result.block_id, Some(remote)) - // .await?; - // let qc_block = self - // .non_driver - // .get_block(&result.qc_block_id, Some(remote)) - // .await?; - - let qc = &result.certificate; - - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(result.block_desc.content().group_chunk_id()), - Some(&remote), + ) -> BuckyResult> { + self.committee + .verify_block_desc_with_qc( + &verifiable_status.block_desc, + &verifiable_status.certificate, + remote.clone(), ) .await?; - if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "verify failed", - )) - } else { - Ok(()) - } + self.store + .check_sub_path_value(sub_path, verifiable_status) + .await } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 73afb0ad0..7272b3882 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -10,10 +10,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::{verify_block, Timer}, + helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, + Committee, CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -32,7 +32,7 @@ enum DecStateSynchronizerMessage { } struct DecStateSynchronizerRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, proposal_result_notifier: CallReplyNotifier>>, } @@ -42,8 +42,9 @@ pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { @@ -51,8 +52,9 @@ impl DecStateSynchronizer { let notifier = CallReplyNotifier::new(); let mut runner = DecStateSynchronizerRunner::new( - local_id, + local_device_id, rpath, + committee, tx.clone(), rx, store, @@ -63,7 +65,7 @@ impl DecStateSynchronizer { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateSynchronizerRaw { - local_id, + local_device_id, tx_dec_state_sync_message: tx, proposal_result_notifier: notifier, })) @@ -126,8 +128,9 @@ struct UpdateNotifyInfo { } struct DecStateSynchronizerRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, @@ -142,8 +145,9 @@ struct DecStateSynchronizerRunner { impl DecStateSynchronizerRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<( DecStateSynchronizerMessage, ObjectId, @@ -157,7 +161,7 @@ impl DecStateSynchronizerRunner { proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, tx_dec_state_sync_message, rx_dec_state_sync_message, @@ -167,6 +171,7 @@ impl DecStateSynchronizerRunner { update_notifies: None, non_driver, proposal_result_notifier, + committee, } } @@ -330,52 +335,29 @@ impl DecStateSynchronizerRunner { } } - let group = match self.update_notifies.as_ref() { - Some(n) => Some((n.group_chunk_id, n.group.clone())), - None => self - .check_cache() - .await - .as_ref() - .map(|c| (c.group_chunk_id, c.group.clone())), - } - .map_or(None, |(chunk_id, group)| { - if &chunk_id == header_block.group_chunk_id() { - Some((chunk_id, group)) - } else { - None - } - }); - - // group changed - let group = match group { - Some(group) => group, - None => { - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(header_block.group_chunk_id()), - Some(&remote), - ) - .await?; - (header_block.group_chunk_id().clone(), group) - } - }; - if header_block.check() - && verify_block( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - &group.1, - ) - .await? + && self + .committee + .verify_block_desc_with_qc( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + remote, + ) + .await + .is_ok() { + let group = self + .committee + .check_group(Some(header_block.group_chunk_id()), None) + .await?; + let group_chunk_id = header_block.group_chunk_id().clone(); + self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, remotes: HashSet::from([remote]), - group_chunk_id: group.0, - group: group.1, + group_chunk_id, + group, }); }; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 759bf2c4a..ef3e34495 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -5,24 +5,6 @@ use cyfs_core::{ use crate::GroupRPathStatus; -pub async fn verify_block( - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - let block_id = block_desc.object_id(); - if qc.round != block_desc.content().round() || qc.block_id != block_id { - log::error!( - "the qc-block({}) should be next block({})", - qc.round, - block_id - ); - return Ok(false); - } - - unimplemented!() -} - pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index f266d3dbd..858c37fff 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -13,7 +13,7 @@ pub struct GroupRPathStatus { } impl RawEncode for GroupRPathStatus { - fn raw_measure(&self, purpose: &Option) -> BuckyResult { + fn raw_measure(&self, _purpose: &Option) -> BuckyResult { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; let mut status_list = vec![]; @@ -33,7 +33,7 @@ impl RawEncode for GroupRPathStatus { fn raw_encode<'a>( &self, mut buf: &'a mut [u8], - purpose: &Option, + _purpose: &Option, ) -> BuckyResult<&'a mut [u8]> { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index cce00e736..de5a0fd4a 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -1,10 +1,14 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, + ObjectTypeCode, RawDecode, +}; use cyfs_core::GroupConsensusBlock; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::GroupRPathStatus; +use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; #[derive(Clone)] pub struct DecStorageCache { @@ -16,13 +20,15 @@ pub struct DecStorageCache { #[derive(Clone)] pub struct DecStorage { cache: Arc>>, + pub state_processor: GlobalStateRawProcessorRef, } impl DecStorage { - pub async fn load() -> BuckyResult { - unimplemented!(); + pub async fn load(state_processor: GlobalStateRawProcessorRef) -> BuckyResult { + // unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), + state_processor, }; Ok(obj) @@ -45,4 +51,64 @@ impl DecStorage { pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } + + pub async fn check_sub_path_value<'a>( + &self, + sub_path: &str, + verifiable_status: &'a GroupRPathStatus, + ) -> BuckyResult> { + let block_desc = &verifiable_status.block_desc; + let qc = &verifiable_status.certificate; + + let mut parent_state_id = match block_desc.content().result_state_id() { + Some(state_id) => state_id.clone(), + None => return Ok(None), + }; + + let root_cache = self.state_processor.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { + Some(state) => state, + None => return Ok(None), + }; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(None); + } + } + } + + Ok(verifiable_status.status_map.get(&parent_state_id)) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index c4803d6ff..eb0ede98f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -22,9 +22,9 @@ pub struct StorageCacheInfo { } impl StorageCacheInfo { - pub fn new(init_state_id: Option) -> Self { + pub fn new(dec_state_id: Option) -> Self { Self { - dec_state_id: init_state_id, + dec_state_id, last_vote_round: 0, last_qc: None, last_tc: None, diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index b3a01fd60..604e44744 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,10 +2,10 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, + ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -154,6 +154,19 @@ impl StorageEngineGroupState { None => 0, }; + let dec_state_id_in_header = cache + .header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); + + assert_eq!(dec_state_id, dec_state_id_in_header); + if dec_state_id != dec_state_id_in_header { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the state should same as it in header-block", + )); + } + let (prepare_blocks, pre_commit_blocks) = load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { @@ -179,6 +192,10 @@ impl StorageEngineGroupState { .await?, ) } + + pub fn root_cache(&self) -> &ObjectMapRootCacheRef { + self.state_mgr.root_cache() + } } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index ee2618cde..d233025ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -5,7 +5,7 @@ use std::{ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, + ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -15,7 +15,8 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ @@ -56,7 +57,6 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, @@ -84,7 +84,7 @@ impl GroupStorage { GroupStatePath::new(rpath.to_string()), ), local_device_id, - cache: StorageCacheInfo::new(init_state_id), + cache: StorageCacheInfo::new(None), }) } @@ -809,4 +809,100 @@ impl GroupStorage { ) } } + + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let (header_block, qc) = match self.cache.header_block.as_ref() { + Some(block) => { + let (_, qc_block) = self + .cache + .pre_commits + .iter() + .next() + .expect("pre-commit should not be empty"); + + assert_eq!( + qc_block.prev_block_id().unwrap(), + block.block_id().object_id(), + "the prev-block for all pre-commits should be the header" + ); + + (block, qc_block.qc().as_ref().unwrap()) + } + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "the header block is none", + )); + } + }; + + let mut parent_state_id = match header_block.result_state_id() { + Some(state_id) => state_id.clone(), + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map: HashMap::new(), + }) + } + }; + + let mut status_map = HashMap::new(); + + let root_cache = self.storage_engine.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + status_map.insert(parent_state_id, parent_state); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } + } + } + + let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + status_map.insert(parent_state_id, leaf_state); + + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } } diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 9fbc4eb4f..5d005a726 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), // init state + Yes, } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 2ba99716e..0401c55a0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -816,7 +816,7 @@ async fn main_run() { &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -845,7 +845,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -892,7 +892,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); From 7c6acd58cfcb628496b5452728ed8912301a7acc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 17:03:44 +0800 Subject: [PATCH 453/553] Example for APP-State as tree --- .../src/consensus/hotstuff/hotstuff.rs | 9 +- .../cyfs-group/src/dec/delegate_factory.rs | 10 +- .../src/storage/engine/storage_engine.rs | 2 +- .../engine/storage_engine_group_state.rs | 23 ++- .../cyfs-group/src/storage/group_storage.rs | 18 +- src/tests/group-example/src/main.rs | 155 +++++++++++++++--- 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 667966a6c..d9773bd88 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,13 +9,13 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, @@ -499,7 +499,7 @@ impl HotstuffRunner { if self .delegate - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -851,6 +851,7 @@ impl HotstuffRunner { .on_commited( &proposal_obj, pre_state_id, + self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1528,7 +1529,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id).await { + match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index bdcb98f60..0b13d97ce 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -34,12 +34,14 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult; @@ -47,7 +49,13 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ); } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index eb0ede98f..cbb5d99df 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 604e44744..aae81394b 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -8,8 +8,8 @@ use cyfs_base::{ use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -672,3 +672,22 @@ fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult Self { + Self { + state_mgr: state_mgr.clone(), + } + } +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { + async fn create_single_op_env(&self) -> BuckyResult { + self.state_mgr.create_single_op_env(ACCESS) + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d233025ab..3a1c20f2a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,12 +15,15 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ - engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + engine::{ + GroupObjectMapProcessorGroupState, StorageCacheInfo, StorageEngineGroupState, + StorageEngineMock, + }, StorageEngine, }; @@ -50,6 +53,7 @@ pub struct GroupStorage { cache: StorageCacheInfo, storage_engine: StorageEngineGroupState, + object_map_processor: GroupObjectMapProcessorGroupState, } impl GroupStorage { @@ -71,6 +75,7 @@ impl GroupStorage { .expect("create group state failed."); let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -85,6 +90,7 @@ impl GroupStorage { ), local_device_id, cache: StorageCacheInfo::new(None), + object_map_processor, }) } @@ -129,6 +135,7 @@ impl GroupStorage { let state_path = GroupStatePath::new(rpath.to_string()); let cache = StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -140,6 +147,7 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, cache, + object_map_processor, }) } @@ -905,4 +913,8 @@ impl GroupStorage { status_map, }); } + + pub fn get_object_map_processor(&self) -> &dyn GroupObjectMapProcessor { + &self.object_map_processor + } } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0401c55a0..0fae6dd53 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -38,16 +38,18 @@ mod Common { CyfsStackNOCParams, CyfsStackParams, }; - lazy_static::lazy_static! { - // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + /** + * |--root + * |--folder1 + * |--folder2 + * |--value-->u64 + */ - // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); + pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } fn create_member( @@ -495,7 +497,7 @@ mod Client { } mod GroupDecService { - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, fmt::format, sync::Arc}; use async_std::sync::Mutex; use cyfs_base::*; @@ -503,9 +505,11 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; use cyfs_stack::CyfsStack; + use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; + pub struct DecService {} impl DecService { @@ -580,17 +584,78 @@ mod GroupDecService { } impl MyRPathDelegate { - pub fn execute( + pub async fn get_value_from_state_tree_with_single_op_envs( + pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<( + Option, + Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + )> { + let mut single_op_envs = vec![]; + let mut parent_map_id = pre_state_id; + for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + let single_op_env = object_map_processor.create_single_op_env().await.expect( + format!( + "create_single_op_env load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + parent_map_id = match parent_map_id { + Some(parent_map_id) => { + single_op_env.load(&parent_map_id).await.expect( + format!( + "load folder {} parent with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + single_op_env.get_by_key(folder).await.expect( + format!( + "load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ) + } + None => { + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!( + "create folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + None + } + }; + single_op_envs.push((single_op_env, folder, parent_map_id)); + } + + Ok((parent_map_id, single_op_envs)) + } + + pub async fn execute( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let result_state_id = { + let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await?; + + let result_value = { /** * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); + let pre_value = pre_value.map_or(0, |pre_value| { + let buf = pre_value.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -608,6 +673,32 @@ mod GroupDecService { .unwrap() }; + let result_state_id = { + let mut sub_folder_value = result_value; + for (parent_single_op_env, folder, sub_folder_prev_value) in + single_op_envs.into_iter().rev() + { + parent_single_op_env + .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + .await + .expect( + format!( + "update folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + sub_folder_value = parent_single_op_env.commit().await.expect( + format!( + "commit folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + } + sub_folder_value + }; + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? @@ -623,7 +714,7 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_state_id + proposal + context + * (result_state_id, return_object) = pre_value + proposal + context */ Ok(ExecuteResult { context, @@ -632,17 +723,20 @@ mod GroupDecService { }) } - pub fn verify( + pub async fn verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context */ - let result = self.execute(proposal, pre_state_id)?; + let result = self + .execute(proposal, pre_state_id, object_map_processor) + .await?; let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() @@ -658,23 +752,28 @@ mod GroupDecService { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id) + self.execute(proposal, pre_state_id, object_map_processor) + .await } async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) + self.verify(proposal, pre_state_id, object_map_processor, execute_result) + .await } async fn on_commited( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { @@ -685,14 +784,28 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let pre_value = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); - let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let result_value = Self::get_value_from_state_tree_with_single_op_envs( + execute_result.result_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); @@ -901,7 +1014,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } From daeb0eab0c284b67551395799bdaf5d04635e938 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 19:51:46 +0800 Subject: [PATCH 454/553] Fix: Update the state structure, mount the template dec-state of blocks in prepare/pre-commit, to avoid it's recycled. --- .../cyfs-base/src/objects/object_map/mod.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 5 +- .../cyfs-group/src/statepath/design.md | 12 +- .../src/statepath/group_statepath.rs | 34 +++ .../src/storage/engine/storage_engine.rs | 20 +- .../engine/storage_engine_group_state.rs | 139 ++++++++-- .../src/storage/engine/storage_engine_mock.rs | 7 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 248 +++++++++++------- 9 files changed, 351 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index 3bbc5f131..75589834b 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -18,6 +18,7 @@ mod visitor; pub use access::*; pub use cache::*; pub use diff::*; +pub use isolate_path_env::*; pub use iterator::*; pub use object_map::*; pub use op_env::*; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 0b13d97ce..f5092dbfc 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,6 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -58,4 +60,5 @@ pub trait RPathDelegate: Sync + Send { #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; } diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index cb964e066..885888d5b 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -22,14 +22,20 @@ | |--users | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-vote-round-->u64 // 最后一次投票的 轮次 | |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block | | -| |--prepares->Set // Prepare状态的block -| |--pre-commits->Set // pre-commit状态的block +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 72f48e601..0ed0abd25 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -10,6 +10,8 @@ pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; @@ -164,10 +166,42 @@ impl GroupStatePath { self.prepares.as_str() } + pub fn prepares_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn prepares_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn pre_commits(&self) -> &str { self.pre_commits.as_str() } + pub fn pre_commits_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn finish_proposals(&self) -> &str { self.finish_proposals.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index cbb5d99df..e14445695 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -43,9 +43,19 @@ impl StorageCacheInfo { #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()>; + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + is_instead: bool, + ) -> BuckyResult<()>; + async fn push_commit( &mut self, height: u64, @@ -54,7 +64,9 @@ pub trait StorageWriter: Send + Sync { prev_result_state_id: &Option, min_height: u64, ) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( &mut self, proposal_ids: &[ObjectId], @@ -62,7 +74,9 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index aae81394b..8b8799207 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,14 +2,15 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, - ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -90,7 +91,8 @@ impl StorageEngineGroupState { None => None, }; - let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let prepare_block_ids = + load_object_ids_with_path_map_key(&op_env, state_path.prepares()).await?; if prepare_block_ids.len() == 0 && commit_range.is_none() { return Err(BuckyError::new( BuckyErrorCode::NotFound, @@ -99,7 +101,7 @@ impl StorageEngineGroupState { } let pre_commit_block_ids = - load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + load_object_ids_with_path_map_key(&op_env, state_path.pre_commits()).await?; let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { @@ -113,8 +115,10 @@ impl StorageEngineGroupState { n }); - let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; - let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + let adding_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.adding()).await?; + let over_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.recycle()).await?; let load_block_ids = [ first_header_block_ids.as_slice(), @@ -233,7 +237,7 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new(ObjectMapSimpleContentType::Map) .await?; None } else { @@ -253,20 +257,51 @@ impl StorageEngineGroupStateWriter { }) } - async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn create_block_result_object_map( + &self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult { + let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await?; + single_op_env + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + if let Some(state_id) = result_state_id.as_ref() { + single_op_env + .insert_with_key(GROUP_STATE_PATH_RESULT_STATE, state_id) + .await?; + } + + single_op_env.commit().await + } + + async fn insert_prepares_inner( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) + .await?; self.prepare_op_env - .insert(block_id) + .insert_with_key(block_id.to_string().as_str(), &block_result_pair) .await - .map(|is_changed| assert!(is_changed)) } async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); if is_instead { self.op_env @@ -274,12 +309,17 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self - .op_env - .insert(self.state_path.pre_commits(), block_id) + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) .await?; - assert!(is_changed); - Ok(()) + + self.op_env + .insert_with_key( + self.state_path.pre_commits(), + block_id.to_string().as_str(), + &block_result_pair, + ) + .await } async fn push_commit_inner( @@ -357,8 +397,11 @@ impl StorageEngineGroupStateWriter { async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); } Ok(()) } @@ -486,19 +529,26 @@ impl StorageEngineGroupStateWriter { #[async_trait::async_trait] impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result = self.insert_prepares_inner(block_id, result_state_id).await; self.write_result.clone() } async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result = self + .insert_pre_commit_inner(block_id, result_state_id, is_instead) + .await; self.write_result.clone() } @@ -614,7 +664,7 @@ fn parse_u64_obj(obj: &ObjectId) -> u64 { u64::from_le_bytes(buf) } -async fn load_object_ids_with_path( +async fn load_object_ids_with_path_set( op_env: &ObjectMapPathOpEnvRef, full_path: &str, ) -> BuckyResult> { @@ -647,6 +697,41 @@ async fn load_object_ids_with_path( Ok(object_ids) } +async fn load_object_ids_with_path_map_key( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Map((key_id_base58, _)) => { + object_ids.push(ObjectId::from_base58(key_id_base58)?) + } + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} + fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { match r { Ok(t) => Ok(Some(t)), @@ -690,4 +775,8 @@ impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { async fn create_single_op_env(&self) -> BuckyResult { self.state_mgr.create_single_op_env(ACCESS) } + + async fn create_sub_tree_op_env(&self) -> BuckyResult { + self.state_mgr.create_isolate_path_op_env(ACCESS) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index ebeedd7ca..fbc7cafdc 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -71,7 +71,11 @@ pub struct StorageEngineMockWriter<'a> { #[async_trait::async_trait] impl<'a> StorageWriter for StorageEngineMockWriter<'a> { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { if !self.engine.prepare_blocks.insert(block_id.clone()) { assert!(false); return Err(BuckyError::new( @@ -85,6 +89,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { if !self.engine.prepare_blocks.remove(block_id) { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a1c20f2a..491d029dd 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -291,10 +291,16 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(block_id.object_id()).await?; - if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_prepares(block_id.object_id(), block.result_state_id()) + .await?; + if let Some((new_pre_commit_id, new_pre_commit)) = new_pre_commit.as_ref() { writer - .insert_pre_commit(new_pre_commit, new_header.is_some()) + .insert_pre_commit( + new_pre_commit_id, + new_pre_commit.result_state_id(), + new_header.is_some(), + ) .await?; } if let Some(new_header) = new_header.as_ref() { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0fae6dd53..394b15acb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -584,59 +584,59 @@ mod GroupDecService { } impl MyRPathDelegate { - pub async fn get_value_from_state_tree_with_single_op_envs( - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, - ) -> BuckyResult<( - Option, - Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - )> { - let mut single_op_envs = vec![]; - let mut parent_map_id = pre_state_id; - for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - let single_op_env = object_map_processor.create_single_op_env().await.expect( - format!( - "create_single_op_env load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - parent_map_id = match parent_map_id { - Some(parent_map_id) => { - single_op_env.load(&parent_map_id).await.expect( - format!( - "load folder {} parent with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - single_op_env.get_by_key(folder).await.expect( - format!( - "load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ) - } - None => { - single_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await - .expect( - format!( - "create folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - None - } - }; - single_op_envs.push((single_op_env, folder, parent_map_id)); - } - - Ok((parent_map_id, single_op_envs)) - } + // pub async fn get_value_from_state_tree_with_single_op_envs( + // pre_state_id: Option, + // object_map_processor: &dyn GroupObjectMapProcessor, + // ) -> BuckyResult<( + // Option, + // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + // )> { + // let mut single_op_envs = vec![]; + // let mut parent_map_id = pre_state_id; + // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + // let single_op_env = object_map_processor.create_single_op_env().await.expect( + // format!( + // "create_single_op_env load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // parent_map_id = match parent_map_id { + // Some(parent_map_id) => { + // single_op_env.load(&parent_map_id).await.expect( + // format!( + // "load folder {} parent with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // single_op_env.get_by_key(folder).await.expect( + // format!( + // "load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ) + // } + // None => { + // single_op_env + // .create_new(ObjectMapSimpleContentType::Map) + // .await + // .expect( + // format!( + // "create folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // None + // } + // }; + // single_op_envs.push((single_op_env, folder, parent_map_id)); + // } + + // Ok((parent_map_id, single_op_envs)) + // } pub async fn execute( &self, @@ -644,11 +644,30 @@ mod GroupDecService { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await?; + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + let pre_value = match pre_state_id { + Some(pre_state_id) => { + state_op_env.load(&pre_state_id).await?; + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ) + } + None => { + state_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ); + None + } + }; let result_value = { /** @@ -674,29 +693,50 @@ mod GroupDecService { }; let result_state_id = { - let mut sub_folder_value = result_value; - for (parent_single_op_env, folder, sub_folder_prev_value) in - single_op_envs.into_iter().rev() - { - parent_single_op_env - .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - .await - .expect( - format!( - "update folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value - ) - .as_str(), - ); - sub_folder_value = parent_single_op_env.commit().await.expect( + state_op_env + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .await + .expect( format!( - "commit folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value + "set_with_path {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value ) .as_str(), ); - } - sub_folder_value + state_op_env.commit().await.expect( + format!( + "commit {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value + ) + .as_str(), + ) + // let mut sub_folder_value = result_value; + // for (parent_single_op_env, folder, sub_folder_prev_value) in + // single_op_envs.into_iter().rev() + // { + // parent_single_op_env + // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + // .await + // .expect( + // format!( + // "update folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // sub_folder_value = parent_single_op_env.commit().await.expect( + // format!( + // "commit folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // } + // sub_folder_value }; let receipt = { @@ -784,13 +824,26 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let pre_value = match pre_state_id { + Some(pre_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&pre_state_id) + .await + .expect(format!("load {} failed", pre_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; @@ -798,13 +851,26 @@ mod GroupDecService { u64::from_be_bytes(pre_value) }); - let result_value = Self::get_value_from_state_tree_with_single_op_envs( - execute_result.result_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let result_value = match execute_result.result_state_id { + Some(result_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&result_state_id) + .await + .expect(format!("load {} failed", result_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; From 2d303741d78867d70f5ca1874e3c1a5234d591cc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:00 +0800 Subject: [PATCH 455/553] Accept the invalid block with vote it. --- src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 138 +++++++++++++----- .../cyfs-group/src/storage/group_storage.rs | 102 +------------ 3 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index aaab4ed76..4a7aae6c2 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' +itertools = "0.10.3" cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d9773bd88..511b0b32e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -13,6 +13,7 @@ use cyfs_core::{ }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; +use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, @@ -365,7 +366,7 @@ impl HotstuffRunner { } } - let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, Err(err) => return err }; @@ -391,9 +392,6 @@ impl HotstuffRunner { self, block.block_id()); - self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await?; - self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -402,7 +400,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote, &proposals).await + self.process_block(block, remote, &HashMap::new()).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -574,7 +572,7 @@ impl HotstuffRunner { } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { match self.store.block_linked(block).await .map_err(|err| Err(err))? { @@ -585,16 +583,6 @@ impl HotstuffRunner { ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - Err (Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - ))) - } crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", @@ -605,7 +593,7 @@ impl HotstuffRunner { "duplicate block", ))) } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { + crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", self, @@ -614,7 +602,7 @@ impl HotstuffRunner { // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; - Ok((prev_block, proposals)) + Ok(prev_block) } crate::storage::BlockLinkState::Pending => { log::warn!( @@ -942,20 +930,6 @@ impl HotstuffRunner { return None; } - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 - let mut proposal_temp: HashMap = HashMap::new(); - if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { - Ok(_) => proposals = &proposal_temp, - Err(_) => return None - } - } else { - assert_eq!(proposals.len(), block.proposals().len()); - } - if !Self::check_timestamp_precision(block, proposals) { - return None; - } - // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -982,6 +956,22 @@ impl HotstuffRunner { return None; } + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block.clone()), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None + }, + }, + None => None + }; + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -993,6 +983,77 @@ impl HotstuffRunner { } } + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + return None + } + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + return None; + } + + if proposals.len() != block.proposals().len() { + let mut dup_proposals = block.proposals().clone(); + dup_proposals.sort_unstable_by_key(|p| p.proposal); + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + ); + return None; + } + + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + match block.prev_block_id() { + Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await.map(|is_finished| (is_finished, &proposal_result.proposal)), + None => Ok((false, &proposal_result.proposal)) + } + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok((is_finished, proposal_id)) => { + if is_finished { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + proposal_id + ); + return None; + } + }, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", + self, + block.block_id(), + err + ); + return None; + }, + } + } + + if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await.is_err() { + return None; + } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1021,12 +1082,23 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { false } else { + if let Some(prev_block) = prev_block { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { + if duration > TIME_PRECISION { + return false + } + } + } + for proposal in block.proposals() { let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 491d029dd..04e4c80fc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,22 +1,19 @@ -use std::{ - collections::{HashMap, HashSet}, - time::SystemTime, -}; +use std::collections::{HashMap, HashSet}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ @@ -31,11 +28,10 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, - DuplicateProposal, Duplicate, Link( Option, - HashMap, + // HashMap, ), // Pending, InvalidBranch, @@ -528,18 +524,6 @@ impl GroupStorage { return Ok(BlockLinkState::Duplicate); } - let now = SystemTime::now(); - let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); - - if let Ok(duration) = block_time.duration_since(now) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } - log::debug!( "[group storage] {} block_linked {} step2", self.local_device_id, @@ -554,17 +538,6 @@ impl GroupStorage { } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); - if let Ok(duration) = prev_block_time.duration_since(block_time) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } Some(prev_block) } } @@ -592,66 +565,7 @@ impl GroupStorage { block.block_id() ); - let mut proposals = HashMap::new(); - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? - { - return Ok(BlockLinkState::DuplicateProposal); - } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - - Ok(BlockLinkState::Link( - None, - HashMap::from([(proposal_result.proposal, proposal)]), - )) - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok(result) => match result { - BlockLinkState::Link(_, proposal) => { - let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); - if proposals.get(&proposal_id).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } - proposals.insert(proposal_id, proposal); - } - _ => return Ok(result), - }, - _ => return check_result, - } - } - - log::debug!( - "[group storage] {} block_linked {} step4", - self.local_device_id, - block.block_id() - ); - - Ok(BlockLinkState::Link(prev_block, proposals)) + Ok(BlockLinkState::Link(prev_block)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From abb2ae4e91efaa08b9e5292a0acc0e81f051bc1e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:55 +0800 Subject: [PATCH 456/553] Chore unused code --- src/component/cyfs-group/src/storage/group_storage.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 04e4c80fc..122ae72ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -29,10 +29,7 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, Duplicate, - Link( - Option, - // HashMap, - ), // + Link(Option), // Pending, InvalidBranch, } From ee43170137db2f15b936ed898180d0007fdf9ede Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 12:20:23 +0800 Subject: [PATCH 457/553] get VerifiableState from the admin --- .../src/consensus/hotstuff/hotstuff.rs | 260 +++++++++++------- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 2 +- src/component/cyfs-group/src/constant.rs | 2 +- .../src/dec_state/dec_state_requestor.rs | 5 + .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../src/objects/group_rpath_status.rs | 21 +- .../cyfs-group/src/objects/protocol.rs | 11 +- .../cyfs-group/src/storage/dec_storage.rs | 6 + .../cyfs-group/src/storage/group_storage.rs | 27 +- src/tests/group-example/Cargo.toml | 3 +- src/tests/group-example/src/main.rs | 79 +++++- 11 files changed, 302 insertions(+), 116 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 511b0b32e..10c5d9635 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -4,7 +4,7 @@ use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, + RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -19,11 +19,13 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * + * synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -212,6 +214,7 @@ struct HotstuffRunner { round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, + max_quorum_round: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -311,6 +314,7 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, + max_quorum_round: round - 1, state_pusher, tx_block_gen, rx_block_gen, @@ -366,15 +370,6 @@ impl HotstuffRunner { } } - let prev_block = match self.check_block_linked(&block, remote).await { - Ok(link) => link, - Err(err) => return err - }; - - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", - self, - block.block_id()); - self.committee .verify_block(block, remote) .await @@ -388,6 +383,18 @@ impl HotstuffRunner { err })?; + let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); + self.update_max_quorum_round(quorum_round); + + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + + let prev_block = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err + }; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", self, block.block_id()); @@ -452,10 +459,19 @@ impl HotstuffRunner { block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, + remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = prev_block - .as_ref() - .map_or(None, |block| block.result_state_id().clone()); + let mut prev_state_id = match prev_block + .as_ref() { + Some(prev_block) => { + let result_state_id = block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; + } + result_state_id.clone() + }, + None => None + }; for proposal_exe_info in block.proposals() { // 去重 @@ -672,7 +688,7 @@ impl HotstuffRunner { err })?; - if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", self, header_block.block_id() @@ -696,29 +712,18 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(header_block.clone(), qc_block).await; + self.notify_block_committed(&header_block, &old_header_block, qc_block).await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", self, block.block_id() ); - let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self, self.round, err - ); - - err - }); - // notify by leader - if let Ok(leader) = leader { - if self.local_device_id == leader { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } + if &self.local_id == header_block.owner() { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; } log::debug!( @@ -733,7 +738,7 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, the qc of block {:?} has received before", self, block.block_id() ); - return self.process_block_qc(qc, block, remote).await; + return self.process_block_qc(qc, block).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( @@ -762,7 +767,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block, proposals).await { + if let Some(vote) = self.make_vote(block, proposals, &remote).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -791,22 +796,12 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - let mut pre_state_id = match new_header.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); + + let mut pre_state_id = old_header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); for proposal in new_header.proposals() { let proposal_obj = self @@ -900,6 +895,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_round(&mut self, quorum_round: u64) { + if quorum_round > self.max_quorum_round { + self.max_quorum_round = quorum_round; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -922,7 +923,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -930,6 +931,13 @@ impl HotstuffRunner { return None; } + if self.max_quorum_round >= self.round { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } + // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -1002,6 +1010,10 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + self, + block.block_id(), + ); return None; } @@ -1016,44 +1028,15 @@ impl HotstuffRunner { return None; } - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - match block.prev_block_id() { - Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await.map(|is_finished| (is_finished, &proposal_result.proposal)), - None => Ok((false, &proposal_result.proposal)) - } - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok((is_finished, proposal_id)) => { - if is_finished { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", - self, - block.block_id(), - proposal_id - ); - return None; - } - }, - Err(err) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", - self, - block.block_id(), - err - ); - return None; - }, - } + if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err + ); + return None; } - if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await.is_err() { - return None; - } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1075,7 +1058,12 @@ impl HotstuffRunner { } }; - if self.store.set_last_vote_round(block.round()).await.is_err() { + if let Err(err) = self.store.set_last_vote_round(block.round()).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for update last-vote-round failed {:?}", + self, + block.block_id(), + err + ); return None; } @@ -1086,23 +1074,39 @@ impl HotstuffRunner { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + block.block_id(), + block_timestamp, + now + ); + false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); + let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + block.block_id(), + block_timestamp, + prev_block_time + ); return false } } } for proposal in block.proposals() { - let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_id = proposal.proposal; + let proposal = proposals.get(&proposal_id).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + block.block_id(), + block_timestamp, + proposal_id, + proposal_timestamp + ); return false } } @@ -1174,7 +1178,7 @@ impl HotstuffRunner { if is_prev_none {"None"} else {"Some"} ); - self.process_block_qc(qc, &block, remote).await?; + self.process_block_qc(qc, &block).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1185,7 +1189,6 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, - remote: ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1334,7 +1337,10 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - + + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1453,6 +1459,9 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1501,8 +1510,7 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ) - .await.map_err(|err| { + ).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", self, err @@ -1541,7 +1549,13 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let prev_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), + Some(qc) => { + let prev_block = self.store.find_block_in_cache(&qc.block_id)?; + if let Some(result_state_id) = prev_block.result_state_id() { + self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + } + Some(prev_block) + }, None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1940,6 +1954,58 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } + async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 + let obj_map_processor = self.store.get_object_map_processor(); + + #[async_recursion::async_recursion] + async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if non_driver.get_object(&root_id, None).await.is_ok() { + // TODO: 可能有下级分支子树因为异常不齐全 + return Ok(()); + } + let obj = non_driver.get_object(root_id, Some(remote)).await?; + match obj.object.as_ref() { + Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { + let single_op_env = obj_map_processor.create_single_op_env().await?; + single_op_env.load(root_id).await?; + loop { + let branchs = single_op_env.next(16).await?; + for branch in branchs.list.iter() { + let branch_id = match branch { + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Map(map) => &map.1, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Set(set) => set, + }; + make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + } + + if branchs.list.len() < 16 { + return Ok(()) + } + } + }, + _ => return Ok(()) + } + } + + let mut result = Ok(()); + for remote in remotes { + result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + if result.is_ok() { + return result; + } + } + result + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 82f4017a0..f44260a04 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 1170176b2..77a652a7e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,7 +17,7 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; -pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(5000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 0a3544c09..790429c6c 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -154,6 +154,11 @@ impl DecStateRequestorRunner { .await .map(|r| r.cloned()); + log::debug!( + "handle_verifiable_state sub_path: {}, result: {:?}", + sub_path, + result + ); self.query_state_notifier.reply(&sub_path, result).await } Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cc0b4aff2..b1506a192 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -13,7 +13,7 @@ use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), - BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), // LastStateRequest(ObjectId), DelayBroadcast, } diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index 858c37fff..bfc9bc5d2 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -69,8 +69,25 @@ impl<'de> RawDecode<'de> for GroupRPathStatus { assert_eq!(remain.len(), 0); let mut status_map = HashMap::new(); for obj_buf in proto.status_list.iter() { - let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; - assert_eq!(remain.len(), 0); + log::debug!("will decode len: {}", obj_buf.len()); + // size + object_id + let status = if obj_buf.len() > OBJECT_ID_LEN + 1 { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status + } else if obj_buf.len() == OBJECT_ID_LEN + 1 { + NONObjectInfo::new( + ObjectId::clone_from_slice(&obj_buf.as_slice()[1..])?, + obj_buf.clone(), + None, + ) + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidData, + "expect NONObjectInfo", + )); + }; + status_map.insert(status.object_id, status); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 6c9f89e96..932e5cd46 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use itertools::Itertools; use sha2::Digest; use crate::GroupRPathStatus; @@ -185,12 +186,13 @@ impl std::fmt::Debug for HotstuffMessage { result.as_ref().map(|status| { let desc = status.block_desc.content(); format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ) }) ) @@ -315,12 +317,13 @@ impl std::fmt::Debug for HotstuffPackage { |status| { let desc = status.block_desc.content(); let ok = format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ); Ok(ok) } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index de5a0fd4a..60a45724f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -69,6 +69,10 @@ impl DecStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { Some(state) => state, None => return Ok(None), @@ -98,6 +102,8 @@ impl DecStorage { assert_eq!(remain.len(), 0); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 122ae72ab..966fa518a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, - ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, @@ -223,7 +223,13 @@ impl GroupStorage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - ) -> BuckyResult)>> { + ) -> BuckyResult< + Option<( + &GroupConsensusBlock, + Option, + Vec, + )>, + > { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); @@ -399,9 +405,10 @@ impl GroupStorage { } } - self.cache.header_block = Some(new_header); + let old_header_block = self.cache.header_block.replace(new_header); return Ok(Some(( self.cache.header_block.as_ref().unwrap(), + old_header_block, removed_blocks, ))); } @@ -736,6 +743,7 @@ impl GroupStorage { } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + // TODO: 需要一套通用的同步ObjectMap树的实现 let (header_block, qc) = match self.cache.header_block.as_ref() { Some(block) => { let (_, qc_block) = self @@ -778,6 +786,9 @@ impl GroupStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { @@ -806,6 +817,8 @@ impl GroupStorage { status_map.insert(parent_state_id, parent_state); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder @@ -821,7 +834,11 @@ impl GroupStorage { } } - let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + let leaf_state = if parent_state_id.is_data() { + NONObjectInfo::new(parent_state_id, parent_state_id.to_vec()?, None) + } else { + self.non_driver.get_object(&parent_state_id, None).await? + }; status_map.insert(parent_state_id, leaf_state); return Ok(GroupRPathStatus { diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 0053ccd5f..01094f12a 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -27,4 +27,5 @@ cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } -cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 394b15acb..618336df4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -14,7 +14,7 @@ use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; mod Common { use std::{fmt::format, io::ErrorKind, sync::Arc}; @@ -505,8 +505,15 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + use cyfs_group::{ + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, + }; + use cyfs_lib::{ + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, + }; use cyfs_stack::CyfsStack; + use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -522,10 +529,42 @@ mod GroupDecService { Box::new(GroupRPathDelegateFactory { local_name }), ) .await - .unwrap() + .unwrap(); + + // let source = RequestSourceInfo { + // protocol: todo!(), + // zone: todo!(), + // dec: todo!(), + // verified: todo!(), + // }; + + // cyfs_stack + // .router_handlers() + // .handlers(&RouterHandlerChain::PostRouter) + // .post_object() + // .add_handler(RouterHandler::new()); } } + // pub struct PostProposalRoutine { + // controller: RPathControl, + // } + + // #[async_trait::async_trait] + // impl EventListenerAsyncRoutine + // for PostProposalRoutine + // { + // async fn call( + // &self, + // param: &NONPostObjectInputRequest, + // ) -> BuckyResult { + // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // self.controller.push_proposal(proposal).await?; + // Ok(NONPostObjectInputResponse { object: None }) + // } + // } + pub struct GroupRPathDelegateFactory { local_name: String, } @@ -778,6 +817,16 @@ mod GroupDecService { .execute(proposal, pre_state_id, object_map_processor) .await?; + log::info!( + "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + execute_result.result_state_id, + execute_result.context.is_none(), + execute_result.receipt.is_none(), + result.result_state_id, + result.context.is_none(), + result.receipt.is_none() + ); + let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() && execute_result.receipt.is_none(); @@ -1007,7 +1056,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 1000usize; + let PROPOSAL_COUNT = 5usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1085,6 +1134,28 @@ async fn main_run() { log::info!("will push new proposals, i: {}", i); } } + + let client = admin_stacks + .get(0) + .unwrap() + .group_mgr() + .rpath_client( + &group.desc().object_id(), + dec_app_id.object_id(), + &EXAMPLE_RPATH, + ) + .await + .unwrap(); + + let value_obj = client + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .unwrap(); + let buf = value_obj.as_ref().unwrap().object_id.data(); + let mut value = [0u8; 8]; + value.copy_from_slice(&buf[..8]); + + log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From c47886f14393cf2ed8f14131436dea53f3241e0b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 15:46:00 +0800 Subject: [PATCH 458/553] Fix: result-state verify failed --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++++++++++++++---- src/tests/group-example/src/main.rs | 3 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 10c5d9635..e142d4069 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -464,7 +464,7 @@ impl HotstuffRunner { let mut prev_state_id = match prev_block .as_ref() { Some(prev_block) => { - let result_state_id = block.result_state_id(); + let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; } @@ -520,14 +520,24 @@ impl HotstuffRunner { err })? { + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); + prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", self, proposal_exe_info.proposal, - prev_state_id, - proposal_exe_info.result_state + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); @@ -966,7 +976,7 @@ impl HotstuffRunner { let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block.clone()), + Ok(block) => Some(block), Err(_) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", self, @@ -1960,11 +1970,18 @@ impl HotstuffRunner { #[async_recursion::async_recursion] async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if root_id.is_data() { + return Ok(()); + } + if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await?; + let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { + log::warn!("get branch {} failed {:?}", root_id, err); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { let single_op_env = obj_map_processor.create_single_op_env().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 618336df4..4daa0d4f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -818,7 +818,8 @@ mod GroupDecService { .await?; log::info!( - "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + pre_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), From 8f054488b046797059b6aacd605d383a657dded6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 28 Feb 2023 20:27:49 +0800 Subject: [PATCH 459/553] Redefine the Group object for Permission --- .../protos/standard_objects-permission.proto | 203 ++++++++++++++++++ src/tests/group-example/src/main.rs | 8 +- 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto new file mode 100644 index 000000000..b2ec61f60 --- /dev/null +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -0,0 +1,203 @@ +syntax="proto3"; + +// contract +message ContractBodyContent { + bytes data = 1; +} + +// device +message DeviceBodyContent { + repeated bytes endpoints = 1; + repeated bytes sn_list = 2; + repeated bytes passive_pn_list = 3; + optional string name = 4; + optional uint32 bdt_version = 5; +} + +// dir +message DirBodyContent { + enum Type { + Chunk = 0; + ObjList = 1; + } + Type type = 1; + optional bytes chunk_id = 2; + + // 使用list编码hash_map + message ObjItem { + bytes obj_id = 1; + bytes value = 2; + } + repeated ObjItem obj_list = 3; +} + +// file +message ChunkList { + enum Type { + ChunkInList = 0; + ChunkInFile = 1; + ChunkInBundle = 2; + } + enum HashMethod { + Serial = 0; + } + + Type type = 1; + repeated bytes chunk_id_list = 2; + bytes file_id = 3; + optional HashMethod hash_method = 4; +} + +message FileBodyContent { + ChunkList chunk_list = 1; +} + +// people +message PeopleBodyContent { + repeated bytes ood_list = 1; + optional string name = 2; + optional bytes icon = 3; + optional string ood_work_mode = 4; +} + +message GroupRPathPermissionWeight { + string rpath = 1; + GroupFunctionPermissionWeight weight = 2; +} + +message GroupDecPermissionWeight { + bytes dec_id = 1; + optional GroupRPathPermissionWeight default_dec_weight = 2; + repeated GroupRPathPermissionWeight rpath_weight = 3; +} + +message GroupMember { + bytes id = 1; + string title = 2; + // uint64 shares = 3; delay + optional GroupGlobalPermissionWeight global_weight = 4; + optional GroupDecPermissionWeight weight = 5; +} + +/** +admin 修改管理员列表 +member 修改成员列表 +display-${scope} 修改展示信息 + ${scope}=g: 修改group信息 + ${scope}=s: 修改自身信息 + ${scope}=m: 修改任意member信息 + ${scope}=a: 修改任意admin信息 +property 修改资产信息 +conclusion 修改决议类别列表 +conclusion-${category} 修改决议类别配置 +it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) +c-${any} 其他自定义(custom)权限 +*/ + +message GroupGlobalPermissionWeight { + optional uint32 admin = 1; + optional uint32 member = 2; + optional uint32 display_group = 3; + optional uint32 display_self = 4; + optional uint32 display_member = 5; + optional uint32 display_admin = 6; + optional uint32 property = 7; +} + +message GroupCommonPermissionWeight { + string category = 1; + uint32 weight = 2; +} + +message GroupFunctionPermissionWeight { + optional uint32 it = 1; + optional uint32 conclusion = 2; + repeated GroupCommonPermissionWeight conclusion_category = 3; + repeated GroupCommonPermissionWeight custom = 4; +} + +message GroupITConfig { + repeated bytes ood_list = 8; + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms +} + +message GroupConclusionConfig { + string category = 1; + uint64 lifespan = 2; // ms +} + +message GroupConfigItem { + optional GroupITConfig it = 1; + repeated GroupConclusionConfig conclusions = 2; + optional GroupFunctionPermissionWeight weight_threshold = 3; +} + +message GroupRPathConfig { + string rpath = 1; + GroupConfigItem config = 2; +} + +message GroupDecConfig { + bytes dec_id = 1; + optional GroupConfigItem default_dec_config = 2; + repeated GroupRPathConfig rpath_configs = 3; +} + +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; + + repeated GroupMember members = 4; + + // uint64 total_equity = 5; // delay + + repeated bytes revoked_conclusions = 6; + + GroupConfigItem default_config = 7; + repeated GroupDecConfig dec_configs = 8; + + GroupGlobalPermissionWeight global_weight_threshold = 9; + GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + + uint64 version = 11; +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} + +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} + +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; +} + +// tx +message TxBodyContent { + bytes data = 1; +} + +// proof_of_service +message ProofData { + bytes data = 1; +} + +message ProofOfServiceBodyContent { + ProofData data = 1; +} \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 4daa0d4f1..ef2366de0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1051,13 +1051,13 @@ async fn main_run() { .unwrap(); } - async_std::task::sleep(Duration::from_millis(30000)).await; + async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 5usize; + let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1130,12 +1130,14 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } + async_std::task::sleep(Duration::from_millis(10000)).await; + let client = admin_stacks .get(0) .unwrap() From 4a6d79ffef3722dc94224e0b24a5e0d5b368e299 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 14:41:55 +0800 Subject: [PATCH 460/553] Simplify group definition --- .../protos/standard_objects-permission.proto | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto index b2ec61f60..09f9e3684 100644 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -60,89 +60,9 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } -message GroupRPathPermissionWeight { - string rpath = 1; - GroupFunctionPermissionWeight weight = 2; -} - -message GroupDecPermissionWeight { - bytes dec_id = 1; - optional GroupRPathPermissionWeight default_dec_weight = 2; - repeated GroupRPathPermissionWeight rpath_weight = 3; -} - message GroupMember { bytes id = 1; string title = 2; - // uint64 shares = 3; delay - optional GroupGlobalPermissionWeight global_weight = 4; - optional GroupDecPermissionWeight weight = 5; -} - -/** -admin 修改管理员列表 -member 修改成员列表 -display-${scope} 修改展示信息 - ${scope}=g: 修改group信息 - ${scope}=s: 修改自身信息 - ${scope}=m: 修改任意member信息 - ${scope}=a: 修改任意admin信息 -property 修改资产信息 -conclusion 修改决议类别列表 -conclusion-${category} 修改决议类别配置 -it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) -c-${any} 其他自定义(custom)权限 -*/ - -message GroupGlobalPermissionWeight { - optional uint32 admin = 1; - optional uint32 member = 2; - optional uint32 display_group = 3; - optional uint32 display_self = 4; - optional uint32 display_member = 5; - optional uint32 display_admin = 6; - optional uint32 property = 7; -} - -message GroupCommonPermissionWeight { - string category = 1; - uint32 weight = 2; -} - -message GroupFunctionPermissionWeight { - optional uint32 it = 1; - optional uint32 conclusion = 2; - repeated GroupCommonPermissionWeight conclusion_category = 3; - repeated GroupCommonPermissionWeight custom = 4; -} - -message GroupITConfig { - repeated bytes ood_list = 8; - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms -} - -message GroupConclusionConfig { - string category = 1; - uint64 lifespan = 2; // ms -} - -message GroupConfigItem { - optional GroupITConfig it = 1; - repeated GroupConclusionConfig conclusions = 2; - optional GroupFunctionPermissionWeight weight_threshold = 3; -} - -message GroupRPathConfig { - string rpath = 1; - GroupConfigItem config = 2; -} - -message GroupDecConfig { - bytes dec_id = 1; - optional GroupConfigItem default_dec_config = 2; - repeated GroupRPathConfig rpath_configs = 3; } message CommonGroupBodyContent { @@ -152,17 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - // uint64 total_equity = 5; // delay - - repeated bytes revoked_conclusions = 6; - - GroupConfigItem default_config = 7; - repeated GroupDecConfig dec_configs = 8; - - GroupGlobalPermissionWeight global_weight_threshold = 9; - GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + repeated bytes ood_list = 5; - uint64 version = 11; + optional bytes prev_version = 6; + uint64 version_num = 7; } // simple_group @@ -184,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx From f3591ab3a53f3f3e3225192a1a6fe85e5cfa955e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 20:16:27 +0800 Subject: [PATCH 461/553] Move the interface to cyfs-lib --- .../src/consensus/hotstuff/hotstuff.rs | 8 +++--- .../cyfs-group/src/dec/group_manager.rs | 6 ++--- src/component/cyfs-group/src/dec/mod.rs | 6 ++--- .../cyfs-group/src/dec/rpath_control.rs | 3 ++- .../engine/storage_engine_group_state.rs | 6 ++--- .../cyfs-group/src/storage/group_storage.rs | 6 ++--- .../src/group}/delegate_factory.rs | 2 +- .../cyfs-lib/src/group/group_manager.rs | 20 ++++++++++++++ src/component/cyfs-lib/src/group/mod.rs | 7 +++++ .../cyfs-lib/src/group/rpath_client.rs | 27 +++++++++++++++++++ src/component/cyfs-lib/src/lib.rs | 6 +++-- src/tests/group-example/src/main.rs | 8 +++--- 12 files changed, 79 insertions(+), 26 deletions(-) rename src/component/{cyfs-group/src/dec => cyfs-lib/src/group}/delegate_factory.rs (98%) create mode 100644 src/component/cyfs-lib/src/group/group_manager.rs create mode 100644 src/component/cyfs-lib/src/group/mod.rs create mode 100644 src/component/cyfs-lib/src/group/rpath_client.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e142d4069..52dcdd650 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,15 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, + GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7b7fbbbe..60ddba1fb 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,11 +6,11 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; use crate::{ - storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, + NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index b4e753a27..8a43844b2 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,11 +1,9 @@ // dec framework -mod delegate_factory; +mod group_manager; mod rpath_client; mod rpath_control; -mod group_manager; -pub use delegate_factory::*; +pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 7abff1ec1..c3a25b060 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,10 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathDelegate, + PendingProposalHandler, PendingProposalMgr, }; struct RPathControlRaw { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 8b8799207..adf11c7e4 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,11 +6,11 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_lib::GroupObjectMapProcessor; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, - GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, - GROUP_STATE_PATH_RESULT_STATE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 966fa518a..fa6f4930f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,11 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-lib/src/group/delegate_factory.rs similarity index 98% rename from src/component/cyfs-group/src/dec/delegate_factory.rs rename to src/component/cyfs-lib/src/group/delegate_factory.rs index f5092dbfc..9e55ff8f4 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-lib/src/group/delegate_factory.rs @@ -1,8 +1,8 @@ +use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-lib/src/group/group_manager.rs new file mode 100644 index 000000000..7d836ae49 --- /dev/null +++ b/src/component/cyfs-lib/src/group/group_manager.rs @@ -0,0 +1,20 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +use crate::{DelegateFactory, RPathClient}; + +#[derive(Clone)] +pub struct GroupManager; + +impl GroupManager { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self) { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-lib/src/group/mod.rs new file mode 100644 index 000000000..482d9ea0d --- /dev/null +++ b/src/component/cyfs-lib/src/group/mod.rs @@ -0,0 +1,7 @@ +mod delegate_factory; +mod group_manager; +mod rpath_client; + +pub use delegate_factory::*; +pub use group_manager::*; +pub use rpath_client::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-lib/src/group/rpath_client.rs new file mode 100644 index 000000000..4162abe68 --- /dev/null +++ b/src/component/cyfs-lib/src/group/rpath_client.rs @@ -0,0 +1,27 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{GroupProposal, GroupRPath}; + +use crate::NONObjectInfo; + +struct RPathClientRaw {} + +#[derive(Clone)] +pub struct RPathClient(Arc); + +impl RPathClient { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index f74e62985..d2f02315a 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,9 +4,11 @@ mod base; mod crypto; mod default_app; mod events; +mod group; mod ndn; mod non; mod prelude; +mod requestor; mod rmeta; mod root_state; mod router_handler; @@ -17,7 +19,6 @@ mod trans; mod util; mod ws; mod zone; -mod requestor; pub use crate::util::*; pub use acl::*; @@ -26,9 +27,11 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; +pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; +pub use requestor::*; pub use rmeta::*; pub use root_state::*; pub use router_handler::*; @@ -38,7 +41,6 @@ pub use sync::*; pub use trans::*; pub use ws::*; pub use zone::*; -pub use requestor::*; // 重新导出cache相关接口,由于bdt层的依赖关系,只能放在util工程 pub use cyfs_util::cache::*; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ef2366de0..42544e51c 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,12 +505,10 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, - }; + use cyfs_group::RPathControl; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, + NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, }; use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; From d6f9b6c39a7cc80d977d8cc2e6db677351d699c1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 12:20:30 +0800 Subject: [PATCH 462/553] Remove the `decide` from proposal, It seems unuseful --- .../cyfs-core/protos/core_objects.proto | 9 +- .../cyfs-core/src/group/group_proposal.rs | 415 +++++++++--------- src/component/cyfs-core/src/group/mod.rs | 10 +- 3 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 487ece4bd..abd299e9d 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -352,7 +352,7 @@ message GroupProposalDescContent { message GroupProposalBodyContent { optional bytes payload = 1; - +/* message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; @@ -360,8 +360,10 @@ message GroupProposalBodyContent { } repeated Signature decide_signatures = 2; +*/ } +/* message GroupUpdateGroupPropsalParam { repeated bytes target_dec_id = 1; // the proccesor decs optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) @@ -373,6 +375,7 @@ message GroupPropsalDecideParam { bytes proposal_id = 2; bytes decide = 3; } +*/ message HotstuffBlockQc { bytes block_id = 1; @@ -431,6 +434,7 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } +/* message GroupActionDescContent { // target GroupRPath r_path = 1; @@ -441,4 +445,5 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 10aeed798..bf28aafb2 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,4 +1,4 @@ -use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; +use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use sha2::Digest; @@ -34,45 +34,44 @@ impl DescContent for GroupProposalDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone)] -pub struct GroupProposalSignature { - signature: Signature, - proponent_id: ObjectId, - decide: Vec, -} - -impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> - for GroupProposalSignature -{ - fn transform( - value: &crate::codec::protos::group_proposal_body_content::Signature, - ) -> BuckyResult { - Ok(Self { - signature: Signature::raw_decode(value.signature.as_slice())?.0, - proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, - decide: value.decide.clone(), - }) - } -} - -impl ProtobufTransform<&GroupProposalSignature> - for crate::codec::protos::group_proposal_body_content::Signature -{ - fn transform(value: &GroupProposalSignature) -> BuckyResult { - Ok(Self { - signature: value.signature.to_vec()?, - proponent_id: value.proponent_id.to_vec()?, - decide: value.decide.clone(), - }) - } -} +// #[derive(Clone)] +// pub struct GroupProposalSignature { +// signature: Signature, +// proponent_id: ObjectId, +// decide: Vec, +// } + +// impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> +// for GroupProposalSignature +// { +// fn transform( +// value: &crate::codec::protos::group_proposal_body_content::Signature, +// ) -> BuckyResult { +// Ok(Self { +// signature: Signature::raw_decode(value.signature.as_slice())?.0, +// proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, +// decide: value.decide.clone(), +// }) +// } +// } + +// impl ProtobufTransform<&GroupProposalSignature> +// for crate::codec::protos::group_proposal_body_content::Signature +// { +// fn transform(value: &GroupProposalSignature) -> BuckyResult { +// Ok(Self { +// signature: value.signature.to_vec()?, +// proponent_id: value.proponent_id.to_vec()?, +// decide: value.decide.clone(), +// }) +// } +// } #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] pub struct GroupProposalBodyContent { payload: Option>, - - decide_signatures: Vec, + // decide_signatures: Vec, } impl BodyContent for GroupProposalBodyContent { @@ -85,14 +84,14 @@ impl ProtobufTransform for GroupProposalBodyContent { fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push(GroupProposalSignature::transform(sign)?); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push(GroupProposalSignature::transform(sign)?); + // } Ok(Self { payload: value.payload, - decide_signatures, + // decide_signatures, }) } } @@ -101,16 +100,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> for crate::codec::protos::GroupProposalBodyContent { fn transform(value: &GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push( - crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, - ); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push( + // crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + // ); + // } Ok(Self { payload: value.payload.clone(), - decide_signatures, + // decide_signatures, }) } } @@ -143,17 +142,17 @@ impl GroupProposalDescContent { } impl GroupProposalBodyContent { - fn hash_decide_signature( - proposal_id: &ObjectId, - proponent_id: &ObjectId, - decide: &[u8], - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(proposal_id.as_slice()); - sha256.input(proponent_id.as_slice()); - sha256.input(decide); - sha256.result().into() - } + // fn hash_decide_signature( + // proposal_id: &ObjectId, + // proponent_id: &ObjectId, + // decide: &[u8], + // ) -> HashValue { + // let mut sha256 = sha2::Sha256::new(); + // sha256.input(proposal_id.as_slice()); + // sha256.input(proponent_id.as_slice()); + // sha256.input(decide); + // sha256.result().into() + // } } #[async_trait] @@ -182,27 +181,27 @@ pub trait GroupProposalObject { fn payload(&self) -> &Option>; fn set_payload(&mut self, payload: Option>); - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult>; - - fn decided_members_no_verify(&self) -> &Vec; - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult; - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()>; + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult>; + + // fn decided_members_no_verify(&self) -> &Vec; + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult; + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()>; } #[async_trait] @@ -231,7 +230,7 @@ impl GroupProposalObject for GroupProposal { desc, GroupProposalBodyContent { payload, - decide_signatures: vec![], + // decide_signatures: vec![], }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) @@ -252,9 +251,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { - Some(params) => { - HashValue::try_from(params.as_slice()).map(|h| Some(h)) - } + Some(params) => HashValue::try_from(params.as_slice()).map(|h| Some(h)), None => Ok(None), } } @@ -298,134 +295,130 @@ impl GroupProposalObject for GroupProposal { self.body_mut().as_mut().unwrap().content_mut().payload = payload; } - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult> { - let signs = self - .body() - .as_ref() - .unwrap() - .content() - .decide_signatures - .as_slice(); - - let proposal_id = self.desc().object_id(); - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - - let mut decides = vec![]; - - for sign in signs { - if &sign.proponent_id == member_id { - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &sign.proponent_id, - sign.decide.as_slice(), - ); - - if verifier.verify(hash.as_slice(), &sign.signature).await { - decides.push(sign.decide.as_slice()); - } else { - return Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )); - } - } - } - - Ok(decides) - } - - fn decided_members_no_verify(&self) -> &Vec { - &self.body().as_ref().unwrap().content().decide_signatures - } - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult { - let signs = &self.body().as_ref().unwrap().content().decide_signatures; - - if signs.iter().find(|s| s.proponent_id == member_id).is_some() { - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicated decide", - )); - } - - let proposal_id = self.desc().object_id(); - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.as_slice(), - ); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - let sign = signer - .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) - .await?; - - Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) - } - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()> { - let proposal_id = self.desc().object_id(); - - if decide.proposal_id() != &proposal_id { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - format!( - "proposal id not match for decide signature: {}/{}", - proposal_id, - decide.proposal_id() - ), - )); - } - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.decide(), - ); - - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - if verifier.verify(hash.as_slice(), decide.signature()).await { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - for exist in signs.iter() { - if &exist.proponent_id == &member_id && exist.decide == decide.decide() { - return Ok(()); - } - } - - signs.push(GroupProposalSignature { - signature: decide.signature().clone(), - proponent_id: member_id, - decide: Vec::from(decide.decide()), - }); - - Ok(()) - } else { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )) - } - } + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult> { + // let signs = self + // .body() + // .as_ref() + // .unwrap() + // .content() + // .decide_signatures + // .as_slice(); + + // let proposal_id = self.desc().object_id(); + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + // let mut decides = vec![]; + + // for sign in signs { + // if &sign.proponent_id == member_id { + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &sign.proponent_id, + // sign.decide.as_slice(), + // ); + + // if verifier.verify(hash.as_slice(), &sign.signature).await { + // decides.push(sign.decide.as_slice()); + // } else { + // return Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )); + // } + // } + // } + + // Ok(decides) + // } + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult { + // let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + // if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + // return Err(BuckyError::new( + // BuckyErrorCode::AlreadyExists, + // "duplicated decide", + // )); + // } + + // let proposal_id = self.desc().object_id(); + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.as_slice(), + // ); + + // let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + // let sign = signer + // .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + // .await?; + + // Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) + // } + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()> { + // let proposal_id = self.desc().object_id(); + + // if decide.proposal_id() != &proposal_id { + // return Err(BuckyError::new( + // BuckyErrorCode::NotMatch, + // format!( + // "proposal id not match for decide signature: {}/{}", + // proposal_id, + // decide.proposal_id() + // ), + // )); + // } + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.decide(), + // ); + + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + // if verifier.verify(hash.as_slice(), decide.signature()).await { + // let signs = &mut self + // .body_mut() + // .as_mut() + // .unwrap() + // .content_mut() + // .decide_signatures; + // for exist in signs.iter() { + // if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + // return Ok(()); + // } + // } + + // signs.push(GroupProposalSignature { + // signature: decide.signature().clone(), + // proponent_id: member_id, + // decide: Vec::from(decide.decide()), + // }); + + // Ok(()) + // } else { + // Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )) + // } + // } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b2885d637..4310f48a5 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,13 +1,15 @@ mod group_consensus_block; mod group_proposal; -mod group_proposal_decide_param; +// mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_update_group_proposal_param; +// mod group_update_group_proposal_param; +mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; -pub use group_proposal_decide_param::*; +// pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_update_group_proposal_param::*; +// pub use group_update_group_proposal_param::*; +pub use group_protocol::*; From 36f15bd615b82f7136cdcb5fa25b0b69d024f26f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 20:52:45 +0800 Subject: [PATCH 463/553] Prepare for export interface to SDK --- .../cyfs-core/protos/core_objects.proto | 2 +- src/component/cyfs-core/src/coreobj.rs | 1 + src/component/cyfs-core/src/group/mod.rs | 2 - src/component/cyfs-group-lib/Cargo.toml | 34 ++ .../{cyfs-group => cyfs-group-lib}/build.rs | 27 +- .../protos/group_bft_protocol.proto | 63 +++ src/component/cyfs-group-lib/readme.md | 14 + .../src/delegate.rs} | 18 +- .../src}/group_manager.rs | 6 +- .../mod.rs => cyfs-group-lib/src/lib.rs} | 6 +- .../cyfs-group-lib/src/objects/certificate.rs | 190 ++++++++ .../cyfs-group-lib/src/objects/codec/mod.rs | 3 + .../src/objects/group_command.rs | 428 ++++++++++++++++++ .../src/objects/group_decide_proposal.rs | 0 .../src/objects/group_rpath_status.rs | 6 +- .../src/objects/group_update_proposal.rs | 0 .../cyfs-group-lib/src/objects/mod.rs | 12 + .../src}/rpath_client.rs | 3 +- src/component/cyfs-group/Cargo.toml | 3 +- .../protos/group_bft_protocol.proto | 23 - .../src/consensus/hotstuff/hotstuff.rs | 60 +-- .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 7 +- .../cyfs-group/src/dec/group_events.rs | 42 ++ .../cyfs-group/src/dec/group_manager.rs | 94 ++-- src/component/cyfs-group/src/dec/mod.rs | 2 + .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec/rpath_control.rs | 8 +- .../src/dec_state/dec_state_requestor.rs | 6 +- .../src/dec_state/dec_state_synchronizer.rs | 64 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/helper/mod.rs | 2 - src/component/cyfs-group/src/helper/verify.rs | 16 - src/component/cyfs-group/src/lib.rs | 4 - src/component/cyfs-group/src/network/mod.rs | 2 + .../src/{objects => network}/protocol.rs | 306 +++---------- src/component/cyfs-group/src/objects/mod.rs | 9 - .../cyfs-group/src/storage/dec_storage.rs | 9 +- .../engine/storage_engine_group_state.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 7 +- src/component/cyfs-group/src/utils.rs | 8 - src/component/cyfs-lib/src/lib.rs | 2 - 42 files changed, 977 insertions(+), 529 deletions(-) create mode 100644 src/component/cyfs-group-lib/Cargo.toml rename src/component/{cyfs-group => cyfs-group-lib}/build.rs (66%) create mode 100644 src/component/cyfs-group-lib/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group-lib/readme.md rename src/component/{cyfs-lib/src/group/delegate_factory.rs => cyfs-group-lib/src/delegate.rs} (81%) rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/group_manager.rs (100%) rename src/component/{cyfs-lib/src/group/mod.rs => cyfs-group-lib/src/lib.rs} (56%) create mode 100644 src/component/cyfs-group-lib/src/objects/certificate.rs create mode 100644 src/component/cyfs-group-lib/src/objects/codec/mod.rs create mode 100644 src/component/cyfs-group-lib/src/objects/group_command.rs rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_decide_proposal.rs (100%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_rpath_status.rs (93%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_update_proposal.rs (100%) create mode 100644 src/component/cyfs-group-lib/src/objects/mod.rs rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/rpath_client.rs (94%) delete mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group/src/dec/group_events.rs delete mode 100644 src/component/cyfs-group/src/helper/verify.rs rename src/component/cyfs-group/src/{objects => network}/protocol.rs (70%) delete mode 100644 src/component/cyfs-group/src/objects/mod.rs delete mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index abd299e9d..742c14904 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -446,4 +446,4 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; } -*/ \ No newline at end of file +*/ diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3d53a082f..8eb96a930 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupAction = 704, GroupQuorumCertificate = 705, + GroupCommand = 706, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4310f48a5..d7134a3c0 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,7 +4,6 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; @@ -12,4 +11,3 @@ pub use group_proposal::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; -pub use group_protocol::*; diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml new file mode 100644 index 000000000..e7cfda851 --- /dev/null +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -0,0 +1,34 @@ + +[package] +name = 'cyfs-group-lib' +version = '0.1.1' +authors = ['zhangzhen '] +edition = '2021' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +prost-build = { version = '0.9.0' } +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +itertools = "0.10.3" +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group-lib/build.rs similarity index 66% rename from src/component/cyfs-group/build.rs rename to src/component/cyfs-group-lib/build.rs index 8d4efe9c9..206d6bc6f 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group-lib/build.rs @@ -37,28 +37,13 @@ fn gen_protos() { } fn main() { - println!("cargo:rerun-if-env-changed=VERSION"); - println!("cargo:rerun-if-env-changed=CHANNEL"); - println!("cargo:rerun-if-env-changed=TARGET"); - println!( - "cargo:rustc-env=VERSION={}", - std::env::var("VERSION").unwrap_or("0".to_owned()) - ); - println!( - "cargo:rustc-env=CHANNEL={}", - std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) - ); - println!( - "cargo:rustc-env=TARGET={}", - std::env::var("TARGET").unwrap() - ); - + println!("cargo:rerun-if-changed=protos"); println!( - "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + "cargo:warning={}", + format!( + "cyfs-core run build script, OUT_DIR={}", + std::env::var("OUT_DIR").unwrap() + ) ); - - println!("cargo:rerun-if-changed=protos"); - gen_protos(); } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto new file mode 100644 index 000000000..2bfdd8d21 --- /dev/null +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -0,0 +1,63 @@ + +syntax = "proto3"; + +message HotstuffBlockQCVote { + bytes block_id = 1; + optional bytes prev_block_id = 2; + uint64 round = 3; + bytes voter = 4; + bytes signature = 5; +} + +message HotstuffTimeoutVote { + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; +} + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} + +// GroupCommand + +message GroupCommandDescContent { + +} + +message GroupCommandNewRPath { + bytes group_id = 1; + string rpath = 2; + optional bytes with_block = 3; // Block.to_vec() +} + +message GroupCommandExecute { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId +} + +message GroupCommandExecuteResult { + optional bytes result_state_id = 1; // ObjectId + optional bytes receipt = 2; // NONObjectInfo.to_vec() + optional bytes context = 3; // Vec +} + +message GroupCommandVerify { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec +} + +message GroupCommandCommited { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec + bytes block = 6; // Block.to_vec() +} diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group-lib/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-lib/src/group/delegate_factory.rs b/src/component/cyfs-group-lib/src/delegate.rs similarity index 81% rename from src/component/cyfs-lib/src/group/delegate_factory.rs rename to src/component/cyfs-group-lib/src/delegate.rs index 9e55ff8f4..21b1e6346 100644 --- a/src/component/cyfs-lib/src/group/delegate_factory.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,25 +1,17 @@ -use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult>; - - async fn on_state_changed( &self, group_id: &ObjectId, rpath: &str, - state_id: Option, - pre_state_id: Option, - ); + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()>; } pub struct ExecuteResult { @@ -30,8 +22,6 @@ pub struct ExecuteResult { #[async_trait::async_trait] pub trait RPathDelegate: Sync + Send { - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; - async fn on_execute( &self, proposal: &GroupProposal, @@ -45,7 +35,7 @@ pub trait RPathDelegate: Sync + Send { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult; + ) -> BuckyResult<()>; async fn on_commited( &self, diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs similarity index 100% rename from src/component/cyfs-lib/src/group/group_manager.rs rename to src/component/cyfs-group-lib/src/group_manager.rs index 7d836ae49..8c82bc9e1 100644 --- a/src/component/cyfs-lib/src/group/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -6,15 +6,15 @@ use crate::{DelegateFactory, RPathClient}; pub struct GroupManager; impl GroupManager { - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { unimplemented!() } - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn unregister(&self) { unimplemented!() } } diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-group-lib/src/lib.rs similarity index 56% rename from src/component/cyfs-lib/src/group/mod.rs rename to src/component/cyfs-group-lib/src/lib.rs index 482d9ea0d..199307bcc 100644 --- a/src/component/cyfs-lib/src/group/mod.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,7 +1,9 @@ -mod delegate_factory; +mod delegate; mod group_manager; +mod objects; mod rpath_client; -pub use delegate_factory::*; +pub use delegate::*; pub use group_manager::*; +pub use objects::*; pub use rpath_client::*; diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs new file mode 100644 index 000000000..32b1b53c8 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -0,0 +1,190 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, HashValue, ObjectId, ObjectLink, ProtobufDecode, + ProtobufEncode, ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, + RawEncodePurpose, RsaCPUObjectSigner, Signature, SignatureSource, Signer, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffBlockQcVote)] +pub struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub prev_block_id: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.block_id().object_id(); + let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let signature = signer + .sign( + hash.as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + block_id: block_id.clone(), + round, + voter: local_device_id, + signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) + } + + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: super::codec::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for super::codec::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffTimeoutVote)] +pub struct HotstuffTimeoutVote { + pub high_qc: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: Option, + round: u64, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_device_id, + signature, + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + } + + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: super::codec::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffTimeoutVote { + high_qc: match value.high_qc.as_ref() { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} diff --git a/src/component/cyfs-group-lib/src/objects/codec/mod.rs b/src/component/cyfs-group-lib/src/objects/codec/mod.rs new file mode 100644 index 000000000..66df9053f --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/codec/mod.rs @@ -0,0 +1,3 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs new file mode 100644 index 000000000..912ced438 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -0,0 +1,428 @@ +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, NamedObjType, NamedObject, + NamedObjectBase, NamedObjectBuilder, NamedObjectId, ObjectId, ProtobufDecode, ProtobufEncode, + ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, RawEncode, RawEncodePurpose, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, +}; + +use cyfs_core::{CoreObjectType, GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandDescContent)] +pub struct GroupCommandDescContent {} + +impl DescContent for GroupCommandDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupCommand as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupCommandDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Debug)] +pub enum GroupCommandType { + NewRPath, + Execute, + ExecuteResult, + Verify, + Commited, +} + +#[derive(Clone, RawEncode, RawDecode)] +pub enum GroupCommandBodyContent { + NewRPath(GroupCommandNewRPath), + Execute(GroupCommandExecute), + ExecuteResult(GroupCommandExecuteResult), + Verify(GroupCommandVerify), + Commited(GroupCommandCommited), +} + +pub type GroupCommandObjectType = NamedObjType; +pub type GroupCommandBuilder = NamedObjectBuilder; + +pub type GroupCommandId = NamedObjectId; +pub type GroupCommand = NamedObjectBase; + +impl GroupCommandBodyContent { + pub fn cmd_type(&self) -> GroupCommandType { + match self { + GroupCommandBodyContent::NewRPath(_) => GroupCommandType::NewRPath, + GroupCommandBodyContent::Execute(_) => GroupCommandType::Execute, + GroupCommandBodyContent::ExecuteResult(_) => GroupCommandType::ExecuteResult, + GroupCommandBodyContent::Verify(_) => GroupCommandType::Verify, + GroupCommandBodyContent::Commited(_) => GroupCommandType::Commited, + } + } +} + +pub trait GroupCommandObject { + fn cmd_type(&self) -> GroupCommandType; + fn into_cmd(self) -> GroupCommandBodyContent; +} + +impl GroupCommandObject for GroupCommand { + fn cmd_type(&self) -> GroupCommandType { + self.body().as_ref().unwrap().content().cmd_type() + } + + fn into_cmd(self) -> GroupCommandBodyContent { + self.into_body().unwrap().into_content() + } +} + +impl BodyContent for GroupCommandBodyContent { + fn version(&self) -> u8 { + 0 + } + + fn format(&self) -> u8 { + cyfs_base::OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupCommandBodyContent") + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandNewRPath)] +pub struct GroupCommandNewRPath { + pub group_id: ObjectId, + pub rpath: String, + pub with_block: Option, +} + +impl ProtobufTransform for GroupCommandNewRPath { + fn transform(value: super::codec::protos::GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: ObjectId::raw_decode(value.group_id.as_slice())?.0, + with_block: match value.with_block.as_ref() { + Some(buf) => Some(GroupConsensusBlock::raw_decode(buf.as_slice())?.0), + None => None, + }, + rpath: value.rpath, + }) + } +} + +impl ProtobufTransform<&GroupCommandNewRPath> for super::codec::protos::GroupCommandNewRPath { + fn transform(value: &GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: value.group_id.to_vec()?, + rpath: value.rpath.clone(), + with_block: match value.with_block.as_ref() { + Some(block) => Some(block.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecute)] +pub struct GroupCommandExecute { + pub proposal: GroupProposal, + pub prev_state_id: Option, +} + +impl ProtobufTransform for GroupCommandExecute { + fn transform(value: super::codec::protos::GroupCommandExecute) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecute> for super::codec::protos::GroupCommandExecute { + fn transform(value: &GroupCommandExecute) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecuteResult)] +pub struct GroupCommandExecuteResult { + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform + for GroupCommandExecuteResult +{ + fn transform(value: super::codec::protos::GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecuteResult> + for super::codec::protos::GroupCommandExecuteResult +{ + fn transform(value: &GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandVerify)] +pub struct GroupCommandVerify { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform for GroupCommandVerify { + fn transform(value: super::codec::protos::GroupCommandVerify) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + receipt: match value.receipt { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupCommandVerify { + fn transform(value: &GroupCommandVerify) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] +pub struct GroupCommandCommited { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, + pub block: GroupConsensusBlock, +} + +impl ProtobufTransform for GroupCommandCommited { + fn transform(value: super::codec::protos::GroupCommandCommited) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, + }, + block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { + fn transform(value: &GroupCommandCommited) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + block: value.block.to_vec()?, + }) + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandNewRPath) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::NewRPath(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecute) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Execute(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecuteResult) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::ExecuteResult(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandVerify) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Verify(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandCommited) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Commited(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::NewRPath(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect NewRPath", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Execute(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Execute", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::ExecuteResult(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect ExecuteResult", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Verify(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Verify", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Commited(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Commited", cmd_type), + )), + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_decide_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs similarity index 93% rename from src/component/cyfs-group/src/objects/group_rpath_status.rs rename to src/component/cyfs-group-lib/src/objects/group_rpath_status.rs index bfc9bc5d2..ae656b5ad 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs @@ -21,7 +21,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -42,7 +42,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -56,7 +56,7 @@ impl RawEncode for GroupRPathStatus { impl<'de> RawDecode<'de> for GroupRPathStatus { fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let proto = super::codec::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::Failed, msg) diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_update_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_update_proposal.rs diff --git a/src/component/cyfs-group-lib/src/objects/mod.rs b/src/component/cyfs-group-lib/src/objects/mod.rs new file mode 100644 index 000000000..668afe8cf --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/mod.rs @@ -0,0 +1,12 @@ +mod group_command; +// mod group_decide_proposal; +mod group_rpath_status; +// mod group_update_proposal; +mod certificate; +mod codec; + +pub use group_command::*; +// pub use group_decide_proposal::*; +pub use group_rpath_status::*; +// pub use group_update_proposal::*; +pub use certificate::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs similarity index 94% rename from src/component/cyfs-lib/src/group/rpath_client.rs rename to src/component/cyfs-group-lib/src/rpath_client.rs index 4162abe68..2fea6dcf7 100644 --- a/src/component/cyfs-lib/src/group/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -5,8 +5,7 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupProposal, GroupRPath}; - -use crate::NONObjectInfo; +use cyfs_lib::NONObjectInfo; struct RPathClientRaw {} diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 4a7aae6c2..1caf5b9a4 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,5 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto deleted file mode 100644 index 621186522..000000000 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ /dev/null @@ -1,23 +0,0 @@ - -syntax = "proto3"; - -message HotstuffBlockQCVote { - bytes block_id = 1; - optional bytes prev_block_id = 2; - uint64 round = 3; - bytes voter = 4; - bytes signature = 5; -} - -message HotstuffTimeoutVote { - optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) - uint64 round = 2; - bytes voter = 3; - bytes signature = 4; -} - -message GroupRPathStatus { - bytes block_desc = 1; // GroupConsensusBlockDescContent - bytes certificate = 2; // HotstuffBlockQC for block - repeated bytes status_list = 4; // Array> -} \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52dcdd650..cc555298b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,16 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; +use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, }; /** @@ -51,7 +52,7 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -81,7 +82,7 @@ impl Hotstuff { rx_message, proposal_consumer, state_pusher_runner, - delegate, + event_notifier, rpath2, ) .run() @@ -224,7 +225,7 @@ struct HotstuffRunner { tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, synchronizer: Synchronizer, rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, @@ -251,7 +252,7 @@ impl HotstuffRunner { rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, state_pusher: StatePusher, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); @@ -307,7 +308,7 @@ impl HotstuffRunner { network_sender, tx_message, rx_message, - delegate, + event_notifier, synchronizer, non_driver, rpath, @@ -511,37 +512,25 @@ impl HotstuffRunner { context: proposal_exe_info.context.clone(), }; - if self - .delegate - .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) + self + .event_notifier + .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); err - })? - { - log::debug!( - "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + })?; - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); - return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); - } + prev_state_id = proposal_exe_info.result_state; } assert_eq!( @@ -840,11 +829,10 @@ impl HotstuffRunner { None => None, }; - self.delegate + self.event_notifier .on_commited( &proposal_obj, pre_state_id, - self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1625,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { + match self.event_notifier.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ad3a21e35..398274723 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -14,9 +14,10 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::network::NONDriverHelper; #[derive(Clone)] pub(crate) struct Committee { diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index f44260a04..6a9735a7f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,13 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, -}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, HotstuffTimeout, HotstuffTimeoutSign, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::Committee; pub(crate) struct VoteMgr { committee: Committee, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs new file mode 100644 index 000000000..67f79cfdd --- /dev/null +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -0,0 +1,42 @@ +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_group_lib::ExecuteResult; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone)] +pub(crate) struct RPathEventNotifier {} + +impl RPathEventNotifier { + pub fn new() -> Self { + unimplemented!() + } + + pub async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 60ddba1fb..95bdbcd17 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,15 +2,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, - NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, + RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -22,7 +22,6 @@ type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - delegate_by_dec: HashMap>, control_by_group: ControlByGroup, client_by_group: ClientByGroup, } @@ -33,6 +32,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,12 +54,12 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { control_by_group: ControlByGroup::default(), client_by_group: ClientByGroup::default(), - delegate_by_dec: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -69,29 +69,12 @@ impl GroupManager { Ok(mgr) } - pub async fn register( - &self, - dec_id: DecAppId, - delegate_factory: Box, - ) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec - .insert(dec_id.object_id().clone(), delegate_factory); - Ok(()) - } - - pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec.remove(dec_id.object_id()); - Ok(()) - } - pub async fn find_rpath_control( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -204,7 +187,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, Some(&block), Some(&remote), ) @@ -220,7 +203,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -236,7 +219,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -252,7 +235,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -268,7 +251,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -284,7 +267,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -331,7 +314,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::No, + false, None, Some(&remote), ) @@ -378,7 +361,7 @@ impl GroupManager { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -398,7 +381,6 @@ impl GroupManager { { // write - let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); @@ -411,6 +393,7 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -424,40 +407,25 @@ impl GroupManager { let store = match store { Ok(store) => Some(store), Err(e) => { - if let IsCreateRPath::No = is_auto_create { - return Err(e); - } if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - None + + self.on_new_rpath_request(group_id, dec_id, rpath, block) + .await?; + + if !is_auto_create { + return Err(e); + } else { + None + } } else { return Err(e); } } }; - // TODO: query group - let group = non_driver - .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) - .await?; - let mut raw = self.write().await; - let delegate = { - let delegate_factory = raw.delegate_by_dec.get(dec_id); - if delegate_factory.is_none() { - return Err(BuckyError::new( - BuckyErrorCode::DecNotRunning, - "dec not running for the rpath-control", - )); - } - let delegate_factory = delegate_factory.unwrap(); - - delegate_factory - .create_rpath_delegate(&group, rpath, block) - .await? - }; - let store = match store { Some(store) => store, None => { @@ -489,7 +457,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - Arc::new(delegate), + event_notifier, network_sender, non_driver, store, @@ -501,4 +469,14 @@ impl GroupManager { } } } + + async fn on_new_rpath_request( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 8a43844b2..2ad717514 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,9 +1,11 @@ // dec framework +mod group_events; mod group_manager; mod rpath_client; mod rpath_control; +pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 8a1dd34a7..08be0f5a0 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -224,10 +224,10 @@ impl RPathClient { HotstuffMessage::Timeout(tc) => unreachable!(), HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), HotstuffMessage::LastStateRequest => unreachable!(), - HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffMessage::StateChangeNotify(header_block, qc) => { self.0 .state_sync - .on_state_change(header_block, qc_block, remote) + .on_state_change(header_block, qc, remote) .await } HotstuffMessage::ProposalResult(proposal_id, result) => { diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c3a25b060..593d82db4 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::RPathDelegate; +use cyfs_group_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, + PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; struct RPathControlRaw { @@ -26,7 +26,7 @@ impl RPathControl { local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, - delegate: Arc>, + event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, store: GroupStorage, @@ -46,7 +46,7 @@ impl RPathControl { network_sender.clone(), non_driver, pending_proposal_consumer, - delegate, + event_notifier, rpath.clone(), ); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 790429c6c..8fd67496b 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,13 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, - CHANNEL_CAPACITY, -}; +use crate::{storage::DecStorage, Committee, HotstuffMessage, CHANNEL_CAPACITY}; use super::{CallReplyNotifier, CallReplyWaiter}; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 7272b3882..e019db892 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -2,15 +2,12 @@ use std::{collections::HashSet, sync::Arc}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, -}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, Committee, CHANNEL_CAPACITY, @@ -21,13 +18,9 @@ use super::{CallReplyNotifier, CallReplyWaiter}; enum DecStateSynchronizerMessage { ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, ), - StateChange(GroupConsensusBlock, GroupConsensusBlock), + StateChange(GroupConsensusBlock, HotstuffBlockQC), DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } @@ -81,11 +74,7 @@ impl DecStateSynchronizer { pub async fn on_proposal_complete( &self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { self.0 @@ -100,13 +89,13 @@ impl DecStateSynchronizer { pub async fn on_state_change( &self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { self.0 .tx_dec_state_sync_message .send(( - DecStateSynchronizerMessage::StateChange(header_block, qc_block), + DecStateSynchronizerMessage::StateChange(header_block, qc), remote, )) .await; @@ -121,7 +110,7 @@ struct DecStateSynchronizerCache { struct UpdateNotifyInfo { header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remotes: HashSet, group_chunk_id: ObjectId, group: Group, @@ -178,15 +167,11 @@ impl DecStateSynchronizerRunner { async fn handle_proposal_complete( &mut self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { match result { - Ok((result, header_block, qc_block)) => { + Ok((result, header_block, qc)) => { if header_block .proposals() .iter() @@ -200,7 +185,7 @@ impl DecStateSynchronizerRunner { } if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_err() { @@ -226,11 +211,11 @@ impl DecStateSynchronizerRunner { async fn handle_state_change( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_ok() { @@ -251,11 +236,7 @@ impl DecStateSynchronizerRunner { for remote in notify_info.remotes.iter() { match self .store - .sync( - ¬ify_info.header_block, - ¬ify_info.qc_block, - remote.clone(), - ) + .sync(¬ify_info.header_block, ¬ify_info.qc, remote.clone()) .await { Ok(_) => { @@ -264,7 +245,7 @@ impl DecStateSynchronizerRunner { state_cache: DecStorageCache { state: notify_info.header_block.result_state_id().clone(), header_block: notify_info.header_block.clone(), - qc_block: notify_info.qc_block.clone(), + qc: notify_info.qc.clone(), }, group_chunk_id: notify_info.group_chunk_id, group: notify_info.group.clone(), @@ -316,14 +297,9 @@ impl DecStateSynchronizerRunner { async fn push_update_notify( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { - if qc_block.qc().is_none() { - log::warn!("the qc is none for qc-block({})", qc_block.block_id()); - return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); - } - if let Some(notify) = self.update_notifies.as_mut() { match notify.header_block.height().cmp(&header_block.height()) { std::cmp::Ordering::Less => {} @@ -338,11 +314,7 @@ impl DecStateSynchronizerRunner { if header_block.check() && self .committee - .verify_block_desc_with_qc( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - remote, - ) + .verify_block_desc_with_qc(header_block.named_object().desc(), &qc, remote) .await .is_ok() { @@ -354,7 +326,7 @@ impl DecStateSynchronizerRunner { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, - qc_block: qc_block, + qc: qc, remotes: HashSet::from([remote]), group_chunk_id, group, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b1506a192..571c1ca13 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -194,7 +194,11 @@ impl StateChanggeRunner { .post_message( HotstuffMessage::ProposalResult( exe_info.proposal, - Ok((receipt, block.clone(), qc_block.clone())), + Ok(( + receipt, + block.clone(), + qc_block.qc().as_ref().unwrap().clone(), + )), ), rpath.clone(), &proposer, @@ -320,7 +324,7 @@ impl StateChanggeRunner { let msg = HotstuffMessage::StateChangeNotify( progress.header_block.clone(), - progress.qc_block.clone(), + progress.qc_block.qc().as_ref().unwrap().clone(), ); if notify_targets.len() > 0 { diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index ce36043a3..4d3f1b1c6 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,5 +1,3 @@ mod timer; -mod verify; pub use timer::*; -pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs deleted file mode 100644 index ef3e34495..000000000 --- a/src/component/cyfs-group/src/helper/verify.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, -}; - -use crate::GroupRPathStatus; - -pub async fn verify_rpath_value( - value: &GroupRPathStatus, - sub_path: &str, - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - unimplemented!() -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index ba8e83569..c493f13c5 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -4,10 +4,8 @@ mod dec; mod dec_state; mod helper; mod network; -mod objects; mod statepath; mod storage; -mod utils; pub use consensus::*; pub use constant::*; @@ -15,7 +13,5 @@ pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; pub use network::*; -pub use objects::*; pub use statepath::*; pub(crate) use storage::*; -pub use utils::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index f79e67dd4..096bd0950 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,7 +1,9 @@ mod listener; mod non_driver; +mod protocol; mod sender; pub(crate) use listener::*; pub use non_driver::*; +pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs similarity index 70% rename from src/component/cyfs-group/src/objects/protocol.rs rename to src/component/cyfs-group/src/network/protocol.rs index 932e5cd46..7e32fdc4d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -1,16 +1,8 @@ -pub mod protos { - include!(concat!(env!("OUT_DIR"), "/mod.rs")); -} - use cyfs_base::*; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_group_lib::{GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; use itertools::Itertools; -use sha2::Digest; - -use crate::GroupRPathStatus; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { @@ -96,15 +88,11 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, - ), // (proposal-id, (ExecuteResult, block, qc-block)) + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, + ), // (proposal-id, (ExecuteResult, block, qc)) QueryState(String), VerifiableState(String, BuckyResult), } @@ -151,8 +139,8 @@ impl std::fmt::Debug for HotstuffMessage { "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest => { @@ -169,8 +157,8 @@ impl std::fmt::Debug for HotstuffMessage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) }) ) @@ -214,16 +202,12 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) LastStateRequest(ProtocolAddress), ProposalResult( ObjectId, Result< - ( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - ), + (Option, GroupConsensusBlock, HotstuffBlockQC), (BuckyError, ProtocolAddress), >, ), // (proposal-id, ExecuteResult) @@ -276,8 +260,8 @@ impl std::fmt::Debug for HotstuffPackage { "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest(_) => { @@ -296,8 +280,8 @@ impl std::fmt::Debug for HotstuffPackage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ); Ok(ok) } @@ -394,23 +378,25 @@ fn decode_with_length<'de, O: RawDecode<'de>>( impl RawEncode for HotstuffPackage { fn raw_measure(&self, purpose: &Option) -> BuckyResult { let len = match self { - HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::Block(b) => 3 + b.raw_measure(purpose)?, HotstuffPackage::BlockVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::TimeoutVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::Timeout(addr, tc) => { - 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + tc.raw_measure(purpose)? } HotstuffPackage::SyncRequest(addr, min, max) => { - addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + + min.raw_measure(purpose)? + + max.raw_measure(purpose)? } HotstuffPackage::StateChangeNotify(block, qc) => { - 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + 3 + qc.raw_measure(purpose)? } - HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::LastStateRequest(addr) => 2 + addr.raw_measure(purpose)?, HotstuffPackage::ProposalResult(id, result) => { id.raw_measure(purpose)? + match result { @@ -418,22 +404,23 @@ impl RawEncode for HotstuffPackage { non.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + + 3 + block_qc.raw_measure(purpose)? } Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } HotstuffPackage::QueryState(addr, sub_path) => { - addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } HotstuffPackage::VerifiableState(sub_path, result) => { sub_path.raw_measure(purpose)? + match result { - Ok(status) => status.raw_measure(purpose)?, + Ok(status) => 3 + status.raw_measure(purpose)?, Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } @@ -451,43 +438,43 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::Block(b) => { buf[0] = 0; let buf = &mut buf[1..]; - b.raw_encode(buf, purpose) + encode_with_length(buf, b, purpose, 3) } HotstuffPackage::BlockVote(addr, vote) => { buf[0] = 1; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::TimeoutVote(addr, vote) => { buf[0] = 2; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::Timeout(addr, tc) => { buf[0] = 3; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - tc.raw_encode(buf, purpose) + encode_with_length(buf, tc, purpose, 3) } HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; + encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; - let buf = max.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + max.raw_encode(buf, purpose) } HotstuffPackage::StateChangeNotify(block, qc) => { buf[0] = 5; let buf = &mut buf[1..]; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } HotstuffPackage::LastStateRequest(addr) => { buf[0] = 6; let buf = &mut buf[1..]; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; @@ -501,19 +488,19 @@ impl RawEncode for HotstuffPackage { Ok((non, block, qc)) => { let buf = non.raw_encode(buf, purpose)?; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } HotstuffPackage::QueryState(addr, sub_path) => { buf[0] = 8; let buf = &mut buf[1..]; - let buf = sub_path.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2)?; + sub_path.raw_encode(buf, purpose) } HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; @@ -523,10 +510,10 @@ impl RawEncode for HotstuffPackage { let buf = &mut buf[1..]; let buf = sub_path.raw_encode(buf, purpose)?; match result { - Ok(status) => status.raw_encode(buf, purpose), + Ok(status) => encode_with_length(buf, status, purpose, 3), Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } @@ -542,49 +529,49 @@ impl<'de> RawDecode<'de> for HotstuffPackage { match pkg_type { 0 => { let buf = &buf[1..]; - let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (b, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } @@ -596,7 +583,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { true => { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), @@ -605,7 +592,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } @@ -613,8 +600,8 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } 8 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } @@ -624,13 +611,13 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (sub_path, buf) = String::raw_decode(buf)?; match is_ok { true => { - let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + let (status, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), @@ -698,188 +685,5 @@ impl ProtocolAddress { } } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] -pub(crate) struct HotstuffBlockQCVote { - pub block_id: ObjectId, - pub prev_block_id: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let block_id = block.block_id().object_id(); - let round = block.round(); - - log::debug!( - "[block vote] local: {:?}, vote hash {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let hash = Self::hash_content(block_id, block.prev_block_id(), round); - - log::debug!( - "[block vote] local: {:?}, vote sign {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let signature = signer - .sign( - hash.as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - block_id: block_id.clone(), - round, - voter: local_device_id, - signature, - prev_block_id: block.prev_block_id().map(|id| id.clone()), - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) - } - - fn hash_content( - block_id: &ObjectId, - prev_block_id: Option<&ObjectId>, - round: u64, - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(block_id.as_slice()); - sha256.input(round.to_le_bytes()); - if let Some(prev_block_id) = prev_block_id { - sha256.input(prev_block_id.as_slice()); - } - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffBlockQCVote { - fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, - round: value.round, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), - None => None, - }, - }) - } -} - -impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { - fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { - let ret = crate::protos::HotstuffBlockQcVote { - block_id: value.block_id.to_vec()?, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(id.to_vec()?), - None => None, - }, - }; - - Ok(ret) - } -} - -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] -pub(crate) struct HotstuffTimeoutVote { - pub high_qc: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffTimeoutVote { - pub async fn new( - high_qc: Option, - round: u64, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let signature = signer - .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - high_qc, - round, - voter: local_device_id, - signature, - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) - } - - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(high_qc_round.to_le_bytes()); - sha256.input(round.to_le_bytes()); - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffTimeoutVote { - fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { - let high_qc = if value.high_qc().len() == 0 { - None - } else { - Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) - }; - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - round: value.round, - high_qc, - }) - } -} - -impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { - fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { - let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc.as_ref() { - Some(qc) => Some(qc.to_vec()?), - None => None, - }, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - }; - - Ok(ret) - } -} - #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs deleted file mode 100644 index 5d1a8b13f..000000000 --- a/src/component/cyfs-group/src/objects/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod group_decide_proposal; -mod group_rpath_status; -mod group_update_proposal; -mod protocol; - -pub use group_decide_proposal::*; -pub use group_rpath_status::*; -pub use group_update_proposal::*; -pub use protocol::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 60a45724f..0d937487c 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -5,16 +5,17 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; +use crate::STATE_PATH_SEPARATOR; #[derive(Clone)] pub struct DecStorageCache { pub state: Option, pub header_block: GroupConsensusBlock, - pub qc_block: GroupConsensusBlock, + pub qc: HotstuffBlockQC, } #[derive(Clone)] @@ -42,7 +43,7 @@ impl DecStorage { pub async fn sync( &self, header_block: &GroupConsensusBlock, - qc_block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index adf11c7e4..63158a865 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_lib::GroupObjectMapProcessor; +use cyfs_group_lib::GroupObjectMapProcessor; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index fa6f4930f..a1a681259 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; +use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, + STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs deleted file mode 100644 index 5d005a726..000000000 --- a/src/component/cyfs-group/src/utils.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cyfs_base::ObjectId; - -pub type Round = u64; - -pub enum IsCreateRPath { - No, - Yes, -} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index d2f02315a..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,7 +4,6 @@ mod base; mod crypto; mod default_app; mod events; -mod group; mod ndn; mod non; mod prelude; @@ -27,7 +26,6 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; -pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; From bc104af4582acc166309b9b18bb4b1b963b0c927 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 12:15:59 +0800 Subject: [PATCH 464/553] Implement the events with post_object --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- .../cyfs-group/src/dec/group_events.rs | 120 +++++++++++++++--- .../cyfs-group/src/dec/group_manager.rs | 50 ++++++-- .../cyfs-group/src/dec/rpath_client.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 19 ++- .../cyfs-stack/src/stack/group_non_driver.rs | 8 +- 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index cc555298b..eaaaed06e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -514,7 +514,7 @@ impl HotstuffRunner { self .event_notifier - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal.clone(), prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -831,14 +831,14 @@ impl HotstuffRunner { self.event_notifier .on_commited( - &proposal_obj, + proposal_obj, pre_state_id, &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, - &new_header, + new_header.clone(), ) .await; @@ -1613,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.event_notifier.on_execute(&proposal, result_state_id).await { + match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 67f79cfdd..fc3d12c63 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,42 +1,132 @@ use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_group_lib::ExecuteResult; +use cyfs_group_lib::{ + ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandVerify, +}; use cyfs_lib::NONObjectInfo; +use crate::NONDriverHelper; + #[derive(Clone)] -pub(crate) struct RPathEventNotifier {} +pub(crate) struct RPathEventNotifier { + non_driver: NONDriverHelper, +} impl RPathEventNotifier { - pub fn new() -> Self { - unimplemented!() + pub fn new(driver: NONDriverHelper) -> Self { + Self { non_driver: driver } } pub async fn on_execute( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, ) -> BuckyResult { - unimplemented!() + let cmd = GroupCommandExecute { + proposal, + prev_state_id, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_some()); + match result.as_ref() { + Some(result) => { + let (cmd, _remain) = GroupCommand::raw_decode(result.object_raw.as_slice())?; + assert_eq!(_remain.len(), 0); + let mut cmd = TryInto::::try_into(cmd)?; + Ok(ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }) + } + None => Err(BuckyError::new( + BuckyErrorCode::Unknown, + "expect some result from dec-app", + )), + } } pub async fn on_verify( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandVerify { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } pub async fn on_commited( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, - block: &GroupConsensusBlock, + block: GroupConsensusBlock, ) { - unimplemented!() + let cmd = GroupCommandCommited { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec().expect( + format!("on_commited {} failed for encode", self.non_driver.dec_id()) + .as_str(), + ), + object: None, + }, + None, + ) + .await + .map_err(|err| log::warn!("on_commited {} failed {:?}", self.non_driver.dec_id(), err)); + + assert!(result.is_err() || result.unwrap().is_none()); } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95bdbcd17..346e75d02 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,11 +2,13 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -32,7 +34,6 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, - event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,7 +55,6 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, - event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { @@ -393,7 +393,6 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -410,8 +409,13 @@ impl GroupManager { if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - self.on_new_rpath_request(group_id, dec_id, rpath, block) - .await?; + self.on_new_rpath_request( + group_id.clone(), + dec_id, + rpath.to_string(), + block.cloned(), + ) + .await?; if !is_auto_create { return Err(e); @@ -457,7 +461,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - event_notifier, + RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, store, @@ -472,11 +476,33 @@ impl GroupManager { async fn on_new_rpath_request( &self, - group_id: &ObjectId, + group_id: ObjectId, dec_id: &ObjectId, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, + rpath: String, + with_block: Option, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandNewRPath { + group_id, + rpath, + with_block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .local_info() + .non_driver + .post_object( + dec_id, + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 08be0f5a0..41db0c25c 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -100,7 +100,7 @@ impl RPathClient { match self .0 .non_driver - .post_object(non_proposal.clone(), ood) + .post_object(non_proposal.clone(), Some(ood)) .await { Ok(r) => post_result = Some(Ok(())), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 979451b79..c7f9e7d93 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, }; @@ -29,8 +29,8 @@ pub trait NONDriver: Send + Sync { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()>; + to: Option<&ObjectId>, + ) -> BuckyResult>; } #[derive(Clone)] @@ -49,6 +49,10 @@ impl NONDriverHelper { } } + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id + } + pub async fn get_object( &self, object_id: &ObjectId, @@ -74,12 +78,17 @@ impl NONDriverHelper { self.driver.put_object(&self.dec_id, obj).await } - pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object( + &self, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { self.driver.post_object(&self.dec_id, obj, to).await } pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { - futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), Some(to)))) + .await; } pub async fn get_block( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fcb0dd6da..f7f305a83 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -88,8 +88,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()> { + to: Option<&ObjectId>, + ) -> BuckyResult> { self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { @@ -107,12 +107,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { level: NONAPILevel::Router, - target: Some(to.clone()), + target: to.cloned(), flags: 0, }, object: obj, }) .await - .map(|_| ()) + .map(|resp| resp.object) } } From 07efe6d6e3b02711ff1c25206f14b774f64c9213 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 14:56:29 +0800 Subject: [PATCH 465/553] Rename `control` into `Service` --- .../cyfs-group/src/dec/group_manager.rs | 80 +++++++++---------- src/component/cyfs-group/src/dec/mod.rs | 4 +- .../{rpath_control.rs => rpath_service.rs} | 8 +- src/tests/group-example/src/main.rs | 20 ++--- 4 files changed, 56 insertions(+), 56 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_control.rs => rpath_service.rs} (96%) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 346e75d02..23202fddf 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,19 +12,19 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, + RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, }; -type ControlByRPath = HashMap; -type ControlByDec = HashMap; -type ControlByGroup = HashMap; +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; type ClientByRPath = HashMap; type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - control_by_group: ControlByGroup, + service_by_group: ServiceByGroup, client_by_group: ClientByGroup, } @@ -58,7 +58,7 @@ impl GroupManager { }; let raw = GroupRPathMgrRaw { - control_by_group: ControlByGroup::default(), + service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), }; @@ -69,14 +69,14 @@ impl GroupManager { Ok(mgr) } - pub async fn find_rpath_control( + pub async fn find_rpath_service( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, is_auto_create: bool, - ) -> BuckyResult { - self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + ) -> BuckyResult { + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -155,7 +155,7 @@ impl GroupManager { } // return - pub async fn enum_rpath_control( + pub async fn enum_rpath_service( &self, group_id: &ObjectId, ) -> BuckyResult> { @@ -182,8 +182,8 @@ impl GroupManager { match msg { HotstuffPackage::Block(block) => { let rpath = block.r_path(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -192,14 +192,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Block(block), remote) .await; } HotstuffPackage::BlockVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -208,14 +208,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; } HotstuffPackage::TimeoutVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -224,14 +224,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; } HotstuffPackage::Timeout(target, tc) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -240,14 +240,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Timeout(tc), remote) .await; } HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -256,14 +256,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; } HotstuffPackage::LastStateRequest(target) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -272,7 +272,7 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::LastStateRequest, remote) .await; } @@ -309,8 +309,8 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -320,9 +320,9 @@ impl GroupManager { ) .await; - match control { - Ok(control) => { - control + match service { + Ok(service) => { + service .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } @@ -356,7 +356,7 @@ impl GroupManager { Ok(()) } - async fn find_rpath_control_inner( + async fn find_rpath_service_inner( &self, group_id: &ObjectId, dec_id: &ObjectId, @@ -364,12 +364,12 @@ impl GroupManager { is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, - ) -> BuckyResult { + ) -> BuckyResult { { // read let raw = self.read().await; let found = raw - .control_by_group + .service_by_group .get(group_id) .map_or(None, |by_dec| by_dec.get(dec_id)) .map_or(None, |by_rpath| by_rpath.get(rpath)); @@ -446,7 +446,7 @@ impl GroupManager { }; let found = raw - .control_by_group + .service_by_group .entry(group_id.clone()) .or_insert_with(HashMap::new) .entry(dec_id.clone()) @@ -456,7 +456,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let control = RPathControl::load( + let service = RPathService::load( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -467,8 +467,8 @@ impl GroupManager { store, ) .await?; - entry.insert(control.clone()); - Ok(control) + entry.insert(service.clone()); + Ok(service) } } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 2ad717514..f881db19c 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod group_events; mod group_manager; mod rpath_client; -mod rpath_control; +mod rpath_service; pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; -pub use rpath_control::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_service.rs similarity index 96% rename from src/component/cyfs-group/src/dec/rpath_control.rs rename to src/component/cyfs-group/src/dec/rpath_service.rs index 593d82db4..b4b90972f 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -9,7 +9,7 @@ use crate::{ PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; -struct RPathControlRaw { +struct RPathServiceRaw { local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, @@ -18,9 +18,9 @@ struct RPathControlRaw { } #[derive(Clone)] -pub struct RPathControl(Arc); +pub struct RPathService(Arc); -impl RPathControl { +impl RPathService { pub(crate) async fn load( local_id: ObjectId, local_device_id: ObjectId, @@ -50,7 +50,7 @@ impl RPathControl { rpath.clone(), ); - let raw = RPathControlRaw { + let raw = RPathServiceRaw { network_sender, pending_proposal_handle, local_id, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 42544e51c..88450ac1b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,7 +505,7 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathControl; + use cyfs_group::RPathService; use cyfs_lib::{ DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, @@ -545,7 +545,7 @@ mod GroupDecService { } // pub struct PostProposalRoutine { - // controller: RPathControl, + // service: RPathService, // } // #[async_trait::async_trait] @@ -558,7 +558,7 @@ mod GroupDecService { // ) -> BuckyResult { // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // self.controller.push_proposal(proposal).await?; + // self.service.push_proposal(proposal).await?; // Ok(NONPostObjectInputResponse { object: None }) // } // } @@ -1037,9 +1037,9 @@ async fn main_run() { ) .await; - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1066,9 +1066,9 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1113,9 +1113,9 @@ async fn main_run() { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1125,7 +1125,7 @@ async fn main_run() { .unwrap(); async_std::task::spawn(async move { - control.push_proposal(proposal).await.unwrap(); + service.push_proposal(proposal).await.unwrap(); }); if i % 10 == 0 { From 92554e875a985b48ddaf616466e30ef99dec33b6 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 15:34:34 +0800 Subject: [PATCH 466/553] Interface in client for DecAPP --- src/component/cyfs-group-lib/src/delegate.rs | 6 +-- .../cyfs-group-lib/src/group_manager.rs | 37 ++++++++++++++++--- src/component/cyfs-group-lib/src/lib.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 23 ++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/rpath_service.rs diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 21b1e6346..645cd0656 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,4 @@ -use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, -}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -11,7 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()>; + ) -> BuckyResult>; } pub struct ExecuteResult { diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 8c82bc9e1..103807446 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,20 +1,47 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::DecAppId; +use cyfs_lib::SharedCyfsStack; -use crate::{DelegateFactory, RPathClient}; +use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; #[derive(Clone)] pub struct GroupManager; impl GroupManager { - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn open( + stack: SharedCyfsStack, + delegate_factory: Box, + ) -> BuckyResult { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn start_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + delegate: Box, + ) -> BuckyResult { + Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + } + + pub async fn find_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client( + &self, + group_id: ObjectId, + dec_id: DecAppId, + rpath: String, + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 199307bcc..34473bf07 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -2,8 +2,10 @@ mod delegate; mod group_manager; mod objects; mod rpath_client; +mod rpath_service; pub use delegate::*; pub use group_manager::*; pub use objects::*; pub use rpath_client::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs new file mode 100644 index 000000000..81225ed72 --- /dev/null +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupProposal, GroupRPath}; + +struct RPathServiceRaw {} + +#[derive(Clone)] +pub struct RPathService(Arc); + +impl RPathService { + pub(crate) async fn load() -> BuckyResult { + unimplemented!() + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + unimplemented!() + } +} From 97de0c06319922645559e0c7275ae9231b3d0786 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 21:21:44 +0800 Subject: [PATCH 467/553] Interface in client for DecAPP events --- .../cyfs-base/protos/standard_objects.proto | 4 +- src/component/cyfs-base/src/objects/group.rs | 20 +- .../cyfs-core/protos/core_objects.proto | 8 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 18 +- .../cyfs-core/src/group/group_rpath.rs | 14 +- src/component/cyfs-group-lib/Cargo.toml | 3 +- src/component/cyfs-group-lib/src/delegate.rs | 24 +- .../cyfs-group-lib/src/group_manager.rs | 442 +++++++++++++++++- .../cyfs-group-lib/src/rpath_client.rs | 45 +- .../cyfs-group-lib/src/rpath_service.rs | 122 ++++- .../src/consensus/hotstuff/hotstuff.rs | 4 +- .../cyfs-group/src/dec/group_events.rs | 10 +- .../cyfs-group/src/dec/group_manager.rs | 28 +- .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec_state/state_pusher.rs | 4 +- .../cyfs-group/src/network/protocol.rs | 6 +- .../engine/storage_engine_group_state.rs | 8 +- .../cyfs-group/src/storage/group_storage.rs | 6 +- src/component/cyfs-lib/src/stack/stack.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- 21 files changed, 689 insertions(+), 115 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index cfb722c62..4a9714958 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -72,7 +72,7 @@ message GroupMethodACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; double min_support_percent = 4; string permissions = 5; // ACL-String @@ -83,7 +83,7 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; string method = 4; double right_percent = 5; diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ed7686157..5c8cda714 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -436,7 +436,7 @@ impl TryFrom<&GroupMember> for protos::GroupMember { pub struct GroupMethodACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub min_support_percent: f64, pub permissions: String, // ACL-String } @@ -452,8 +452,8 @@ impl TryFrom for GroupMethodACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -475,8 +475,8 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.min_support_percent = value.min_support_percent; ret.permissions = value.permissions.clone(); @@ -489,7 +489,7 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { pub struct GroupRoleACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub method: String, pub right_percent: f64, @@ -508,8 +508,8 @@ impl TryFrom for GroupRoleACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -533,8 +533,8 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.method = value.method.clone(); ret.right_percent = value.right_percent; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 742c14904..8048b3951 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -333,12 +333,12 @@ message SyncResponseObjectMetaInfo { message GroupRPath { bytes group_id = 1; bytes dec_id = 2; - string r_path = 3; + string rpath = 3; } message GroupProposalDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; @@ -404,7 +404,7 @@ message HotstuffTimeout { message GroupConsensusBlockDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // input bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) @@ -437,7 +437,7 @@ message GroupConsensusBlockBodyContent { /* message GroupActionDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 35c418552..7d447ad15 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -10,7 +10,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path: GroupRPath, + rpath: GroupRPath, body_hash: HashValue, result_state_id: Option, height: u64, @@ -40,7 +40,7 @@ impl DescContent for GroupConsensusBlockDescContent { impl GroupConsensusBlockDescContent { pub fn rpath(&self) -> &GroupRPath { - &self.r_path + &self.rpath } pub fn result_state_id(&self) -> &Option { @@ -236,7 +236,7 @@ impl GroupConsensusBlockBodyContent { pub trait GroupConsensusBlockObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -248,7 +248,7 @@ pub trait GroupConsensusBlockObject { owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; @@ -266,7 +266,7 @@ pub trait GroupConsensusBlockObject { impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -280,7 +280,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { - r_path, + rpath, result_state_id, height, @@ -319,9 +319,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path(&self) -> &GroupRPath { + fn rpath(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path + &desc.rpath } fn proposals(&self) -> &Vec { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index bf28aafb2..508418f7b 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -6,7 +6,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, @@ -123,7 +123,7 @@ pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, meta_block_id: Option, @@ -131,7 +131,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path, + rpath, method, params, meta_block_id, @@ -158,7 +158,7 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -169,7 +169,7 @@ pub trait GroupProposalObject { effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -207,7 +207,7 @@ pub trait GroupProposalObject { #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -218,7 +218,7 @@ impl GroupProposalObject for GroupProposal { effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path, + rpath, method, params, meta_block_id, @@ -237,8 +237,8 @@ impl GroupProposalObject for GroupProposal { .owner(owner) } - fn r_path(&self) -> &GroupRPath { - &self.desc().content().r_path + fn rpath(&self) -> &GroupRPath { + &self.desc().content().rpath } fn method(&self) -> &str { diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 3b86fbc57..f177015bf 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,25 +1,25 @@ use cyfs_base::*; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq, Hash)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, - r_path: String, + rpath: String, } impl std::fmt::Debug for GroupRPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.rpath) } } impl GroupRPath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { Self { group_id, dec_id, - r_path, + rpath, } } @@ -31,7 +31,7 @@ impl GroupRPath { &self.dec_id } - pub fn r_path(&self) -> &str { - self.r_path.as_str() + pub fn rpath(&self) -> &str { + self.rpath.as_str() } } diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index e7cfda851..bad3d3112 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -31,4 +31,5 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 645cd0656..3cc99902b 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,6 @@ -use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SingleOpEnvStub}; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { @@ -23,30 +23,36 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult<()>; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ); } #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { - async fn create_single_op_env(&self) -> BuckyResult; - async fn create_sub_tree_op_env(&self) -> BuckyResult; + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult; + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 103807446..f93be45f0 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,37 +1,132 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::DecAppId; -use cyfs_lib::SharedCyfsStack; +use std::{collections::HashMap, sync::Arc}; -use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RawDecode, +}; +use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, + SharedCyfsStack, +}; +use cyfs_util::EventListenerAsyncRoutine; + +use crate::{ + DelegateFactory, ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandNewRPath, GroupCommandObject, GroupCommandType, + GroupCommandVerify, RPathClient, RPathDelegate, RPathService, +}; + +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupManagerRaw { + stack: SharedCyfsStack, + requestor: HttpRequestorRef, + delegate_factory: Option>, + clients: RwLock, + services: RwLock, + local_zone: Option, +} #[derive(Clone)] -pub struct GroupManager; +pub struct GroupManager(Arc); impl GroupManager { pub async fn open( stack: SharedCyfsStack, delegate_factory: Box, + requestor_type: &CyfsStackRequestorType, ) -> BuckyResult { - unimplemented!() + if stack.dec_id().is_none() { + let msg = "the stack should be opened with dec-id"; + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let dec_id = stack.dec_id().unwrap().clone(); + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + let router_handler_manager = stack.router_handlers().clone(); + + let mgr = Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: Some(delegate_factory), + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + })); + + // TODO: other filters? only local zone + let filter = format!( + "obj_type == {} && dec_id == {}", + CoreObjectType::GroupCommand as u16, + dec_id, + ); + + router_handler_manager + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-cmd-{}", dec_id).as_str(), + 0, + Some(filter), + None, + RouterHandlerAction::Pass, + Some(Box::new(mgr.clone())), + ) + .await?; + + Ok(mgr) } - pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { + pub async fn open_as_client( + stack: SharedCyfsStack, + requestor_type: &CyfsStackRequestorType, + ) -> BuckyResult { + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + + Ok(Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: None, + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + }))) + } + + pub async fn stop(&self) { unimplemented!() } + pub fn stack(&self) -> &SharedCyfsStack { + &self.0.stack + } + pub async fn start_rpath_service( &self, group_id: ObjectId, rpath: String, delegate: Box, ) -> BuckyResult { - Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + unimplemented!() } pub async fn find_rpath_service( &self, - group_id: ObjectId, - rpath: String, + group_id: &ObjectId, + rpath: &str, ) -> BuckyResult { unimplemented!() } @@ -40,8 +135,329 @@ impl GroupManager { &self, group_id: ObjectId, dec_id: DecAppId, - rpath: String, - ) -> BuckyResult { - unimplemented!() + rpath: &str, + ) -> RPathClient { + { + let clients = self.0.clients.read().await; + let found = clients + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id.object_id())) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return found.clone(); + } + } + + { + let client = RPathClient::new( + GroupRPath::new(group_id, dec_id.object_id().clone(), rpath.to_string()), + self.0.stack.dec_id().cloned(), + self.0.stack.non_service().clone(), + ); + + let mut clients = self.0.clients.write().await; + let client = clients + .entry(group_id) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert(client); + client.clone() + } + } + + async fn on_command( + &self, + cmd: GroupCommand, + ) -> BuckyResult> { + match cmd.into_cmd() { + crate::GroupCommandBodyContent::NewRPath(cmd) => { + self.on_new_rpath(cmd).await.map(|_| None) + } + crate::GroupCommandBodyContent::Execute(cmd) => { + self.on_execute(cmd).await.map(|r| Some(r)) + } + crate::GroupCommandBodyContent::ExecuteResult(_) => { + let msg = format!( + "should not get the cmd({:?}) in sdk", + GroupCommandType::ExecuteResult + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)) + } + crate::GroupCommandBodyContent::Verify(cmd) => self.on_verify(cmd).await.map(|_| None), + crate::GroupCommandBodyContent::Commited(cmd) => { + self.on_commited(cmd).await.map(|_| None) + } + } + } + + async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let group_id = &cmd.group_id; + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.rpath.as_str(); + + { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if found.is_some() { + return Ok(()); + } + } + + let delegate = factory + .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) + .await?; + + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(()); + } + }; + + new_service.start().await; + Ok(()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } + } + + async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try execute proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try execute proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let mut result = service + .on_execute(&cmd.proposal, &cmd.prev_state_id) + .await?; + + Ok(GroupCommandExecuteResult { + result_state_id: result.result_state_id.take(), + receipt: result.receipt.take(), + context: result.context.take(), + }) + } + + async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try verify proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try verify proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) + .await + } + + async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try commited proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try commited proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } +} + +#[async_trait::async_trait] +impl EventListenerAsyncRoutine + for GroupManager +{ + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + let req_common = ¶m.request.common; + if req_common.level != NONAPILevel::NOC + || req_common.source.zone.zone != self.0.local_zone + || self.0.local_zone.is_none() + || self.0.stack.dec_id().is_none() + { + log::warn!( + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id() + ); + + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let obj = ¶m.request.object; + match obj.object.as_ref() { + None => { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }) + } + Some(any_obj) => { + assert_eq!(any_obj.obj_type(), CoreObjectType::GroupCommand as u16); + if any_obj.obj_type() != CoreObjectType::GroupCommand as u16 { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let (cmd, remain) = GroupCommand::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + let resp_obj = self.on_command(cmd).await; + + let resp_cmd = resp_obj.map_or_else( + |err| Err(err), + |resp_obj| { + resp_obj.map_or(Ok(None), |resp_cmd| { + let resp_cmd = GroupCommand::from(resp_cmd); + resp_cmd.to_vec().map(|buf| { + Some(NONObjectInfo::new(resp_cmd.desc().object_id(), buf, None)) + }) + }) + }, + ); + + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: Some(resp_cmd.map(|cmd| NONPostObjectInputResponse { object: cmd })), + }) + } + } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 2fea6dcf7..ea032715b 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -1,26 +1,55 @@ use std::sync::Arc; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, - RawConvertTo, +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, }; -use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::NONObjectInfo; -struct RPathClientRaw {} +struct RPathClientRaw { + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, +} #[derive(Clone)] pub struct RPathClient(Arc); impl RPathClient { + pub(crate) fn new( + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, + ) -> Self { + Self(Arc::new(RPathClientRaw { + requestor, + rpath, + local_dec_id, + })) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + self.0 + .requestor + .post_object(NONPostObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: self.0.local_dec_id.clone(), + level: NONAPILevel::Router, + target: Some(proposal.rpath().group_id().clone()), + flags: 0, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), proposal.to_vec()?, None), + }) + .await + .map(|resp| resp.object) } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 81225ed72..cebe445dd 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,23 +1,133 @@ use std::sync::Arc; -use cyfs_base::BuckyResult; -use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, +}; -struct RPathServiceRaw {} +use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + +struct RPathServiceRaw { + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, +} #[derive(Clone)] pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load() -> BuckyResult { + pub fn rpath(&self) -> &GroupRPath { unimplemented!() } - pub fn rpath(&self) -> &GroupRPath { + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + // post http unimplemented!() } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub(crate) fn new( + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, + ) -> Self { + Self(Arc::new(RPathServiceRaw { + rpath, + requestor, + delegate, + stack, + })) + } + + pub(crate) async fn start(&self) -> BuckyResult { + // post create command unimplemented!() } + + pub(crate) async fn on_execute( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + ) -> BuckyResult { + self.0 + .delegate + .on_execute( + proposal, + prev_state_id, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_verify( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + self.0 + .delegate + .on_verify( + proposal, + prev_state_id, + execute_result, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_commited( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + self.0 + .delegate + .on_commited( + proposal, + prev_state_id, + execute_result, + block, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } +} + +struct GroupObjectMapProcessorImpl { + stack: SharedCyfsStack, +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorImpl { + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_single_op_env_with_access(access) + .await + } + + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_isolate_path_op_env_with_access(access) + .await + } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index eaaaed06e..d2dbcc517 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,7 +11,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; @@ -20,7 +20,7 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, }; /** diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index fc3d12c63..9bda7e340 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,6 @@ use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -130,3 +130,9 @@ impl RPathEventNotifier { assert!(result.is_err() || result.unwrap().is_none()); } } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 23202fddf..7a9708ccc 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -181,12 +181,12 @@ impl GroupManager { ) -> BuckyResult<()> { match msg { HotstuffPackage::Block(block) => { - let rpath = block.r_path(); + let rpath = block.rpath(); let service = self .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, Some(&block), Some(&remote), @@ -202,7 +202,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -218,7 +218,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -234,7 +234,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -250,7 +250,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -266,7 +266,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -278,9 +278,9 @@ impl GroupManager { } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { // TODO: unimplemented - // let rpath = header_block.r_path(); + // let rpath = header_block.rpath(); // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) // .await?; // client // .on_message( @@ -292,10 +292,10 @@ impl GroupManager { HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( @@ -313,7 +313,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -328,7 +328,7 @@ impl GroupManager { } _ => { let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) @@ -342,7 +342,7 @@ impl GroupManager { |status| status.block_desc.content().rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 41db0c25c..43fb8e559 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -78,13 +78,13 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.0.rpath); + assert_eq!(proposal.rpath(), &self.0.rpath); // TODO: signature let group = self .0 .non_driver - .get_group(proposal.r_path().group_id(), None, None) + .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 571c1ca13..99c3fed62 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -222,7 +222,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) @@ -248,7 +248,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 7e32fdc4d..1f2a46a73 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -321,16 +321,16 @@ impl std::fmt::Debug for HotstuffPackage { impl HotstuffPackage { pub(crate) fn rpath(&self) -> &GroupRPath { match self { - HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::Block(block) => block.rpath(), HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), - HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::StateChangeNotify(block, _) => block.rpath(), HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( |(_, addr)| addr.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 63158a865..029b09e78 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,12 +5,12 @@ use cyfs_base::{ ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_group_lib::GroupObjectMapProcessor; +use cyfs_core::GroupConsensusBlockObject; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a1a681259..3a762c1b6 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,12 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, - STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 2f162c331..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -94,7 +94,7 @@ pub struct SharedCyfsStack { // uni_stack uni_stack: Arc>, - requestor_holder: RequestorHolder, + requestor_holder: Arc>, } #[derive(Debug, Clone)] @@ -493,14 +493,15 @@ impl SharedCyfsStack { device_info: Arc::new(RwLock::new(None)), uni_stack: Arc::new(OnceCell::new()), - requestor_holder, + requestor_holder: Arc::new(RwLock::new(requestor_holder)), }; Ok(ret) } pub async fn stop(&self) { - self.requestor_holder.stop().await; + let requestor_holder = self.requestor_holder.read().unwrap(); + requestor_holder.stop().await; self.router_handlers.stop().await; @@ -744,6 +745,11 @@ impl SharedCyfsStack { pub fn uni_stack(&self) -> &UniCyfsStackRef { self.uni_stack.get_or_init(|| self.create_uni_stack()) } + + pub fn select_requestor(&self, requestor_type: &CyfsStackRequestorType) -> HttpRequestorRef { + let mut requestor_holder = self.requestor_holder.write().unwrap(); + requestor_holder.select_requestor(&self.param, requestor_type) + } } impl UniCyfsStack for SharedCyfsStack { diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index f7f305a83..431915a96 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: None, flags: 0, @@ -105,7 +105,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, From e6e1613ea09fdff521f317dfcaff809c264cff43 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 16:49:16 +0800 Subject: [PATCH 468/553] Interface for client --- src/component/cyfs-group-lib/Cargo.toml | 1 + src/component/cyfs-group-lib/src/delegate.rs | 1 + .../cyfs-group-lib/src/group_manager.rs | 255 ++++++++---------- .../cyfs-group-lib/src/input_request.rs | 0 src/component/cyfs-group-lib/src/lib.rs | 12 + .../cyfs-group-lib/src/output_request.rs | 7 + src/component/cyfs-group-lib/src/processor.rs | 6 + src/component/cyfs-group-lib/src/request.rs | 0 .../cyfs-group-lib/src/request_codec.rs | 21 ++ src/component/cyfs-group-lib/src/requestor.rs | 210 +++++++++++++++ .../cyfs-group-lib/src/rpath_client.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 14 +- .../cyfs-lib/src/non/output_request.rs | 20 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- 14 files changed, 391 insertions(+), 162 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/input_request.rs create mode 100644 src/component/cyfs-group-lib/src/output_request.rs create mode 100644 src/component/cyfs-group-lib/src/processor.rs create mode 100644 src/component/cyfs-group-lib/src/request.rs create mode 100644 src/component/cyfs-group-lib/src/request_codec.rs create mode 100644 src/component/cyfs-group-lib/src/requestor.rs diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index bad3d3112..740b303cd 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' itertools = "0.10.3" +http-types = '2.12' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 3cc99902b..d678438c3 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -9,6 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult>; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f93be45f0..f442d5c55 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,7 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, @@ -195,98 +195,28 @@ impl GroupManager { } async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { - match self.0.delegate_factory.as_ref() { - Some(factory) => { - let group_id = &cmd.group_id; - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.rpath.as_str(); - - { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - if found.is_some() { - return Ok(()); - } - } - - let delegate = factory - .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) - .await?; - - let new_service = { - let mut is_new = false; - - let mut services = self.0.services.write().await; - let service = services - .entry(group_id.clone()) - .or_insert_with(HashMap::new) - .entry(dec_id.clone()) - .or_insert_with(HashMap::new) - .entry(rpath.to_string()) - .or_insert_with(|| { - is_new = true; - - RPathService::new( - GroupRPath::new( - group_id.clone(), - dec_id.clone(), - rpath.to_string(), - ), - self.0.requestor.clone(), - delegate, - self.0.stack.clone(), - ) - }); - - if is_new { - service.clone() - } else { - return Ok(()); - } - }; - - new_service.start().await; - Ok(()) - } - None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), - } + self.find_or_restart_service( + &cmd.group_id, + self.0.stack.dec_id().unwrap(), + cmd.rpath.as_str(), + &cmd.with_block, + true, + ) + .await + .map(|_| ()) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try execute proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try execute proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) @@ -300,36 +230,16 @@ impl GroupManager { } async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try verify proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try verify proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -343,47 +253,102 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; - if cmd.proposal.rpath().dec_id() != dec_id { + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } + + async fn find_or_restart_service( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: &Option, + is_new: bool, + ) -> BuckyResult { + if dec_id != self.0.stack.dec_id().unwrap() { let msg = format!( - "try commited proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id + "try find proposal in different dec {:?}, expected: {:?}", + dec_id, + self.0.stack.dec_id().unwrap() ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - let service = { + { let services = self.0.services.read().await; let found = services .get(group_id) .and_then(|by_dec| by_dec.get(dec_id)) .and_then(|by_rpath| by_rpath.get(rpath)); - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try commited proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } + if let Some(found) = found { + return Ok(found.clone()); } - }; + } - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let delegate = factory + .create_rpath_delegate(group_id, rpath, with_block.as_ref(), is_new) + .await?; - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; - Ok(()) + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(service.clone()); + } + }; + + new_service.start().await; + Ok(new_service.clone()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } } } diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 34473bf07..519a64040 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,11 +1,23 @@ mod delegate; mod group_manager; +mod input_request; mod objects; +mod output_request; +mod processor; +mod request; +mod request_codec; +mod requestor; mod rpath_client; mod rpath_service; pub use delegate::*; pub use group_manager::*; +pub use input_request::*; pub use objects::*; +pub use output_request::*; +pub use processor::*; +pub(crate) use request::*; +pub use request_codec::*; +pub use requestor::*; pub use rpath_client::*; pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs new file mode 100644 index 000000000..c847668df --- /dev/null +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -0,0 +1,7 @@ +use cyfs_base::ObjectId; + +#[derive(Debug)] +pub struct GroupStartServiceOutputRequest { + pub group_id: ObjectId, + pub rpath: String, +} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs new file mode 100644 index 000000000..925061f3e --- /dev/null +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +#[async_trait::async_trait] +pub trait GroupOutputProcessor: Send + Sync {} + +pub type GroupOutputProcessorRef = Arc; diff --git a/src/component/cyfs-group-lib/src/request.rs b/src/component/cyfs-group-lib/src/request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs new file mode 100644 index 000000000..c4f330efc --- /dev/null +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -0,0 +1,21 @@ +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use serde_json::{Map, Value}; + +use crate::output_request::GroupStartServiceOutputRequest; + +impl JsonCodec for GroupStartServiceOutputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs new file mode 100644 index 000000000..437a01184 --- /dev/null +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + CYFS_API_LEVEL, +}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, +}; +use http_types::{Method, Request, Url}; + +use crate::{ + output_request::GroupStartServiceOutputRequest, + processor::{GroupOutputProcessor, GroupOutputProcessorRef}, +}; + +#[derive(Clone)] +pub struct GroupRequestor { + dec_id: ObjectId, + requestor: HttpRequestorRef, + service_url: Url, +} + +impl GroupRequestor { + pub fn new(dec_id: ObjectId, requestor: HttpRequestorRef) -> Self { + let addr = requestor.remote_addr(); + + let url = format!("http://{}/group/", addr); + let url = Url::parse(&url).unwrap(); + + Self { + dec_id, + requestor, + service_url: url, + } + } + + pub fn clone_processor(&self) -> GroupOutputProcessorRef { + Arc::new(self.clone()) + } + + fn encode_common_headers( + &self, + // action: NONAction, + com_req: &NONOutputRequestCommon, + http_req: &mut Request, + ) { + let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); + http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); + + RequestorHelper::encode_opt_header_with_encoding( + http_req, + cyfs_base::CYFS_REQ_PATH, + com_req.req_path.as_deref(), + ); + + // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + + http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); + + if let Some(target) = &com_req.target { + http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); + } + + if let Some(source) = &com_req.source { + http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); + } + + http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); + } + + fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(dec_id), + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, + } + } + + pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + log::info!("will start group service: {:?}", rpath); + + let url = self.service_url.join("start-service").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + let req = GroupStartServiceOutputRequest { + group_id: rpath.group_id().clone(), + rpath: rpath.rpath().to_string(), + }; + + self.encode_common_headers( + &Self::make_default_common(rpath.dec_id().clone()), + &mut http_req, + ); + let body = req.encode_string(); + http_req.set_body(body); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group start service failed, read body string error! req={:?} {}", + req, e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!("group start service success"); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group start service failed: rpath={:?}, status={}, {}", + rpath, + code, + e + ); + Err(e) + } + } + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + let proposal_id = proposal.desc().object_id(); + log::info!( + "will push proposal: {:?}, {}", + proposal.rpath(), + proposal_id + ); + + let url = self.service_url.join("push-proposal").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + self.encode_common_headers( + &Self::make_default_common(proposal.rpath().dec_id().clone()), + &mut http_req, + ); + + NONRequestorHelper::encode_object_info( + &mut http_req, + NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + ); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group push proposal failed, read body string error! req={:?}/{} {}", + proposal.rpath(), + proposal_id, + e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!( + "group push proposal success, req={:?}/{}", + proposal.rpath(), + proposal_id + ); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group push proposal failed: rpath={:?}/{}, status={}, {}", + proposal.rpath(), + proposal_id, + code, + e + ); + Err(e) + } + } + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupRequestor {} diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index ea032715b..7d7c9a613 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -32,6 +32,8 @@ impl RPathClient { &self.0.rpath } + // post proposal to the admins, it's same as calling to non.post_object with default parameters; + // and you can call the non.post_object with more parameters. pub async fn post_proposal( &self, proposal: &GroupProposal, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index cebe445dd..95811e339 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -6,11 +6,11 @@ use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; +use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; struct RPathServiceRaw { rpath: GroupRPath, - requestor: HttpRequestorRef, + requestor: GroupRequestor, delegate: Box, stack: SharedCyfsStack, } @@ -20,12 +20,12 @@ pub struct RPathService(Arc); impl RPathService { pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - unimplemented!() + self.0.requestor.push_proposal(proposal).await } pub(crate) fn new( @@ -35,16 +35,16 @@ impl RPathService { stack: SharedCyfsStack, ) -> Self { Self(Arc::new(RPathServiceRaw { + requestor: GroupRequestor::new(rpath.dec_id().clone(), requestor), rpath, - requestor, delegate, stack, })) } - pub(crate) async fn start(&self) -> BuckyResult { + pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - unimplemented!() + self.0.requestor.start_group_service(self.rpath()).await } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-lib/src/non/output_request.rs b/src/component/cyfs-lib/src/non/output_request.rs index d4950ce33..b6e96dcb3 100644 --- a/src/component/cyfs-lib/src/non/output_request.rs +++ b/src/component/cyfs-lib/src/non/output_request.rs @@ -4,7 +4,7 @@ use cyfs_base::*; use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NONOutputRequestCommon { // 请求路径,可为空 pub req_path: Option, @@ -130,14 +130,22 @@ impl NONUpdateObjectMetaOutputRequest { Self::new(NONAPILevel::NOC, object_id, access) } - pub fn new_non(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_non( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::NON, object_id, access); ret.common.target = target.map(|v| v.into()); ret } - pub fn new_router(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_router( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::Router, object_id, access); ret.common.target = target; @@ -243,7 +251,6 @@ impl NONGetObjectOutputRequest { } } - impl fmt::Display for NONGetObjectOutputRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "common: {}", self.common)?; @@ -338,7 +345,6 @@ impl fmt::Display for NONPostObjectOutputResponse { } } - // select #[derive(Clone)] pub struct NONSelectObjectOutputRequest { @@ -392,7 +398,6 @@ impl fmt::Display for NONSelectObjectOutputRequest { } } - #[derive(Clone)] pub struct NONSelectObjectOutputResponse { pub objects: Vec, @@ -470,7 +475,6 @@ impl fmt::Display for NONDeleteObjectOutputRequest { } } - #[derive(Clone)] pub struct NONDeleteObjectOutputResponse { pub object: Option, @@ -479,7 +483,7 @@ pub struct NONDeleteObjectOutputResponse { impl fmt::Display for NONDeleteObjectOutputResponse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "object: {:?}", self.object)?; - + Ok(()) } } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 431915a96..9333e7981 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::NOC, target: None, flags: 0, From 7b8f6ed26b6897fc8c3d200c7dcf7f3c69363abc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 21:35:56 +0800 Subject: [PATCH 469/553] Export to SDK --- .../cyfs-group-lib/src/input_request.rs | 10 + .../cyfs-group-lib/src/output_request.rs | 4 + src/component/cyfs-group-lib/src/processor.rs | 24 ++- .../cyfs-group-lib/src/request_codec.rs | 19 +- src/component/cyfs-group-lib/src/requestor.rs | 54 +++-- .../cyfs-group-lib/src/rpath_service.rs | 21 +- src/component/cyfs-stack/Cargo.toml | 1 + src/component/cyfs-stack/src/group/mod.rs | 5 + .../cyfs-stack/src/group/processor.rs | 25 +++ .../cyfs-stack/src/group/transform.rs | 190 ++++++++++++++++++ .../cyfs-stack/src/group_api/acl/group_acl.rs | 61 ++++++ .../cyfs-stack/src/group_api/acl/mod.rs | 3 + src/component/cyfs-stack/src/group_api/mod.rs | 7 + .../group_api/router/group_service_router.rs | 133 ++++++++++++ .../src/group_api/router/local_service.rs | 113 +++++++++++ .../cyfs-stack/src/group_api/router/mod.rs | 5 + .../src/group_api/service/group_handler.rs | 125 ++++++++++++ .../src/group_api/service/group_listener.rs | 77 +++++++ .../src/group_api/service/group_service.rs | 35 ++++ .../cyfs-stack/src/group_api/service/mod.rs | 7 + .../cyfs-stack/src/interface/http_listener.rs | 11 + .../src/interface/listener_manager.rs | 14 +- src/component/cyfs-stack/src/lib.rs | 2 + .../cyfs-stack/src/stack/cyfs_stack.rs | 12 +- 24 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/component/cyfs-stack/src/group/mod.rs create mode 100644 src/component/cyfs-stack/src/group/processor.rs create mode 100644 src/component/cyfs-stack/src/group/transform.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/group_acl.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/group_service_router.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/local_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_handler.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_listener.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/mod.rs diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index e69de29bb..0f861ea3c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -0,0 +1,10 @@ +use cyfs_base::ObjectId; + +pub struct GroupStartServiceInputRequest { + pub group_id: ObjectId, + pub rpath: String, +} + +pub struct GroupStartServiceInputResponse {} + +pub struct GroupPushProposalInputResponse {} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index c847668df..f65e02e3e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -5,3 +5,7 @@ pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, pub rpath: String, } + +pub struct GroupStartServiceOutputResponse {} + +pub struct GroupPushProposalOutputResponse {} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 925061f3e..9aec5a354 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -1,6 +1,26 @@ use std::sync::Arc; +use cyfs_base::BuckyResult; +use cyfs_core::GroupProposal; +use cyfs_lib::NONOutputRequestCommon; + +use crate::{ + GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, +}; + #[async_trait::async_trait] -pub trait GroupOutputProcessor: Send + Sync {} +pub trait GroupOutputProcessor: Send + Sync { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult; + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} -pub type GroupOutputProcessorRef = Arc; +pub type GroupOutputProcessorRef = Arc>; diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index c4f330efc..58404d6b0 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::output_request::GroupStartServiceOutputRequest; +use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { @@ -19,3 +19,20 @@ impl JsonCodec for GroupStartServiceOutputReques }) } } + +impl JsonCodec for GroupStartServiceInputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 437a01184..462b1df85 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -13,6 +13,7 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, + GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -37,7 +38,7 @@ impl GroupRequestor { } pub fn clone_processor(&self) -> GroupOutputProcessorRef { - Arc::new(self.clone()) + Arc::new(Box::new(self.clone())) } fn encode_common_headers( @@ -70,7 +71,7 @@ impl GroupRequestor { http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { NONOutputRequestCommon { req_path: None, source: None, @@ -81,21 +82,23 @@ impl GroupRequestor { } } - pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + pub async fn start_service( + &self, + req_common: NONOutputRequestCommon, + group_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); let url = self.service_url.join("start-service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { - group_id: rpath.group_id().clone(), - rpath: rpath.rpath().to_string(), + group_id: group_id.clone(), + rpath: rpath.to_string(), }; - self.encode_common_headers( - &Self::make_default_common(rpath.dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -123,7 +126,7 @@ impl GroupRequestor { log::debug!("group start service success"); - Ok(()) + Ok(GroupStartServiceOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -138,7 +141,11 @@ impl GroupRequestor { } } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + proposal: &GroupProposal, + ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", @@ -149,10 +156,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers( - &Self::make_default_common(proposal.rpath().dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, @@ -189,7 +193,7 @@ impl GroupRequestor { proposal_id ); - Ok(()) + Ok(GroupPushProposalOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -207,4 +211,20 @@ impl GroupRequestor { } #[async_trait::async_trait] -impl GroupOutputProcessor for GroupRequestor {} +impl GroupOutputProcessor for GroupRequestor { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupRequestor::push_proposal(self, req_common, &req).await + } +} diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 95811e339..66d0d83f4 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; @@ -25,7 +25,14 @@ impl RPathService { pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - self.0.requestor.push_proposal(proposal).await + self.0 + .requestor + .push_proposal( + GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal, + ) + .await + .map(|_| {}) } pub(crate) fn new( @@ -44,7 +51,15 @@ impl RPathService { pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - self.0.requestor.start_group_service(self.rpath()).await + self.0 + .requestor + .start_service( + GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + self.rpath().group_id(), + self.rpath().rpath(), + ) + .await + .map(|_| {}) } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index d005147ec..ca254632f 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -16,6 +16,7 @@ cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-group = { path = "../../component/cyfs-group" } +cyfs-group-lib = { path = "../../component/cyfs-group-lib" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } diff --git a/src/component/cyfs-stack/src/group/mod.rs b/src/component/cyfs-stack/src/group/mod.rs new file mode 100644 index 000000000..da7603e40 --- /dev/null +++ b/src/component/cyfs-stack/src/group/mod.rs @@ -0,0 +1,5 @@ +mod processor; +mod transform; + +pub(crate) use processor::*; +pub(crate) use transform::*; \ No newline at end of file diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs new file mode 100644 index 000000000..b6fe1544b --- /dev/null +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -0,0 +1,25 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +#[async_trait::async_trait] +pub(crate) trait GroupInputProcessor: Sync + Send { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult; + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} + +pub(crate) type GroupInputProcessorRef = Arc; diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs new file mode 100644 index 000000000..50abe1afb --- /dev/null +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -0,0 +1,190 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, + GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +use super::{GroupInputProcessor, GroupInputProcessorRef}; + +// 实现从input到output的转换 +pub(crate) struct GroupInputTransformer { + processor: GroupOutputProcessorRef, +} + +impl GroupInputTransformer { + pub fn new(processor: GroupOutputProcessorRef) -> GroupInputProcessorRef { + let ret = Self { processor }; + Arc::new(ret) + } + + fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { + NONOutputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 来源DEC + dec_id: common.source.get_opt_dec().cloned(), + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source: common.source.zone.device, + } + } + + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let out_req = GroupStartServiceOutputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let out_resp = self + .processor + .start_service(Self::convert_common(req_common), out_req) + .await?; + + let resp = GroupStartServiceInputResponse {}; + + Ok(resp) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let out_resp = self + .processor + .push_proposal(Self::convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalInputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupInputTransformer { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + GroupInputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupInputTransformer::push_proposal(self, req_common, req).await + } +} + +// 实现从output到input的转换 +pub(crate) struct GroupOutputTransformer { + processor: GroupInputProcessorRef, + source: RequestSourceInfo, +} + +impl GroupOutputTransformer { + fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + let mut source = self.source.clone(); + if let Some(dec_id) = common.dec_id { + source.set_dec(dec_id); + } + + NONInputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source, + } + } + + pub fn new( + processor: GroupInputProcessorRef, + source: RequestSourceInfo, + ) -> GroupOutputProcessorRef { + let ret = Self { processor, source }; + Arc::new(Box::new(ret)) + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let in_resp = self + .processor + .push_proposal(self.convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalOutputResponse {}; + + Ok(resp) + } + + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + let in_req = GroupStartServiceInputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let in_resp = self + .processor + .start_service(self.convert_common(req_common), in_req) + .await?; + + let resp = GroupStartServiceOutputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupOutputTransformer { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupOutputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupOutputTransformer::push_proposal(self, req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs new file mode 100644 index 000000000..0e789c023 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -0,0 +1,61 @@ +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +pub struct GroupAclInnerInputProcessor { + next: GroupInputProcessorRef, +} + +impl GroupAclInnerInputProcessor { + pub(crate) fn new(next: GroupInputProcessorRef) -> GroupInputProcessorRef { + Arc::new(Self { next }) + } + + fn check_local_zone_permit( + &self, + service: &str, + source: &RequestSourceInfo, + ) -> BuckyResult<()> { + // TODO + // if !source.is_current_zone() { + // let msg = format!( + // "{} service valid only in current zone! source={:?}, category={}", + // service, + // source.zone.device, + // source.zone.zone_category.as_str() + // ); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, msg)); + // } + + Ok(()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupAclInnerInputProcessor { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.next.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.next.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/mod.rs b/src/component/cyfs-stack/src/group_api/acl/mod.rs new file mode 100644 index 000000000..53dad00b3 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/mod.rs @@ -0,0 +1,3 @@ +mod group_acl; + +pub use group_acl::*; diff --git a/src/component/cyfs-stack/src/group_api/mod.rs b/src/component/cyfs-stack/src/group_api/mod.rs new file mode 100644 index 000000000..29e257330 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/mod.rs @@ -0,0 +1,7 @@ +mod acl; +mod router; +mod service; + +pub(crate) use acl::*; +pub(crate) use router::*; +pub(crate) use service::*; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs new file mode 100644 index 000000000..2c1a2841f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyResult, DeviceId, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::{ + forward::ForwardProcessorManager, + group::{GroupInputProcessor, GroupInputProcessorRef, GroupInputTransformer}, + group_api::GroupAclInnerInputProcessor, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupServiceRouter { + processor: GroupInputProcessorRef, + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, +} + +impl GroupServiceRouter { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + processor: GroupInputProcessorRef, + ) -> GroupInputProcessorRef { + let processor = GroupAclInnerInputProcessor::new(processor); + let ret = Self { + processor, + zone_manager, + forward, + }; + Arc::new(ret) + } + + async fn get_forward( + &self, + dec_id: ObjectId, + target: DeviceId, + ) -> BuckyResult { + let requestor = self.forward.get(&target).await?; + let group_requestor = GroupRequestor::new(dec_id, requestor); + Ok(GroupInputTransformer::new( + group_requestor.clone_processor(), + )) + } + + // 不同于non/ndn的router,如果target为空,那么表示本地device + async fn get_target(&self, target: Option<&ObjectId>) -> BuckyResult> { + let ret = match target { + Some(object_id) => { + let info = self + .zone_manager + .target_zone_manager() + .resolve_target(Some(object_id)) + .await?; + if info.target_device == *self.zone_manager.get_current_device_id() { + None + } else { + Some(info.target_device) + } + } + None => None, + }; + + Ok(ret) + } + + async fn get_processor( + &self, + dec_id: ObjectId, + target: Option<&ObjectId>, + ) -> BuckyResult { + if let Some(device_id) = self.get_target(target).await? { + debug!("group target resolved: {:?} -> {}", target, device_id); + let processor = self.get_forward(dec_id, device_id).await?; + Ok(processor) + } else { + Ok(self.processor.clone()) + } + } + + pub async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + pub async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupServiceRouter { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs new file mode 100644 index 000000000..e14691b5e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc}; +use cyfs_core::{GroupProposal, GroupProposalObject}; +use cyfs_group::GroupManager; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; + +#[derive(Clone)] +pub(crate) struct LocalGroupService { + group_manager: GroupManager, +} + +impl LocalGroupService { + pub(crate) fn new(group_manager: GroupManager) -> Self { + Self { group_manager } + } + + pub fn clone_processor(&self) -> GroupInputProcessorRef { + Arc::new(self.clone()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for LocalGroupService { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.group_manager + .find_rpath_service( + &req.group_id, + &req_common.source.dec, + req.rpath.as_str(), + true, + ) + .await + .map(|_| GroupStartServiceInputResponse {}) + .map_err(|err| { + log::error!( + "group start service {}-{}-{} failed {:?}", + req.group_id, + req_common.source.dec, + req.rpath, + err + ); + err + }) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let proposal_id = req.desc().object_id(); + let rpath = req.rpath().clone(); + if &req_common.source.dec != rpath.dec_id() { + let msg = format!( + "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + req_common.source.dec + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let service = self + .group_manager + .find_rpath_service( + req.rpath().group_id(), + &req_common.source.dec, + rpath.rpath(), + true, + ) + .await + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed when find the service {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + })?; + + service + .push_proposal(req) + .await + .map(|_| GroupPushProposalInputResponse {}) + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + }) + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/mod.rs b/src/component/cyfs-stack/src/group_api/router/mod.rs new file mode 100644 index 000000000..877b4eff6 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/mod.rs @@ -0,0 +1,5 @@ +mod group_service_router; +mod local_service; + +pub use group_service_router::*; +pub(crate) use local_service::*; diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs new file mode 100644 index 000000000..f01f2eaa5 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -0,0 +1,125 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; + +use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; + +#[derive(Clone)] +pub(crate) struct GroupRequestHandler { + processor: GroupInputProcessorRef, +} + +impl GroupRequestHandler { + pub fn new(processor: GroupInputProcessorRef) -> Self { + Self { processor } + } + + // 解析通用header字段 + fn decode_common_headers( + req: &NONInputHttpRequest, + ) -> BuckyResult { + // req_path + let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( + &req.request, + cyfs_base::CYFS_REQ_PATH, + )?; + + // 尝试提取flags + let flags: Option = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; + + // 尝试提取default_action字段 + let level = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; + + // 尝试提取target字段 + let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; + + let ret = NONInputRequestCommon { + req_path, + source: req.source.clone(), + level: level.unwrap_or_default(), + target, + flags: flags.unwrap_or(0), + }; + + Ok(ret) + } + + // group/start-service + pub async fn process_start_service( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_start_service(req).await { + Ok(_resp) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_start_service( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + let common = Self::decode_common_headers(&req)?; + + // 提取body里面的object对象,如果有的话 + let body = req.request.body_json().await.map_err(|e| { + let msg = format!("group start service failed, read body bytes error! {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidParam, msg) + })?; + + let req = GroupStartServiceInputRequest::decode_json(&body)?; + + self.processor.start_service(common, req).await + } + + pub async fn process_push_proposal( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_push_proposal(req).await { + Ok(_) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_push_proposal( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + // 检查action + // let action = Self::decode_action(&req, NONAction::PutObject)?; + // if action != NONAction::PutObject { + // let msg = format!("invalid non put_object action! {:?}", action); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + // } + + let common = Self::decode_common_headers(&req)?; + let object = NONRequestorHelper::decode_object_info(&mut req.request).await?; + let (proposal, remain) = GroupProposal::raw_decode(object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + // let access: Option = + // RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_ACCESS)?; + // let access = access.map(|v| AccessString::new(v)); + + info!("recv push proposal: {}", object.object_id); + + self.processor.push_proposal(common, proposal).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs new file mode 100644 index 000000000..163228d1f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -0,0 +1,77 @@ +use cyfs_lib::RequestProtocol; +use tide::Response; + +use crate::{non::NONInputHttpRequest, ZoneManagerRef}; + +use super::GroupRequestHandler; + +enum GroupRequestType { + StartService, + PushProposal, +} + +pub(crate) struct GroupRequestHandlerEndpoint { + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, +} + +impl GroupRequestHandlerEndpoint { + fn new( + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, + ) -> Self { + Self { + zone_manager, + protocol, + req_type, + handler, + } + } + + async fn process_request(&self, req: tide::Request) -> Response { + let req = match NONInputHttpRequest::new(&self.zone_manager, &self.protocol, req).await { + Ok(v) => v, + Err(resp) => return resp, + }; + match self.req_type { + GroupRequestType::StartService => self.handler.process_start_service(req).await, + GroupRequestType::PushProposal => self.handler.process_push_proposal(req).await, + } + } + + pub fn register_server( + zone_manager: &ZoneManagerRef, + protocol: &RequestProtocol, + handler: &GroupRequestHandler, + server: &mut tide::Server<()>, + ) { + server.at("/group/start-service").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::StartService, + handler.clone(), + )); + + server.at("group/push-proposal").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::PushProposal, + handler.clone(), + )); + } +} + +#[async_trait::async_trait] +impl tide::Endpoint for GroupRequestHandlerEndpoint +where + State: Clone + Send + Sync + 'static, +{ + async fn call(&self, req: tide::Request) -> tide::Result { + let resp = self.process_request(req).await; + Ok(resp) + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_service.rs b/src/component/cyfs-stack/src/group_api/service/group_service.rs new file mode 100644 index 000000000..3a25e282e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_service.rs @@ -0,0 +1,35 @@ +use cyfs_group::GroupManager; + +use crate::{ + forward::ForwardProcessorManager, + group::GroupInputProcessorRef, + group_api::{GroupServiceRouter, LocalGroupService}, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupService { + router: GroupInputProcessorRef, + local_service: LocalGroupService, +} + +impl GroupService { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + group_manager: GroupManager, + ) -> Self { + let local_service = LocalGroupService::new(group_manager); + let router = + GroupServiceRouter::new(forward, zone_manager, local_service.clone_processor()); + + Self { + router, + local_service, + } + } + + pub(crate) fn clone_processor(&self) -> GroupInputProcessorRef { + self.router.clone() + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/mod.rs b/src/component/cyfs-stack/src/group_api/service/mod.rs new file mode 100644 index 000000000..1140a741d --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/mod.rs @@ -0,0 +1,7 @@ +mod group_service; +mod group_listener; +mod group_handler; + +pub(crate) use group_service::*; +pub(crate) use group_listener::*; +pub(crate) use group_handler::*; diff --git a/src/component/cyfs-stack/src/interface/http_listener.rs b/src/component/cyfs-stack/src/interface/http_listener.rs index 21b6e86e3..e9ef12523 100644 --- a/src/component/cyfs-stack/src/interface/http_listener.rs +++ b/src/component/cyfs-stack/src/interface/http_listener.rs @@ -1,6 +1,7 @@ use crate::acl::AclManagerRef; use crate::crypto_api::*; use crate::front::{FrontProtocolHandler, FrontRequestHandlerEndpoint}; +use crate::group_api::{GroupRequestHandler, GroupRequestHandlerEndpoint, GroupService}; use crate::name::NameResolver; use crate::ndn_api::*; use crate::non_api::*; @@ -75,6 +76,7 @@ impl ObjectHttpListener { global_state_meta: &GlobalStateMetaService, name_resolver: &NameResolver, zone_manager: &ZoneManagerRef, + group_service: &GroupService, ) -> Self { let mut server = new_server(); @@ -225,6 +227,15 @@ impl ObjectHttpListener { &mut server, ); + // group manager + let handler = GroupRequestHandler::new(group_service.clone_processor()); + GroupRequestHandlerEndpoint::register_server( + zone_manager, + &protocol, + &handler, + &mut server, + ); + Self { server } } diff --git a/src/component/cyfs-stack/src/interface/listener_manager.rs b/src/component/cyfs-stack/src/interface/listener_manager.rs index c6b5510be..76d3c4e9d 100644 --- a/src/component/cyfs-stack/src/interface/listener_manager.rs +++ b/src/component/cyfs-stack/src/interface/listener_manager.rs @@ -9,6 +9,7 @@ use crate::acl::AclManagerRef; use crate::app::AuthenticatedAppList; use crate::config::StackGlobalConfig; use crate::events::RouterEventsManager; +use crate::group_api::GroupService; use crate::interface::http_ws_listener::ObjectHttpWSService; use crate::name::NameResolver; use crate::rmeta_api::GlobalStateMetaService; @@ -18,7 +19,7 @@ use crate::stack::ObjectServices; use crate::zone::ZoneRoleManager; use cyfs_base::*; use cyfs_bdt::StackGuard; -use cyfs_lib::{RequestProtocol, BrowserSanboxMode}; +use cyfs_lib::{BrowserSanboxMode, RequestProtocol}; use cyfs_debug::Mutex; use std::net::SocketAddr; @@ -131,6 +132,7 @@ impl ObjectListenerManager { root_state: &GlobalStateService, local_cache: &GlobalStateLocalService, global_state_meta: &GlobalStateMetaService, + group_service: &GroupService, ) { assert!(self.listeners.is_empty()); @@ -151,6 +153,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); @@ -172,18 +175,14 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); let http_server = DefaultHttpServer::new(raw_handler.into(), default_handler.clone()); let http_server = match config.get_stack_params().front.browser_mode { BrowserSanboxMode::None => http_server.into(), - mode @ _ => { - BrowserSanboxHttpServer::new( - http_server.into(), - mode, - ).into() - } + mode @ _ => BrowserSanboxHttpServer::new(http_server.into(), mode).into(), }; self.http_tcp_server = Some(http_server); } @@ -202,6 +201,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); diff --git a/src/component/cyfs-stack/src/lib.rs b/src/component/cyfs-stack/src/lib.rs index c180fe861..832029d33 100644 --- a/src/component/cyfs-stack/src/lib.rs +++ b/src/component/cyfs-stack/src/lib.rs @@ -29,6 +29,8 @@ mod config; mod front; mod rmeta_api; mod rmeta; +mod group; +mod group_api; pub use stack::*; pub use storage::*; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 8cf9bcad0..493f6ace8 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -10,6 +10,7 @@ use crate::crypto_api::{CryptoService, ObjectCrypto, ObjectVerifier}; use crate::events::RouterEventsManager; use crate::forward::ForwardProcessorManager; use crate::front::FrontService; +use crate::group_api::GroupService; use crate::interface::{ ObjectListenerManager, ObjectListenerManagerParams, ObjectListenerManagerRef, }; @@ -105,7 +106,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupManager, + group_service: GroupService, } impl CyfsStackImpl { @@ -437,6 +438,8 @@ impl CyfsStackImpl { bdt_stack.clone(), global_state_manager.clone_processor(), )?; + let group_service = + GroupService::new(forward_manager.clone(), zone_manager.clone(), group_manager); let mut stack = Self { config, @@ -474,7 +477,7 @@ impl CyfsStackImpl { acl_manager, - group_manager, + group_service, }; // init an system-dec router-handler processor for later use @@ -564,6 +567,7 @@ impl CyfsStackImpl { &stack.root_state, &stack.local_cache, &stack.global_state_meta, + &stack.group_service, ); let interface = Arc::new(interface); @@ -1163,8 +1167,8 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupManager { - &self.stack.group_manager + pub fn group_service(&self) -> &GroupService { + &self.stack.group_service } // use system dec as default dec From 648659e2d92b6c3afafe193784804bd244dd2537 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Mar 2023 17:39:29 +0800 Subject: [PATCH 470/553] Remove several unused import --- src/component/cyfs-group-lib/src/request_codec.rs | 2 +- src/component/cyfs-group-lib/src/requestor.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 58404d6b0..4c7ddfe88 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 462b1df85..341bff3e3 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -4,7 +4,7 @@ use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, CYFS_API_LEVEL, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, }; @@ -116,7 +116,7 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupStartServiceOutputResponse::decode_string(&body).map_err(|e| { // error!( // "decode group start service resp from body string error: body={} {}", // body, e, @@ -179,9 +179,9 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { // error!( - // "decode group start service resp from body string error: body={} {}", + // "decode group push proposal resp from body string error: body={} {}", // body, e, // ); // e From 38f85ca5f16282053e5b00b6c5ae10cad7bbc405 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 19:19:00 +0800 Subject: [PATCH 471/553] Debug --- src/component/cyfs-group-lib/Cargo.toml | 1 - .../cyfs-group-lib/src/group_manager.rs | 138 +++++- src/component/cyfs-group-lib/src/requestor.rs | 11 +- .../cyfs-group/src/dec/group_events.rs | 43 +- .../cyfs-group/src/dec/group_manager.rs | 10 +- .../cyfs-group/src/dec/rpath_service.rs | 7 +- .../src/group_api/service/group_listener.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 21 +- .../cyfs-stack/src/zone/zone_manager.rs | 20 +- src/tests/group-example/Cargo.toml | 4 +- src/tests/group-example/src/main.rs | 436 ++++++++---------- 11 files changed, 407 insertions(+), 288 deletions(-) diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index 740b303cd..68931728c 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -32,5 +32,4 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f442d5c55..61a11698d 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -7,7 +7,7 @@ use cyfs_base::{ }; use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -68,11 +68,14 @@ impl GroupManager { // TODO: other filters? only local zone let filter = format!( - "obj_type == {} && dec_id == {}", + "obj_type == {} && source.dec_id == {} && source.zone_category == {}", CoreObjectType::GroupCommand as u16, dec_id, + DeviceZoneCategory::CurrentZone.to_string(), ); + // let filter = "*".to_string(); + router_handler_manager .post_object() .add_handler( @@ -80,7 +83,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - None, + Some("group-inner".to_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) @@ -120,7 +123,38 @@ impl GroupManager { rpath: String, delegate: Box, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap().clone(); + + { + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(&dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath.as_str())); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + RPathService::new( + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + Ok(service.clone()) + } } pub async fn find_rpath_service( @@ -128,7 +162,20 @@ impl GroupManager { group_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap(); + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + found.map_or( + Err(BuckyError::new( + BuckyErrorCode::NotFound, + "please start the service first", + )), + |service| Ok(service.clone()), + ) } pub async fn rpath_client( @@ -204,6 +251,16 @@ impl GroupManager { ) .await .map(|_| ()) + .map_err(|err| { + log::warn!( + "group on_new_rpath {}-{:?}-{} failed, err: {:?}", + cmd.group_id, + self.0.stack.dec_id(), + cmd.rpath, + err + ); + err + }) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { @@ -216,11 +273,27 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; Ok(GroupCommandExecuteResult { result_state_id: result.result_state_id.take(), @@ -239,7 +312,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_verify find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -250,6 +331,14 @@ impl GroupManager { service .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) .await + .map_err(|err| { + log::warn!( + "group on_verify {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + }) } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { @@ -262,7 +351,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_commited find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -361,27 +458,38 @@ impl EventListenerAsyncRoutine BuckyResult { let req_common = ¶m.request.common; - if req_common.level != NONAPILevel::NOC - || req_common.source.zone.zone != self.0.local_zone + let obj = ¶m.request.object; + + log::debug!( + "group-command handle, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) + ); + + if !req_common.source.zone.is_current_zone() || self.0.local_zone.is_none() + // || req_common.source.zone.zone != self.0.local_zone || self.0.stack.dec_id().is_none() { log::warn!( - "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", req_common.level, req_common.source.zone, self.0.local_zone, - self.0.stack.dec_id() + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) ); return Ok(RouterHandlerPostObjectResult { - action: RouterHandlerAction::Reject, + action: RouterHandlerAction::Pass, request: None, response: None, }); } - let obj = ¶m.request.object; match obj.object.as_ref() { None => { return Ok(RouterHandlerPostObjectResult { diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 341bff3e3..b77f93dad 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -6,7 +6,8 @@ use cyfs_base::{ }; use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ - HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, + HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, + RequestorHelper, }; use http_types::{Method, Request, Url}; @@ -43,7 +44,7 @@ impl GroupRequestor { fn encode_common_headers( &self, - // action: NONAction, + action: NONAction, com_req: &NONOutputRequestCommon, http_req: &mut Request, ) { @@ -56,7 +57,7 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); @@ -98,7 +99,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -156,7 +157,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 9bda7e340..a25accb19 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,9 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -32,13 +35,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -78,13 +86,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -111,16 +124,26 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd + .to_vec() + .expect(format!("on_commited {} failed for encode", self.non_driver.dec_id()).as_str()); + let any_obj = cyfs_base::AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(object_raw_buf.as_slice()).expect( + format!( + "on_commited {} failed for convert to any", + self.non_driver.dec_id() + ) + .as_str(), + ), + ); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec().expect( - format!("on_commited {} failed for encode", self.non_driver.dec_id()) - .as_str(), - ), - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7a9708ccc..579f63831 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawConvertTo, RsaCPUObjectSigner, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; @@ -488,6 +488,10 @@ impl GroupManager { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); let result = self .local_info() .non_driver @@ -495,8 +499,8 @@ impl GroupManager { dec_id, NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index b4b90972f..1f2e836a1 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -66,6 +66,11 @@ impl RPathService { } pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + log::info!( + "group({:?}) push proposal {}", + self.rpath(), + proposal.desc().object_id() + ); self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 163228d1f..47be52927 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").post(Self::new( + server.at("/group/start-service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").post(Self::new( + server.at("group/push-proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9333e7981..fa136b3fa 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::NOC, + level: NONAPILevel::Router, target: None, flags: 0, @@ -90,10 +90,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { obj: NONObjectInfo, to: Option<&ObjectId>, ) -> BuckyResult> { + let obj_type_code = obj.object_id.obj_type_code(); + let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some("group-inner".to_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -105,7 +108,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, @@ -114,5 +117,15 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) .await .map(|resp| resp.object) + .map_err(|err| { + log::warn!( + "group post object(type={:?}/{:?}) to {:?} failed {:?}", + obj_type_code, + obj_type, + to, + err + ); + err + }) } } diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 6819b991d..61f284bc4 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -652,7 +652,25 @@ impl ZoneManager { owner_id, work_mode, list ); - return Ok((work_mode, list.to_owned())); + if obj_type == ObjectTypeCode::People { + return Ok((work_mode, list.to_owned())); + } else if obj_type == ObjectTypeCode::Group { + let group = owner_object.into_group(); + // TODO: 先简单处理,找最近的OOD,后面可能要依据具体操作向不同身份发起请求; + // 比如:读操作向任意member请求即可 + let list = group + .ood_list_with_distance( + self.get_current_device_id().object_id(), + ) + .into_iter() + .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) + .map(|id| DeviceId::try_from(id).unwrap()) + .collect(); + return Ok((work_mode, list)); + } else { + unreachable!() + } + /* let ood_device_id = list[0].clone(); let obj_type = ood_device_id.object_id().obj_type_code(); diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 01094f12a..2cf31aba9 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -23,9 +23,9 @@ cyfs-core = { path = '../../component/cyfs-core' } cyfs-bdt = { path = '../../component/cyfs-bdt' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } -cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 88450ac1b..e74f3c5d6 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,36 +1,43 @@ -use std::{clone, sync::Arc, time::Duration}; +use std::{clone, collections::HashSet, sync::Arc, time::Duration}; +use async_std::sync::Mutex; use cyfs_base::{ AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_group::IsCreateRPath; +use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, - NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, + NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, + RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; +use crate::{ + Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}, + GroupDecService::MyRPathDelegate, +}; mod Common { - use std::{fmt::format, io::ErrorKind, sync::Arc}; + use std::{ + fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, + }; - use async_std::{fs, stream::StreamExt}; + use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId, DecAppObj}; - use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_core::{DecApp, DecAppId}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, @@ -348,6 +355,8 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, + rpc_port: u16, + ws_port: u16, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -369,13 +378,19 @@ mod Common { config: CyfsStackConfigParams { isolate: Some(device.desc().object_id().to_string()), sync_service: false, - shared_stack: false, + shared_stack: true, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], - tcp_listeners: vec![], - ws_listener: None, + tcp_listeners: vec![SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + rpc_port, + ))], + ws_listener: Some(SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + ws_port, + ))), }, meta: CyfsStackMetaParams { target: MetaMinerTarget::Dev, @@ -454,9 +469,20 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, - ) -> CyfsStack { - let params = - init_stack_params(people, private_key, device, admins, members, group, dec_app); + rpc_port: u16, + ws_port: u16, + ) -> (CyfsStack, SharedCyfsStack) { + let params = init_stack_params( + people, + private_key, + device, + admins, + members, + group, + dec_app, + rpc_port, + ws_port, + ); log::info!("cyfs-stack.open"); @@ -468,14 +494,23 @@ mod Common { }) .unwrap(); - stack + async_std::task::sleep(Duration::from_millis(1000)).await; + + let shared_stack = + SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) + .await + .unwrap(); + + shared_stack.wait_online(None).await.unwrap(); + + (stack, shared_stack) } } mod Client { // use cyfs_base::ObjectId; // use cyfs_core::GroupProposal; - // use cyfs_group::RPathClient; + // use cyfs_group_lib::RPathClient; // pub struct DecClient {} @@ -505,12 +540,14 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathService; + use cyfs_group_lib::{ + DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, + RPathService, + }; use cyfs_lib::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, - NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, SharedCyfsStack, }; - use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -518,16 +555,18 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { - let group_mgr = cyfs_stack.group_mgr(); - - group_mgr - .register( - dec_app_id.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), - ) - .await - .unwrap(); + pub async fn run( + cyfs_stack: &SharedCyfsStack, + local_name: String, + dec_app_id: DecAppId, + ) -> GroupManager { + let group_mgr = GroupManager::open( + cyfs_stack.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + &cyfs_lib::CyfsStackRequestorType::Http, + ) + .await + .unwrap(); // let source = RequestSourceInfo { // protocol: todo!(), @@ -541,6 +580,8 @@ mod GroupDecService { // .handlers(&RouterHandlerChain::PostRouter) // .post_object() // .add_handler(RouterHandler::new()); + + group_mgr } } @@ -570,7 +611,7 @@ mod GroupDecService { impl GroupRPathDelegateFactory { pub fn is_accept( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, ) -> bool { @@ -583,27 +624,18 @@ mod GroupDecService { impl DelegateFactory for GroupRPathDelegateFactory { async fn create_rpath_delegate( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { + if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } } pub struct MyRPathDelegate { @@ -621,73 +653,19 @@ mod GroupDecService { } impl MyRPathDelegate { - // pub async fn get_value_from_state_tree_with_single_op_envs( - // pre_state_id: Option, - // object_map_processor: &dyn GroupObjectMapProcessor, - // ) -> BuckyResult<( - // Option, - // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - // )> { - // let mut single_op_envs = vec![]; - // let mut parent_map_id = pre_state_id; - // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - // let single_op_env = object_map_processor.create_single_op_env().await.expect( - // format!( - // "create_single_op_env load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // parent_map_id = match parent_map_id { - // Some(parent_map_id) => { - // single_op_env.load(&parent_map_id).await.expect( - // format!( - // "load folder {} parent with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // single_op_env.get_by_key(folder).await.expect( - // format!( - // "load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ) - // } - // None => { - // single_op_env - // .create_new(ObjectMapSimpleContentType::Map) - // .await - // .expect( - // format!( - // "create folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // None - // } - // }; - // single_op_envs.push((single_op_env, folder, parent_map_id)); - // } - - // Ok((parent_map_id, single_op_envs)) - // } - pub async fn execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); - let pre_value = match pre_state_id { - Some(pre_state_id) => { - state_op_env.load(&pre_state_id).await?; + let prev_value = match prev_state_id { + Some(prev_state_id) => { + state_op_env.load(prev_state_id.to_owned()).await?; state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -708,13 +686,13 @@ mod GroupDecService { let result_value = { /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_value.map_or(0, |pre_value| { - let buf = pre_value.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + let prev_value = prev_value.map_or(0, |prev_value| { + let buf = prev_value.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let delta_buf = proposal.params().as_ref().unwrap().as_slice(); @@ -722,7 +700,7 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let value = pre_value + delta; + let value = prev_value + delta; ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() @@ -731,13 +709,13 @@ mod GroupDecService { let result_state_id = { state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) .await .expect( format!( "set_with_path {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), @@ -746,34 +724,11 @@ mod GroupDecService { format!( "commit {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), ) - // let mut sub_folder_value = result_value; - // for (parent_single_op_env, folder, sub_folder_prev_value) in - // single_op_envs.into_iter().rev() - // { - // parent_single_op_env - // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - // .await - // .expect( - // format!( - // "update folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // sub_folder_value = parent_single_op_env.commit().await.expect( - // format!( - // "commit folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // } - // sub_folder_value }; let receipt = { @@ -791,11 +746,11 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_value + proposal + context + * (result_state_id, return_object) = prev_value + proposal + context */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id), + result_state_id: Some(result_state_id.root), receipt, }) } @@ -803,21 +758,21 @@ mod GroupDecService { pub async fn verify( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult { + ) -> BuckyResult<()> { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context + * == prev_state_id + proposal + execute_result.context */ let result = self - .execute(proposal, pre_state_id, object_map_processor) + .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", - pre_state_id, + prev_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), @@ -830,7 +785,11 @@ mod GroupDecService { && execute_result.context.is_none() && execute_result.receipt.is_none(); - Ok(is_ok) + if is_ok { + Ok(()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "result unmatch")) + } } } @@ -839,31 +798,36 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id, object_map_processor) + self.execute(proposal, prev_state_id, object_map_processor) .await } async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, object_map_processor, execute_result) - .await + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<()> { + self.verify( + proposal, + prev_state_id, + object_map_processor, + execute_result, + ) + .await } async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 @@ -872,16 +836,16 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = match pre_state_id { - Some(pre_state_id) => { + let prev_value = match prev_state_id { + Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&pre_state_id) + .load(*prev_state_id) .await - .expect(format!("load {} failed", pre_state_id).as_str()); + .expect(format!("load {} failed", prev_state_id).as_str()); state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -892,21 +856,21 @@ mod GroupDecService { } None => None, } - .map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + .map_or(0, |prev_state_id| { + let buf = prev_state_id.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let result_value = match execute_result.result_state_id { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&result_state_id) + .load(result_state_id) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -932,7 +896,7 @@ mod GroupDecService { "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, - pre_value, + prev_value, result_value, proposal_id, block.block_id(), @@ -942,10 +906,6 @@ mod GroupDecService { let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); assert!(is_new_finished); } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() - } } } @@ -982,6 +942,7 @@ async fn main_run() { cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) .exit_on_panic(true) + .dingtalk_bug_report("any value to disable") .build() .start(); @@ -1004,9 +965,12 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec = vec![]; + let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; + let mut group_mgrs: Vec = vec![]; + let mut rpc_port = 32217_u16; + let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { - let cyfs_stack = create_stack( + let (cyfs_stack, shared_stack) = create_stack( admin, private_key, device, @@ -1020,33 +984,34 @@ async fn main_run() { .collect(), &group, &dec_app, + rpc_port, + ws_port, ) .await; - admin_stacks.push(cyfs_stack); + admin_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; } async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { - let stack = admin_stacks.get(i).unwrap(); + let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); - DecService::run( - &stack, - admin.name().unwrap().to_string(), - dec_app_id.clone(), - ) - .await; - - let service = stack - .group_mgr() - .find_rpath_service( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, + let local_name = admin.name().unwrap(); + let group_mgr = + DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; + + let service = group_mgr + .start_rpath_service( + group.desc().object_id(), + EXAMPLE_RPATH.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), ) .await .unwrap(); + + group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1057,7 +1022,8 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, @@ -1066,42 +1032,31 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); - let noc = stack.noc_manager().clone(); + let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); let proposal_any = Arc::new(AnyNamedObject::Core( TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), )); - let req = NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: dec_app_id.object_id().clone(), - verified: None, + let req = NONPutObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: None, + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: Some(AccessString::full().value()), + access: Some(AccessString::full()), }; - noc.put_object(&req).await; + noc.put_object(req).await; proposals.push(proposal); } @@ -1112,20 +1067,15 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); async_std::task::spawn(async move { - service.push_proposal(proposal).await.unwrap(); + service.push_proposal(&proposal).await.unwrap(); }); if i % 10 == 0 { @@ -1136,27 +1086,25 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - let client = admin_stacks - .get(0) - .unwrap() - .group_mgr() - .rpath_client( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - ) - .await - .unwrap(); - - let value_obj = client - .get_by_path(EXAMPLE_VALUE_PATH.as_str()) - .await - .unwrap(); - let buf = value_obj.as_ref().unwrap().object_id.data(); - let mut value = [0u8; 8]; - value.copy_from_slice(&buf[..8]); - - log::info!("value from client is: {}", u64::from_be_bytes(value)); + // let client = group_mgrs + // .get(0) + // .unwrap() + // .rpath_client( + // &group.desc().object_id(), + // dec_app_id.object_id(), + // &EXAMPLE_RPATH, + // ) + // .await; + + // let value_obj = client + // .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + // .await + // .unwrap(); + // let buf = value_obj.as_ref().unwrap().object_id.data(); + // let mut value = [0u8; 8]; + // value.copy_from_slice(&buf[..8]); + + // log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From fed43a0a98ade17252c971afd50681db1053d39d Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 472/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/service/ood-daemon/src/config/system_config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index ceb3344e9..670ea5832 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -62,6 +62,13 @@ impl SystemConfig { let node = Self::load_as_toml(&config_file)?; + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) + } + self.parse_config(node).await } @@ -206,4 +213,3 @@ pub async fn reload_system_config() -> BuckyResult { pub fn get_system_config() -> Arc { SYSTEM_CONFIG.lock().unwrap().clone().unwrap() -} \ No newline at end of file From f10fa391e01aa04453fc37f0469a40a9cebc474c Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 473/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/service/ood-daemon/src/config/system_config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 670ea5832..e27890656 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -3,6 +3,7 @@ use super::version::{ServiceListVersion, ServiceVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -64,8 +65,6 @@ impl SystemConfig { self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } From ce96f373eb7091719b905d9d52a6d888d19a7352 Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 474/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 3138 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 2742 insertions(+), 396 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 045ce8e2b..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -141,9 +141,96 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + +[[package]] +name = "app-manager" +version = "0.5.0" +dependencies = [ + "app-manager-lib", + "async-std", + "async-trait", + "bollard", + "chrono", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "flate2", + "fs_extra", + "futures-util", + "log 0.4.17", + "once_cell", + "ood-daemon", + "regex", + "serde", + "serde_json", + "surf", + "tar", + "toml 0.5.11", + "version-compare", + "wait-timeout", + "walkdir", + "which", + "zip-extract", +] + +[[package]] +name = "app-manager-lib" +version = "0.5.0" +dependencies = [ + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", + "serde", + "serde_json", + "toml 0.5.11", +] + +[[package]] +name = "app-tool" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + +[[package]] +name = "app-tool-ex" +version = "0.5.0" +dependencies = [ + "async-std", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] [[package]] name = "arrayref" @@ -196,23 +283,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", @@ -221,6 +308,7 @@ dependencies = [ "blocking", "futures-lite", "once_cell", + "tokio", ] [[package]] @@ -245,27 +333,28 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ + "async-lock", "autocfg 1.1.0", "concurrent-queue", "futures-lite", "libc", "log 0.4.17", - "once_cell", "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -300,9 +389,9 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ "proc-macro2", "quote", @@ -383,6 +472,20 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "async-std-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "pin-utils", + "trust-dns-resolver", +] + [[package]] name = "async-task" version = "4.3.0" @@ -404,9 +507,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.60" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -437,9 +540,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -522,6 +625,31 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +[[package]] +name = "bdt-debuger" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "log 0.4.17", +] + +[[package]] +name = "bdt-debuger-deamon" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", + "md5", +] + [[package]] name = "bincode" version = "1.3.3" @@ -538,6 +666,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f" dependencies = [ "bitcoin_hashes", + "rand 0.6.5", "rand_core 0.4.2", "serde", "unicode-normalization", @@ -620,6 +749,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding 0.2.1", "generic-array 0.14.6", ] @@ -672,14 +802,93 @@ dependencies = [ ] [[package]] -name = "bstr" -version = "0.2.17" +name = "bollard" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" +dependencies = [ + "base64 0.13.1", + "bollard-stubs", + "bytes 1.4.0", + "chrono", + "dirs-next", + "futures-core", + "futures-util", + "hex", + "http", + "hyper 0.14.24", + "hyperlocal", + "log 0.4.17", + "pin-project", + "serde", + "serde_derive", + "serde_json", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util 0.6.10", + "url 2.3.0", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2f2e73fffe9455141e170fb9c1feb0ac521ec7e7dcd47a7cab72a658490fb8" +dependencies = [ + "chrono", + "serde", + "serde_with", +] + +[[package]] +name = "browser-meta-spv" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "hex", + "log 0.4.17", + "once_cell", + "serde", + "serde_json", + "sqlx", + "tide", + "toml 0.5.11", +] + +[[package]] +name = "bson" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "8746d07211bb12a7c34d995539b4a2acd4e0b0e757de98ce2ab99bcf17443fad" dependencies = [ + "ahash", + "base64 0.13.1", + "chrono", + "hex", + "indexmap", "lazy_static", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "time 0.3.19", + "uuid 1.3.0", +] + +[[package]] +name = "bstr" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +dependencies = [ "memchr", - "regex-automata", "serde", ] @@ -691,15 +900,15 @@ checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -707,6 +916,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" + [[package]] name = "byteorder" version = "1.4.3" @@ -725,15 +940,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -770,9 +985,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -795,6 +1010,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "checked_int_cast" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" + [[package]] name = "chrono" version = "0.4.23" @@ -811,6 +1032,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "chunk-manager" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "chrono", + "cyfs-base", + "cyfs-base-meta", + "cyfs-chunk", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "lru_time_cache", + "rand 0.8.5", + "rusqlite", + "serde", + "serde_json", + "tide", + "timer", + "url 2.3.0", +] + [[package]] name = "cipher" version = "0.2.5" @@ -838,7 +1086,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -853,6 +1101,15 @@ dependencies = [ "term", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -863,6 +1120,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colored" version = "2.0.0" @@ -880,15 +1143,21 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "memchr", ] +[[package]] +name = "commandlines" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" + [[package]] name = "concurrent-queue" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ "crossbeam-utils", ] @@ -1153,15 +1422,24 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.6", + "subtle 2.4.1", +] + [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -1196,9 +1474,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -1208,9 +1486,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -1223,15 +1501,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -1240,7 +1518,7 @@ dependencies = [ [[package]] name = "cyfs-base" -version = "0.6.8" +version = "0.6.10" dependencies = [ "aes 0.7.5", "async-recursion", @@ -1275,9 +1553,10 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "simple_logger", + "simple_logger 2.3.0", + "sqlx", "url 2.3.0", - "zip", + "zip 0.6.4", ] [[package]] @@ -1310,7 +1589,7 @@ dependencies = [ [[package]] name = "cyfs-bdt" -version = "0.6.8" +version = "0.7.1" dependencies = [ "async-std", "async-trait", @@ -1325,6 +1604,7 @@ dependencies = [ "generic-array 0.12.4", "hex", "libc", + "local-ip-address", "log 0.4.17", "lru_time_cache", "md5", @@ -1336,12 +1616,59 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "socket2", + "socket2 0.4.7", "winapi", ] [[package]] -name = "cyfs-chunk" +name = "cyfs-bdt-ext" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-cache", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-ndc", + "cyfs-tracker-cache", + "cyfs-util", + "futures", + "log 0.4.17", + "lru_time_cache", + "once_cell", + "serde", +] + +[[package]] +name = "cyfs-bench-mark" +version = "0.1.0" +dependencies = [ + "cyfs-debug", +] + +[[package]] +name = "cyfs-check" +version = "0.5.0" +dependencies = [ + "ansi_term", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "dirs 4.0.0", + "log 0.4.17", + "sysinfo 0.26.9", +] + +[[package]] +name = "cyfs-chunk" version = "0.5.0" dependencies = [ "async-std", @@ -1377,12 +1704,30 @@ dependencies = [ "scan_dir", "sha2 0.8.2", "shared_memory", - "sysinfo 0.26.5", + "sysinfo 0.26.9", +] + +[[package]] +name = "cyfs-chunk-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk", + "cyfs-util", + "http-types", + "log 0.4.17", + "serde", + "serde_json", + "time 0.1.45", + "url 2.3.0", ] [[package]] name = "cyfs-chunk-lib" -version = "0.6.3" +version = "0.6.4" dependencies = [ "async-std", "async-trait", @@ -1405,16 +1750,60 @@ dependencies = [ "hmac 0.12.1", "log 0.4.17", "memzero", - "pbkdf2", + "pbkdf2 0.11.0", "rand 0.7.3", "rand_chacha 0.2.2", "rand_core 0.5.1", "sha2 0.10.6", ] +[[package]] +name = "cyfs-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-recursion", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-bdt", + "cyfs-chunk", + "cyfs-chunk-client", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "hex", + "http-types", + "log 0.4.17", + "once_cell", + "rand 0.7.3", + "serde_json", + "url 2.3.0", + "walkdir", +] + +[[package]] +name = "cyfs-container" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "log 0.4.17", +] + [[package]] name = "cyfs-core" -version = "0.6.3" +version = "0.6.6" dependencies = [ "async-std", "async-trait", @@ -1433,6 +1822,7 @@ dependencies = [ "protoc-bin-vendored", "protoc-rust", "rand 0.8.5", + "semver 1.0.16", "serde", "serde_json", "sha2 0.8.2", @@ -1440,7 +1830,7 @@ dependencies = [ [[package]] name = "cyfs-debug" -version = "0.6.2" +version = "0.6.4" dependencies = [ "async-h1", "async-std", @@ -1454,7 +1844,7 @@ dependencies = [ "futures", "hex", "http-types", - "hyper", + "hyper 0.10.16", "lazy_static", "libc", "log 0.4.17", @@ -1468,7 +1858,7 @@ dependencies = [ "surf", "tide", "timer", - "toml", + "toml 0.5.11", "url 2.3.0", "winapi", ] @@ -1498,12 +1888,43 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", "cyfs-lib", + "cyfs-util", "futures", + "http-types", + "itertools", "lazy_static", "log 0.4.17", - "prost 0.11.5", - "prost-build 0.11.5", + "prost 0.11.6", + "prost-build 0.9.0", "protobuf", "protoc-bin-vendored", "protoc-rust", @@ -1515,13 +1936,13 @@ dependencies = [ [[package]] name = "cyfs-lib" -version = "0.7.0" +version = "0.8.1" dependencies = [ "async-h1", "async-std", "async-trait", "async-tungstenite", - "bytes 1.3.0", + "bytes 1.4.0", "chrono", "cyfs-base", "cyfs-bdt", @@ -1544,12 +1965,79 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "surf", "tide", ] +[[package]] +name = "cyfs-meta" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "base58", + "base64 0.13.1", + "byteorder", + "chrono", + "cyfs-base", + "cyfs-base-meta", + "cyfs-core", + "cyfs-util", + "evm", + "futures", + "generic-array 0.12.4", + "hex", + "http-types", + "lazy_static", + "libsqlite3-sys", + "log 0.4.17", + "primitive-types", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", + "sqlx", + "tide", + "timer", +] + +[[package]] +name = "cyfs-meta-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-recursion", + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "dirs 4.0.0", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "rand 0.7.3", + "serde_json", + "simple_logger 2.3.0", +] + +[[package]] +name = "cyfs-meta-genesis" +version = "0.5.0" +dependencies = [ + "commandlines", + "cyfs-meta", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + [[package]] name = "cyfs-meta-lib" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -1557,12 +2045,53 @@ dependencies = [ "hex", "http-types", "log 0.4.17", + "lru_time_cache", "primitive-types", "rand 0.7.3", "serde_json", "surf", ] +[[package]] +name = "cyfs-meta-miner" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-debug", + "cyfs-meta", + "cyfs-meta-lib", + "hex", + "lazy_static", + "log 0.4.17", + "serde", + "serde_json", + "tide", +] + +[[package]] +name = "cyfs-meta-spv" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "base58", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "ethabi", + "hex", + "libsqlite3-sys", + "log 0.4.17", + "serde", + "serde_json", + "sqlx", + "tide", +] + [[package]] name = "cyfs-mobile-stack" version = "0.5.0" @@ -1581,6 +2110,32 @@ dependencies = [ "once_cell", ] +[[package]] +name = "cyfs-monitor" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "futures", + "log 0.4.17", + "once_cell", + "rand 0.7.3", + "serde", + "serde_json", + "surf", + "toml 0.5.11", + "url 2.3.0", +] + [[package]] name = "cyfs-ndc" version = "0.5.0" @@ -1593,7 +2148,6 @@ dependencies = [ "cyfs-util", "log 0.4.17", "rusqlite", - "thread_local", ] [[package]] @@ -1602,6 +2156,7 @@ version = "0.5.0" dependencies = [ "async-std", "async-trait", + "base-x", "cyfs-base", "cyfs-core", "cyfs-debug", @@ -1613,12 +2168,11 @@ dependencies = [ "lru_time_cache", "once_cell", "rusqlite", - "thread_local", ] [[package]] name = "cyfs-perf-base" -version = "0.6.0" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -1626,6 +2180,7 @@ dependencies = [ "cyfs-lib", "cyfs-util", "int-enum", + "lazy_static", "log 0.4.17", "protobuf", "protoc-bin-vendored", @@ -1636,11 +2191,12 @@ dependencies = [ [[package]] name = "cyfs-perf-client" -version = "0.6.1" +version = "0.6.2" dependencies = [ "android_logger", "async-std", "async-trait", + "chrono", "cyfs-base", "cyfs-core", "cyfs-debug", @@ -1665,7 +2221,41 @@ dependencies = [ "pyo3", "rand 0.7.3", "serde", - "threadpool", + "threadpool", +] + +[[package]] +name = "cyfs-runtime" +version = "0.5.0" +dependencies = [ + "android_logger", + "async-h1", + "async-std", + "async-trait", + "bytes 1.4.0", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "dirs 4.0.0", + "formdata", + "futures", + "http-types", + "hyper 0.10.16", + "jni", + "log 0.4.17", + "mime-sniffer", + "once_cell", + "ood-control", + "rand 0.7.3", + "serde", + "serde_json", + "tide", + "toml 0.5.11", + "url 2.3.0", ] [[package]] @@ -1675,7 +2265,7 @@ dependencies = [ "block-buffer 0.7.3", "digest 0.8.1", "fake-simd", - "hex-literal", + "hex-literal 0.1.4", "libc", "opaque-debug 0.2.3", "sha2-asm", @@ -1698,10 +2288,12 @@ dependencies = [ "cyfs-core", "cyfs-debug", "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", "cyfs-noc", + "cyfs-perf-client", "cyfs-task-manager", "cyfs-tracker-cache", "cyfs-util", @@ -1715,8 +2307,8 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.5", - "prost-build 0.11.5", + "prost 0.11.6", + "prost-build 0.11.6", "protoc-bin-vendored", "rand 0.8.5", "semver 1.0.16", @@ -1725,8 +2317,31 @@ dependencies = [ "sha2 0.8.2", "sqlx", "tide", - "toml", - "zip", + "toml 0.5.11", + "zip 0.6.4", +] + +[[package]] +name = "cyfs-stack-bench" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "hex", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "serde", + "toml 0.5.11", ] [[package]] @@ -1748,13 +2363,42 @@ dependencies = [ "log 0.4.17", "regex", "serde", - "toml", - "toml_edit", + "toml 0.5.11", + "toml_edit 0.15.0", +] + +[[package]] +name = "cyfs-stack-test" +version = "0.5.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-noc", + "cyfs-perf-client", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "log 0.4.17", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "zone-simulator", ] [[package]] name = "cyfs-task-manager" -version = "0.6.1" +version = "0.6.3" dependencies = [ "async-std", "async-trait", @@ -1783,7 +2427,7 @@ dependencies = [ [[package]] name = "cyfs-util" -version = "0.6.4" +version = "0.6.6" dependencies = [ "async-h1", "async-std", @@ -1811,13 +2455,49 @@ dependencies = [ "rusqlite", "serde", "serde_json", - "simple_logger", - "sysinfo", - "toml", + "simple_logger 2.3.0", + "sysinfo 0.27.7", + "thread_local", + "toml 0.5.11", "url 2.3.0", "walkdir", "winapi", - "zip", + "zip 0.6.4", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", ] [[package]] @@ -1830,9 +2510,15 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.7", ] +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + [[package]] name = "deadpool" version = "0.7.0" @@ -1858,6 +2544,44 @@ dependencies = [ "pem-rfc7468", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "desc-tool" +version = "0.5.0" +dependencies = [ + "async-std", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "hex", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + [[package]] name = "digest" version = "0.8.1" @@ -1908,6 +2632,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -1919,6 +2653,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users 0.4.3", + "winapi", +] + [[package]] name = "discard" version = "1.0.4" @@ -1933,9 +2678,25 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "email-encoding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34dd14c63662e0206599796cd5e1ad0268ab2b9d19b868d6050d688eba2bbf98" +dependencies = [ + "base64 0.13.1", + "memchr", +] + +[[package]] +name = "email_address" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" [[package]] name = "encoding" @@ -2001,6 +2762,18 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +[[package]] +name = "enum-as-inner" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -2020,12 +2793,133 @@ dependencies = [ "serde", ] +[[package]] +name = "ethabi" +version = "14.0.0" +dependencies = [ + "anyhow", + "cyfs-base", + "ethereum-types", + "evm", + "hex", + "hex-literal 0.3.4", + "itertools", + "paste 1.0.11", + "rustc-hex", + "serde", + "serde_json", + "sha3 0.9.1", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9" +dependencies = [ + "ethereum-types", + "funty", + "hash-db", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "rlp-derive", + "serde", + "sha3 0.9.1", + "triehash", +] + +[[package]] +name = "ethereum-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "evm" +version = "0.26.0" +dependencies = [ + "criterion", + "cyfs-base", + "cyfs-base-meta", + "ethereum", + "evm-core", + "evm-gasometer", + "evm-runtime", + "hex", + "log 0.4.17", + "parity-scale-codec", + "primitive-types", + "rlp", + "rlp-derive", + "serde", + "sha3 0.8.2", +] + +[[package]] +name = "evm-core" +version = "0.26.0" +dependencies = [ + "cyfs-base-meta", + "funty", + "hex", + "parity-scale-codec", + "primitive-types", + "serde", +] + +[[package]] +name = "evm-gasometer" +version = "0.26.0" +dependencies = [ + "cyfs-base", + "evm-core", + "evm-runtime", + "primitive-types", +] + +[[package]] +name = "evm-runtime" +version = "0.26.0" +dependencies = [ + "cyfs-base", + "evm-core", + "primitive-types", + "sha3 0.8.2", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -2046,9 +2940,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -2060,13 +2954,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc04871e5ae3aa2952d552dae6b291b3099723bf779a8054281c1366a54613ef" dependencies = [ "cfg-if 1.0.0", - "js-sys", - "log 0.4.17", - "serde", - "serde_derive", - "serde_json", - "wasm-bindgen", - "web-sys", + "js-sys", + "log 0.4.17", + "serde", + "serde_derive", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "file-manager" +version = "0.5.0" +dependencies = [ + "async-std", + "cyfs-base", + "cyfs-debug", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "rusqlite", + "tide", +] + +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.16", + "windows-sys 0.45.0", ] [[package]] @@ -2123,7 +3043,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.4", + "spin 0.9.5", ] [[package]] @@ -2164,7 +3084,7 @@ checksum = "6b2e172b694029467db935166c398f911adce5373d63bb1149740cd9182a3eee" dependencies = [ "encoding", "httparse", - "hyper", + "hyper 0.10.16", "log 0.4.17", "mime 0.2.6", "mime_multipart", @@ -2181,6 +3101,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -2195,9 +3130,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -2210,9 +3145,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -2220,15 +3155,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -2238,20 +3173,20 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.12.1", + "parking_lot 0.11.2", ] [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -2270,9 +3205,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -2281,21 +3216,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -2309,6 +3244,39 @@ dependencies = [ "slab", ] +[[package]] +name = "gateway" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "bytes 1.4.0", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "lru_time_cache", + "once_cell", + "regex", + "serde", + "serde_json", + "tide", + "toml 0.5.11", + "url 2.3.0", + "wildmatch", + "winapi", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -2374,21 +3342,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -2399,9 +3367,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c4a8d6391675c6b2ee1a6c8d06e8e2d03605c44cec1270675985a4c2a5500b" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", @@ -2418,17 +3386,19 @@ dependencies = [ "async-trait", "cyfs-base", "cyfs-bdt", + "cyfs-bdt-ext", "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", - "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-stack", + "cyfs-util", "futures", "lazy_static", "log 0.4.17", - "prost 0.11.5", + "prost 0.11.6", "protobuf", "rand 0.8.5", "serde", @@ -2436,6 +3406,25 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "h2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +dependencies = [ + "bytes 1.4.0", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util 0.7.7", + "tracing", +] + [[package]] name = "half" version = "1.8.2" @@ -2448,6 +3437,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -2483,9 +3487,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -2524,6 +3528,12 @@ dependencies = [ "proc-macro-hack 0.4.3", ] +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hex-literal-impl" version = "0.1.2" @@ -2583,6 +3593,16 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2603,15 +3623,37 @@ dependencies = [ "hmac 0.7.1", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "fnv", - "itoa 1.0.5", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes 1.4.0", + "http", + "pin-project-lite 0.2.9", ] [[package]] @@ -2667,6 +3709,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + [[package]] name = "hyper" version = "0.10.16" @@ -2686,11 +3734,48 @@ dependencies = [ "url 1.7.2", ] +[[package]] +name = "hyper" +version = "0.14.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +dependencies = [ + "bytes 1.4.0", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite 0.2.9", + "socket2 0.4.7", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyperlocal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +dependencies = [ + "futures-util", + "hex", + "hyper 0.14.24", + "pin-project", + "tokio", +] + [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2710,6 +3795,12 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.1.5" @@ -2732,6 +3823,20 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "impl-codec" version = "0.5.1" @@ -2741,6 +3846,24 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -2791,6 +3914,26 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -2860,6 +4003,24 @@ dependencies = [ "libc", ] +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2 0.3.19", + "widestring 0.4.3", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + [[package]] name = "itertools" version = "0.10.5" @@ -2869,12 +4030,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.5" @@ -2912,13 +4067,42 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2943,6 +4127,28 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lettre" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eabca5e0b4d0e98e7f2243fb5b7520b6af2b65d8f87bcc86f2c75185a6ff243" +dependencies = [ + "base64 0.13.1", + "email-encoding", + "email_address", + "fastrand", + "futures-util", + "hostname", + "httpdate", + "idna 0.2.1", + "mime 0.3.16", + "native-tls", + "nom 7.1.3", + "once_cell", + "quoted_printable", + "socket2 0.4.7", +] + [[package]] name = "lexical-core" version = "0.7.6" @@ -2964,9 +4170,9 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libsecp256k1" @@ -3004,6 +4210,24 @@ dependencies = [ "cc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "local-ip-address" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa9d02443a1741e9f51dafdfcbffb3863b2a89c457d762b40337d6c5153ef81" +dependencies = [ + "libc", + "neli", + "thiserror", + "windows-sys 0.42.0", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -3040,8 +4264,17 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f9dd8546191c1850ecf67d22f5ff00a935b890d0e84713159a55495cc2ac5f" dependencies = [ - "backtrace", - "log 0.4.17", + "backtrace", + "log 0.4.17", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", ] [[package]] @@ -3050,11 +4283,27 @@ version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd" +[[package]] +name = "mac_address" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" +dependencies = [ + "nix 0.23.2", + "winapi", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "maybe-uninit" @@ -3062,6 +4311,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "md5" version = "0.7.0" @@ -3076,9 +4336,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" dependencies = [ "libc", ] @@ -3107,6 +4367,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93c0d11ac30a033511ae414355d80f70d9f29a44a49140face477117a1ee90db" +[[package]] +name = "meta-stat" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-meta", + "log 0.4.17", + "misc-util", + "serde", + "serde_json", + "simple_logger 3.0.0", +] + [[package]] name = "mime" version = "0.2.6" @@ -3122,6 +4399,15 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime-sniffer" +version = "0.1.2" +source = "git+https://github.com/buckyos/rust-mime-sniffer?rev=99c00bba5091810514741bfe0f05d8c9ca244796#99c00bba5091810514741bfe0f05d8c9ca244796" +dependencies = [ + "mime 0.3.16", + "url 1.7.2", +] + [[package]] name = "mime_guess" version = "2.0.4" @@ -3141,7 +4427,7 @@ dependencies = [ "buf-read-ext", "encoding", "httparse", - "hyper", + "hyper 0.10.16", "log 0.4.17", "mime 0.2.6", "tempdir", @@ -3158,12 +4444,80 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "miniz_oxide" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.45.0", +] + +[[package]] +name = "misc-util" +version = "0.1.0" +dependencies = [ + "cyfs-base", + "lettre", + "log 0.4.17", + "serde", +] + +[[package]] +name = "mongodb" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bacb6f8cee6bf010d7bc57550d859f6a4ffe255eb8c9a7014637fe988eaece64" +dependencies = [ + "async-std", + "async-std-resolver", + "async-trait", + "base64 0.13.1", + "bitflags", + "bson", + "chrono", + "derivative", + "futures-core", + "futures-executor", + "futures-io", + "futures-util", + "hex", + "hmac 0.11.0", + "lazy_static", + "md-5", + "os_info", + "pbkdf2 0.8.0", + "percent-encoding 2.2.0", + "rand 0.8.5", + "rustls 0.19.1", + "rustls-pemfile", + "serde", + "serde_with", + "sha-1 0.9.8", + "sha2 0.9.9", + "socket2 0.4.7", + "stringprep", + "strsim 0.10.0", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util 0.6.10", + "trust-dns-proto", + "trust-dns-resolver", + "typed-builder", + "uuid 0.8.2", + "version_check 0.9.4", + "webpki", + "webpki-roots 0.21.1", ] [[package]] @@ -3182,15 +4536,15 @@ dependencies = [ "once_cell", "parking_lot 0.12.1", "thiserror", - "widestring", + "widestring 0.5.1", "winapi", ] [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -3204,6 +4558,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "neli" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9053554eb5dcb7e10d9cdab1206965bde870eed5d0d341532ca035e3ba221508" +dependencies = [ + "byteorder", + "libc", +] + [[package]] name = "nix" version = "0.23.2" @@ -3242,14 +4606,41 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "notify" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.42.0", +] + [[package]] name = "ntapi" version = "0.4.0" @@ -3338,6 +4729,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -3369,18 +4771,107 @@ dependencies = [ [[package]] name = "object" -version = "0.30.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "ood-control" +version = "0.5.1" +dependencies = [ + "android_logger", + "async-h1", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "hex", + "http-types", + "jni", + "lazy_static", + "log 0.4.17", + "mac_address", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sysinfo 0.26.9", + "tide", +] + +[[package]] +name = "ood-daemon" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "fs_extra", + "futures", + "futures-util", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "notify", + "once_cell", + "ood-control", + "rand 0.7.3", + "semver 1.0.16", + "serde", + "serde_json", + "tide", + "toml 0.5.11", + "zip 0.6.4", +] + +[[package]] +name = "ood-installer" +version = "0.5.0" +dependencies = [ + "app-manager", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "desc-tool", + "futures-util", + "hex", + "log 0.4.17", + "mac_address", + "ood-control", + "ood-daemon", + "os_type", + "qrcode", + "rust-embed", +] [[package]] name = "oorandom" @@ -3445,6 +4936,38 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_info" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c424bc68d15e0778838ac013b5b3449544d8133633d8016319e7e05a820b8c0" +dependencies = [ + "log 0.4.17", + "winapi", +] + +[[package]] +name = "os_type" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24d44c0eea30167516ed8f6daca4b5e3eebcde1bde1e4e6e08b809fb02c7ba5" +dependencies = [ + "regex", +] + +[[package]] +name = "pack-tools" +version = "0.5.0" +dependencies = [ + "clap", + "cyfs-base", + "log 0.4.17", + "sha2 0.8.2", + "simple_logger 2.3.0", + "walkdir", + "zip 0.6.4", +] + [[package]] name = "parity-scale-codec" version = "2.3.1" @@ -3465,7 +4988,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -3495,7 +5018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.7", ] [[package]] @@ -3514,15 +5037,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec 1.10.0", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -3561,6 +5084,15 @@ dependencies = [ "proc-macro-hack 0.5.20+deprecated", ] +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -3605,11 +5137,32 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "perf-service" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-perf-base", + "cyfs-util", + "log 0.4.17", + "mongodb", + "serde", + "serde_json", + "toml 0.7.2", +] + [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -3677,9 +5230,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -3709,6 +5262,25 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pn-miner" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "libc", + "log 0.4.17", + "rusqlite", + "serde", + "serde_json", + "tide", +] + [[package]] name = "polling" version = "2.5.2" @@ -3736,15 +5308,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ "proc-macro2", "syn", @@ -3752,9 +5324,9 @@ dependencies = [ [[package]] name = "primal" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389bfb36ac527b5fe21a57f87bc7956af45cbeb2de7750b90b7ebac6770e715e" +checksum = "4b53cc99c892c461727618e8a63806c94b09ae13c494dc5fc70a7557b3a2f071" dependencies = [ "primal-check", "primal-estimate", @@ -3787,9 +5359,9 @@ checksum = "7374f14c76f23e1271e6be806981ac5dd9e52b59132b0a2f10bcc412495f9159" [[package]] name = "primal-sieve" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fee6031f66b44e8e004ac9bf81fd1c5abcbbb25bd392bc27429daa1759654a" +checksum = "9f2a14766f8c543620824b5b2cec356abf2681b76966a7ac4b4ed2c0011e696a" dependencies = [ "primal-bit", "primal-estimate", @@ -3804,6 +5376,8 @@ checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", "uint", ] @@ -3813,18 +5387,17 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit 0.18.1", ] [[package]] @@ -3850,9 +5423,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -3863,18 +5436,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ - "bytes 1.3.0", - "prost-derive 0.11.5", + "bytes 1.4.0", + "prost-derive 0.11.6", ] [[package]] @@ -3883,7 +5456,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "heck 0.3.3", "itertools", "lazy_static", @@ -3899,20 +5472,20 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ - "bytes 1.3.0", - "heck 0.4.0", + "bytes 1.4.0", + "heck 0.4.1", "itertools", "lazy_static", "log 0.4.17", "multimap", "petgraph", "prettyplease", - "prost 0.11.5", - "prost-types 0.11.5", + "prost 0.11.6", + "prost-types 0.11.6", "regex", "syn", "tempfile", @@ -3934,9 +5507,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -3951,18 +5524,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ - "bytes 1.3.0", - "prost 0.11.5", + "bytes 1.4.0", + "prost 0.11.6", ] [[package]] @@ -3971,7 +5544,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", ] [[package]] @@ -4093,6 +5666,16 @@ dependencies = [ "syn", ] +[[package]] +name = "qrcode" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" +dependencies = [ + "checked_int_cast", + "image", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4110,9 +5693,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f14e071918cbeefc5edc986a7aa92c425dae244e003a35e1cdddb5ca39b5cb" +checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" [[package]] name = "radium" @@ -4133,6 +5716,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -4143,7 +5745,7 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc", + "rand_hc 0.2.0", ] [[package]] @@ -4157,6 +5759,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -4210,6 +5822,15 @@ dependencies = [ "getrandom 0.2.8", ] +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -4219,6 +5840,59 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rayon" version = "1.6.1" @@ -4231,9 +5905,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -4289,26 +5963,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -4319,6 +5987,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.16.20" @@ -4343,6 +6021,27 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes 1.4.0", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "route-recognizer" version = "0.2.0" @@ -4411,6 +6110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a" dependencies = [ "bitflags", + "chrono", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -4431,6 +6131,40 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rust-embed" +version = "6.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" +dependencies = [ + "sha2 0.10.6", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -4478,6 +6212,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "rustversion" version = "1.0.11" @@ -4505,6 +6248,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +dependencies = [ + "cfg-if 1.0.0", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +dependencies = [ + "proc-macro-crate 1.3.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "scan_dir" version = "0.3.3" @@ -4516,12 +6283,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -4548,9 +6314,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.7.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -4561,9 +6327,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -4599,6 +6365,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.2" @@ -4631,11 +6406,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.5", + "indexmap", + "itoa", "ryu", "serde", ] @@ -4651,6 +6427,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4658,11 +6443,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.5", + "itoa", "ryu", "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -4745,6 +6565,31 @@ dependencies = [ "cc", ] +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +dependencies = [ + "block-buffer 0.7.3", + "byte-tools", + "digest 0.8.1", + "keccak", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", +] + [[package]] name = "shared_memory" version = "0.12.4" @@ -4761,9 +6606,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -4771,9 +6616,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -4788,34 +6633,60 @@ dependencies = [ ] [[package]] -name = "simple_asn1" -version = "0.4.1" +name = "simple_asn1" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" +dependencies = [ + "chrono", + "num-bigint 0.2.6", + "num-traits", +] + +[[package]] +name = "simple_logger" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48047e77b528151aaf841a10a9025f9459da80ba820e425ff7eb005708a76dc7" +dependencies = [ + "atty", + "colored", + "log 0.4.17", + "time 0.3.19", + "winapi", +] + +[[package]] +name = "simple_logger" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" +checksum = "cc20708d703a44b96b3b700578a85b6fe887fc63ab20315757026bb8a12faaad" dependencies = [ - "chrono", - "num-bigint 0.2.6", - "num-traits", + "atty", + "colored", + "log 0.4.17", + "time 0.3.19", + "winapi", ] [[package]] name = "simple_logger" -version = "2.3.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48047e77b528151aaf841a10a9025f9459da80ba820e425ff7eb005708a76dc7" +checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", - "winapi", + "time 0.3.19", + "windows-sys 0.42.0", ] [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg 1.1.0", ] @@ -4835,6 +6706,58 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "sn-miner-rust" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", +] + +[[package]] +name = "sn-online-test" +version = "0.1.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-util", + "log 0.4.17", + "rand 0.7.3", + "simple_logger 4.0.0", +] + +[[package]] +name = "sn-updater" +version = "0.1.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "log 0.4.17", + "simple_logger 4.0.0", +] + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -4853,9 +6776,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" dependencies = [ "lock_api", ] @@ -4877,7 +6800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom 7.1.1", + "nom 7.1.3", "unicode_categories", ] @@ -4901,7 +6824,8 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.3.0", + "bytes 1.4.0", + "chrono", "crc", "crossbeam-queue", "digest 0.10.6", @@ -4917,7 +6841,7 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.5", + "itoa", "libc", "libsqlite3-sys", "log 0.4.17", @@ -4929,7 +6853,7 @@ dependencies = [ "rand 0.8.5", "rsa 0.6.1", "rustls 0.19.1", - "sha-1", + "sha-1 0.10.1", "sha2 0.10.6", "smallvec 1.10.0", "sqlformat", @@ -4949,7 +6873,7 @@ checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.4.0", + "heck 0.4.1", "once_cell", "proc-macro2", "quote", @@ -5052,6 +6976,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "1.0.0" @@ -5120,9 +7050,24 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.8" +version = "0.26.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" +dependencies = [ + "cfg-if 1.0.0", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + +[[package]] +name = "sysinfo" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6" +checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -5133,12 +7078,29 @@ dependencies = [ "winapi", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -5176,9 +7138,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -5224,10 +7186,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -5291,101 +7254,333 @@ dependencies = [ [[package]] name = "time" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ - "itoa 1.0.5", + "itoa", "libc", "num_threads", "serde", "time-core", - "time-macros 0.2.5", + "time-macros 0.2.7", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack 0.5.20+deprecated", + "time-macros-impl", +] + +[[package]] +name = "time-macros" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" +dependencies = [ + "time-core", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack 0.5.20+deprecated", + "proc-macro2", + "quote", + "standback", + "syn", +] + +[[package]] +name = "timer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" +dependencies = [ + "chrono", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +dependencies = [ + "autocfg 1.1.0", + "bytes 1.4.0", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite 0.2.9", + "socket2 0.4.7", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes 1.4.0", + "futures-core", + "futures-io", + "futures-sink", + "log 0.4.17", + "pin-project-lite 0.2.9", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes 1.4.0", + "futures-core", + "futures-sink", + "pin-project-lite 0.2.9", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "indexmap", + "serde", +] + +[[package]] +name = "toml" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "toml_edit 0.19.4", +] + +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646" +dependencies = [ + "combine", + "indexmap", + "itertools", + "toml_datetime 0.5.1", ] [[package]] -name = "time-core" -version = "0.1.0" +name = "toml_edit" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime 0.5.1", +] [[package]] -name = "time-macros" -version = "0.1.1" +name = "toml_edit" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", - "time-macros-impl", + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "winnow", ] [[package]] -name = "time-macros" -version = "0.2.5" +name = "tower-service" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" -dependencies = [ - "time-core", -] +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] -name = "time-macros-impl" -version = "0.1.2" +name = "tracing" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", - "proc-macro2", - "quote", - "standback", - "syn", + "cfg-if 1.0.0", + "pin-project-lite 0.2.9", + "tracing-core", ] [[package]] -name = "timer" -version = "0.2.0" +name = "tracing-core" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "chrono", + "once_cell", ] [[package]] -name = "tinytemplate" -version = "1.2.1" +name = "traitobject" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" dependencies = [ - "serde", - "serde_json", + "hash-db", + "rlp", ] [[package]] -name = "tokio" -version = "1.23.0" +name = "trust-dns-proto" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" dependencies = [ - "autocfg 1.1.0", - "pin-project-lite 0.2.9", - "windows-sys 0.42.0", + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.1", + "ipnet", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "smallvec 1.10.0", + "thiserror", + "tinyvec", + "tokio", + "url 2.3.0", ] [[package]] -name = "toml" -version = "0.5.10" +name = "trust-dns-resolver" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" dependencies = [ - "indexmap", - "serde", + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lazy_static", + "log 0.4.17", + "lru-cache", + "parking_lot 0.11.2", + "resolv-conf", + "smallvec 1.10.0", + "thiserror", + "tokio", + "trust-dns-proto", ] [[package]] -name = "traitobject" -version = "0.1.0" +name = "try-lock" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" @@ -5395,12 +7590,12 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.3.0", + "bytes 1.4.0", "http", "httparse", "log 0.4.17", "rand 0.8.5", - "sha-1", + "sha-1 0.10.1", "thiserror", "url 2.3.0", "utf-8", @@ -5412,6 +7607,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +[[package]] +name = "typed-builder" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46ee5bd706ff79131be9c94e7edcb82b703c487766a114434e5790361cf08c5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.16.0" @@ -5450,9 +7656,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" @@ -5471,9 +7677,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -5544,6 +7750,25 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "uuid" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +dependencies = [ + "getrandom 0.2.8", + "serde", +] + [[package]] name = "value-bag" version = "1.0.0-alpha.9" @@ -5570,6 +7795,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + [[package]] name = "version_check" version = "0.1.5" @@ -5582,6 +7813,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.0" @@ -5599,6 +7839,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log 0.4.17", + "try-lock", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -5619,9 +7869,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "serde", @@ -5631,9 +7881,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log 0.4.17", @@ -5646,9 +7896,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5658,9 +7908,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5668,9 +7918,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -5681,15 +7931,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -5734,21 +7984,33 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", "once_cell", ] +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "widestring" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +[[package]] +name = "wildmatch" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" + [[package]] name = "win-sys" version = "0.3.1" @@ -5804,37 +8066,48 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" @@ -5844,15 +8117,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" @@ -5862,15 +8129,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" @@ -5880,15 +8141,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" @@ -5898,21 +8153,15 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" @@ -5922,15 +8171,27 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" +name = "winnow" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] [[package]] name = "wyz" @@ -5938,6 +8199,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] + [[package]] name = "zeroize" version = "1.5.7" @@ -5961,9 +8231,23 @@ dependencies = [ [[package]] name = "zip" -version = "0.6.3" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "flate2", + "thiserror", + "time 0.1.45", +] + +[[package]] +name = "zip" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" dependencies = [ "aes 0.7.5", "byteorder", @@ -5973,12 +8257,73 @@ dependencies = [ "crossbeam-utils", "flate2", "hmac 0.12.1", - "pbkdf2", + "pbkdf2 0.11.0", "sha1 0.10.5", - "time 0.3.16", + "time 0.3.19", "zstd", ] +[[package]] +name = "zip-extract" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c5cc0309f6e81ab96c2b43d5e935025f8732c886690be8f78f68e06bad1d274" +dependencies = [ + "log 0.4.17", + "thiserror", + "zip 0.5.13", +] + +[[package]] +name = "zone-simulator" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "bip39", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "lazy_static", + "log 0.4.17", + "once_cell", + "rand 0.7.3", +] + +[[package]] +name = "zone-stack" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "bip39", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "log 0.4.17", + "rand 0.8.5", + "serde", + "serde_json", + "toml 0.5.11", + "zone-simulator", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" @@ -6000,10 +8345,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.4+zstd.1.5.2" +version = "2.0.7+zstd.1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" +checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" dependencies = [ "cc", "libc", + "pkg-config", ] From 19d2ec2fc6f8e5f9d926d1f55d2806a0cc9b5715 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 475/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From 065faf6dafb81f2cc52818b76d4f4e68fd6a9e73 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 14:48:12 +0800 Subject: [PATCH 476/553] Adapte to the buckyos --- .../engine/storage_engine_group_state.rs | 44 ++++++++++++++++--- .../cyfs-group/src/storage/group_storage.rs | 9 +++- src/meta/cyfs-meta/src/executor/view.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 029b09e78..cf04e93ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -19,6 +19,8 @@ const ACCESS: Option = None; #[derive(Clone)] pub struct StorageEngineGroupState { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, state_path: Arc, } @@ -183,18 +185,28 @@ impl StorageEngineGroupState { Ok(cache) } - pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + pub fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: GroupStatePath, + group_id: ObjectId, + dec_id: ObjectId, + ) -> Self { Self { state_mgr, state_path: Arc::new(state_path), + group_id, + dec_id, } } pub async fn create_writer(&self) -> BuckyResult { - Ok( - StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) - .await?, + Ok(StorageEngineGroupStateWriter::new( + self.state_mgr.clone(), + self.state_path.clone(), + self.group_id, + self.dec_id, ) + .await?) } pub fn root_cache(&self) -> &ObjectMapRootCacheRef { @@ -218,6 +230,8 @@ impl StorageEngine for StorageEngineGroupState { #[derive(Clone)] pub struct StorageEngineGroupStateWriter { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, op_env: ObjectMapPathOpEnvRef, prepare_op_env: ObjectMapSingleOpEnvRef, @@ -230,6 +244,8 @@ impl StorageEngineGroupStateWriter { async fn new( state_mgr: ObjectMapRootManagerRef, state_path: Arc, + group_id: ObjectId, + dec_id: ObjectId, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; @@ -237,7 +253,11 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(group_id), + Some(dec_id), + ) .await?; None } else { @@ -254,6 +274,8 @@ impl StorageEngineGroupStateWriter { state_mgr, prepare_map_id, write_result: Ok(()), + group_id, + dec_id, }) } @@ -264,7 +286,11 @@ impl StorageEngineGroupStateWriter { ) -> BuckyResult { let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; single_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(self.group_id), + Some(self.dec_id), + ) .await?; single_op_env .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) @@ -463,7 +489,11 @@ impl StorageEngineGroupStateWriter { } add_single_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new( + ObjectMapSimpleContentType::Set, + Some(self.group_id), + Some(self.dec_id), + ) .await?; } else { add_single_op_env diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a762c1b6..78af14c4b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -81,6 +81,8 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), + group_id.clone(), + dec_id.clone(), ), local_device_id, cache: StorageCacheInfo::new(None), @@ -138,7 +140,12 @@ impl GroupStorage { rpath: rpath.to_string(), non_driver, group_chunk_id: group_chunk_id.object_id(), - storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + state_path, + group_id.clone(), + dec_id.clone(), + ), local_device_id, cache, object_map_processor, diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 7d76e9fcc..47e3c8a7d 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -5,7 +5,7 @@ use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; use crate::stat::Stat; use crate::state_storage::{StateRef, StateWeakRef}; -use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base::{BuckyResult, RawConvertTo, ObjectId}; use cyfs_base_meta::*; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; From 709456b1f18668932a61f26aabefb857fdd28a43 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 18:53:20 +0800 Subject: [PATCH 477/553] Adapt interface of RootState, add param(owner) --- src/tests/group-example/src/main.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 361bfd35a..01d57996b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -547,8 +547,8 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, SharedCyfsStack, + CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, + RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -677,7 +677,12 @@ mod GroupDecService { } None => { state_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new_with_option( + ObjectMapSimpleContentType::Map, + &CreateObjectMapOption::new_with_owner( + proposal.rpath().group_id().clone(), + ), + ) .await .expect( format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), From e9d5480498af47394b9ca4380dd11e4ac6bdd5a4 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 15:13:47 +0800 Subject: [PATCH 478/553] Testcase for client --- .../cyfs-core/src/group/group_proposal.rs | 1 - .../cyfs-group/src/dec/rpath_service.rs | 20 +- src/tests/group-example/src/main.rs | 231 ++++++++++++------ 3 files changed, 175 insertions(+), 77 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 508418f7b..e011afdf7 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,7 +1,6 @@ use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; -use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index 1f2e836a1..47bd1ffd7 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,8 +1,12 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{ + AnyNamedObject, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + RsaCPUObjectSigner, TypelessCoreObject, +}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; +use cyfs_lib::NONObjectInfo; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, @@ -15,6 +19,7 @@ struct RPathServiceRaw { network_sender: crate::network::Sender, pending_proposal_handle: PendingProposalHandler, hotstuff: Hotstuff, + non_driver: NONDriverHelper, } #[derive(Clone)] @@ -44,7 +49,7 @@ impl RPathService { store, signer, network_sender.clone(), - non_driver, + non_driver.clone(), pending_proposal_consumer, event_notifier, rpath.clone(), @@ -56,6 +61,7 @@ impl RPathService { local_id, rpath, hotstuff, + non_driver, }; Ok(Self(Arc::new(raw))) @@ -71,6 +77,16 @@ impl RPathService { self.rpath(), proposal.desc().object_id() ); + + let object_raw = proposal.to_vec()?; + let any_obj = + AnyNamedObject::Core(TypelessCoreObject::clone_from_slice(object_raw.as_slice())?); + let non_obj = NONObjectInfo::new( + proposal.desc().object_id(), + object_raw, + Some(Arc::new(any_obj)), + ); + self.0.non_driver.put_object(non_obj).await?; self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 01d57996b..b913490f2 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -8,9 +8,9 @@ use cyfs_base::{ use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, - NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, - RequestProtocol, RequestSourceInfo, SharedCyfsStack, + CyfsStackRequestorType, DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, + NONOutputRequestCommon, NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, + NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; @@ -473,7 +473,7 @@ mod Common { dec_app: &DecApp, rpc_port: u16, ws_port: u16, - ) -> (CyfsStack, SharedCyfsStack) { + ) -> (Box, Box) { let params = init_stack_params( people, private_key, @@ -488,20 +488,23 @@ mod Common { log::info!("cyfs-stack.open"); - let stack = CyfsStack::open(params.0, params.1, params.2) - .await - .map_err(|e| { - log::error!("stack start failed: {}", e); - e - }) - .unwrap(); + let stack = Box::new( + CyfsStack::open(params.0, params.1, params.2) + .await + .map_err(|e| { + log::error!("stack start failed: {}", e); + e + }) + .unwrap(), + ); async_std::task::sleep(Duration::from_millis(1000)).await; - let shared_stack = + let shared_stack = Box::new( SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) .await - .unwrap(); + .unwrap(), + ); shared_stack.wait_online(None).await.unwrap(); @@ -539,7 +542,7 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; use cyfs_group_lib::{ @@ -548,7 +551,8 @@ mod GroupDecService { }; use cyfs_lib::{ CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, - RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, + RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, + RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -561,50 +565,82 @@ mod GroupDecService { cyfs_stack: &SharedCyfsStack, local_name: String, dec_app_id: DecAppId, + group_id: ObjectId, + rpath: &str, ) -> GroupManager { let group_mgr = GroupManager::open( cyfs_stack.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), + Box::new(GroupRPathDelegateFactory { + local_name: local_name.clone(), + }), &cyfs_lib::CyfsStackRequestorType::Http, ) .await .unwrap(); - // let source = RequestSourceInfo { - // protocol: todo!(), - // zone: todo!(), - // dec: todo!(), - // verified: todo!(), - // }; + let filter = format!("obj_type == {}", CoreObjectType::GroupProposal as u16,); + let routine = ProposalListener { + service: group_mgr + .start_rpath_service( + group_id, + rpath.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), + ) + .await + .unwrap(), + local_name, + }; - // cyfs_stack - // .router_handlers() - // .handlers(&RouterHandlerChain::PostRouter) - // .post_object() - // .add_handler(RouterHandler::new()); + cyfs_stack + .router_handlers() + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-proposal-listener-{}", dec_app_id).as_str(), + 0, + Some(filter), + Some("group-proposal".to_string()), + RouterHandlerAction::Pass, + Some(Box::new(routine)), + ) + .await + .unwrap(); group_mgr } } - // pub struct PostProposalRoutine { - // service: RPathService, - // } + pub struct ProposalListener { + service: RPathService, + local_name: String, + } - // #[async_trait::async_trait] - // impl EventListenerAsyncRoutine - // for PostProposalRoutine - // { - // async fn call( - // &self, - // param: &NONPostObjectInputRequest, - // ) -> BuckyResult { - // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; - // assert_eq!(remain.len(), 0); - // self.service.push_proposal(proposal).await?; - // Ok(NONPostObjectInputResponse { object: None }) - // } - // } + #[async_trait::async_trait] + impl EventListenerAsyncRoutine + for ProposalListener + { + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + log::info!( + "recv proposal {} from {:?}, local: {}", + param.request.object.object_id, + param.request.common.source.zone, + self.local_name + ); + + let (proposal, remain) = + GroupProposal::raw_decode(param.request.object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + self.service.push_proposal(&proposal).await.unwrap(); + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: None, + }) + } + } pub struct GroupRPathDelegateFactory { local_name: String, @@ -939,6 +975,8 @@ fn create_proposal( async fn main_run() { log::info!("main_run"); + async_std::task::sleep(Duration::from_millis(10000)).await; + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -972,8 +1010,10 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; - let mut group_mgrs: Vec = vec![]; + let mut admin_stacks: Vec<(Box, Box)> = vec![]; + let mut admin_group_mgrs: Vec = vec![]; + let mut member_stacks: Vec<(Box, Box)> = vec![]; + let mut member_group_mgrs: Vec = vec![]; let mut rpc_port = 32217_u16; let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { @@ -1000,25 +1040,60 @@ async fn main_run() { ws_port += 1; } + for ((member, _), (device, private_key)) in members.iter() { + let (cyfs_stack, shared_stack) = create_stack( + member, + private_key, + device, + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + &group, + &dec_app, + rpc_port, + ws_port, + ) + .await; + member_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; + } + async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); let local_name = admin.name().unwrap(); - let group_mgr = - DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; - - let service = group_mgr - .start_rpath_service( - group.desc().object_id(), - EXAMPLE_RPATH.to_string(), - Box::new(MyRPathDelegate::new(local_name.to_string())), - ) - .await - .unwrap(); - group_mgrs.push(group_mgr); + let group_mgr = DecService::run( + &shared_stack, + local_name.to_string(), + dec_app_id.clone(), + group_id, + EXAMPLE_RPATH.as_str(), + ) + .await; + + admin_group_mgrs.push(group_mgr); + } + + for i in 0..member_stacks.len() { + let (_, shared_stack) = member_stacks.get(i).unwrap(); + let ((member, _), _) = members.get(i).unwrap(); + let group_mgr = GroupManager::open_as_client( + shared_stack.as_ref().clone(), + &CyfsStackRequestorType::WebSocket, + ) + .await + .unwrap(); + + member_group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1029,9 +1104,9 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let owner = &members.get(i % members.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, owner.desc().object_id(), @@ -1039,11 +1114,6 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); - let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); @@ -1073,16 +1143,29 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); + let stack = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let ((member, _), _) = members.get(i % members.len()).unwrap(); + let local_name = member.name().map(|n| n.to_string()); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); + let client = group_mgr + .rpath_client(group_id, dec_app_id.clone(), &EXAMPLE_RPATH) + .await; async_std::task::spawn(async move { - service.push_proposal(&proposal).await.unwrap(); + log::info!( + "client {:?} will post proposal {}", + local_name, + proposal.desc().object_id(), + ); + + let result = client.post_proposal(&proposal).await; + log::info!( + "client {:?} post proposal {}, result: {:?}", + local_name, + proposal.desc().object_id(), + result.map(|o| o.map(|o| o.object_id)) + ); }); if i % 10 == 0 { @@ -1093,7 +1176,7 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - // let client = group_mgrs + // let client = admin_group_mgrs // .get(0) // .unwrap() // .rpath_client( From 67c3a81fbaaf4a9155acef1ce0a05ae326da7f19 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:13:38 +0800 Subject: [PATCH 479/553] merge from buckyos --- src/component/cyfs-group/Cargo.toml | 2 +- src/component/cyfs-noc/src/blob/file.rs | 1 - src/component/cyfs-stack/Cargo.toml | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 599e13b51..aaab4ed76 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -28,7 +28,7 @@ async-recursion = '1.0' rand = '0.8.5' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } -cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.6' } +cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-noc/src/blob/file.rs b/src/component/cyfs-noc/src/blob/file.rs index 13838c174..9417d1377 100644 --- a/src/component/cyfs-noc/src/blob/file.rs +++ b/src/component/cyfs-noc/src/blob/file.rs @@ -4,7 +4,6 @@ use cyfs_lib::*; use std::borrow::Cow; use std::path::{Path, PathBuf}; -use std::borrow::Cow; pub struct FileBlobStorage { root: PathBuf, diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index 37142e968..d005147ec 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -15,6 +15,7 @@ cyfs-bdt = { path = "../../component/cyfs-bdt" } cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } +cyfs-group = { path = "../../component/cyfs-group" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } From 827b255751bebcef97fdeba2417adda18ccc34a4 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 16:22:30 +0800 Subject: [PATCH 480/553] rename GroupRPathMgr to GroupManager --- .../src/dec/{rpath_mgr.rs => group_manager.rs} | 4 ++-- src/component/cyfs-group/src/dec/mod.rs | 4 ++-- src/component/cyfs-group/src/network/listener.rs | 6 +++--- src/component/cyfs-stack/src/stack/cyfs_stack.rs | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_mgr.rs => group_manager.rs} (99%) diff --git a/src/component/cyfs-group/src/dec/rpath_mgr.rs b/src/component/cyfs-group/src/dec/group_manager.rs similarity index 99% rename from src/component/cyfs-group/src/dec/rpath_mgr.rs rename to src/component/cyfs-group/src/dec/group_manager.rs index 644fc2fcf..56ef5e7d9 100644 --- a/src/component/cyfs-group/src/dec/rpath_mgr.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -34,9 +34,9 @@ struct LocalInfo { } #[derive(Clone)] -pub struct GroupRPathMgr(Arc<(LocalInfo, RwLock)>); +pub struct GroupManager(Arc<(LocalInfo, RwLock)>); -impl GroupRPathMgr { +impl GroupManager { pub fn new( signer: RsaCPUObjectSigner, non_driver: Box, diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index a1f964e95..b4e753a27 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod delegate_factory; mod rpath_client; mod rpath_control; -mod rpath_mgr; +mod group_manager; pub use delegate_factory::*; pub use rpath_client::*; pub use rpath_control::*; -pub use rpath_mgr::*; +pub use group_manager::*; diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index 6a6d7b549..e66ef8a43 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; -use crate::{GroupRPathMgr, HotstuffPackage}; +use crate::{GroupManager, HotstuffPackage}; pub struct Listener; impl Listener { pub fn spawn( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { async_std::task::spawn(async move { @@ -20,7 +20,7 @@ impl Listener { async fn run( datagram: DatagramTunnelGuard, - processor: GroupRPathMgr, + processor: GroupManager, local_device_id: ObjectId, ) { loop { diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 96eaad5cf..d208f57cf 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -35,9 +35,9 @@ use crate::zone::{ZoneManager, ZoneManagerRef, ZoneRoleManager}; use crate::GroupNONDriver; use cyfs_base::*; -use cyfs_bdt::{DeviceCache, StackGuard, SnStatus}; -use cyfs_group::GroupRPathMgr; +use cyfs_bdt::{DeviceCache, SnStatus, StackGuard}; use cyfs_bdt_ext::{BdtStackParams, NamedDataComponents}; +use cyfs_group::GroupManager; use cyfs_lib::*; use cyfs_noc::*; use cyfs_task_manager::{SQLiteTaskStore, TaskManager}; @@ -105,7 +105,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupRPathMgr, + group_manager: GroupManager, } impl CyfsStackImpl { @@ -431,7 +431,7 @@ impl CyfsStackImpl { config.clone(), ); - let group_manager = GroupRPathMgr::new( + let group_manager = GroupManager::new( signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), @@ -1162,7 +1162,7 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupRPathMgr { + pub fn group_mgr(&self) -> &GroupManager { &self.stack.group_manager } From a082490875c40b022fe2aac59b8504b58b7f984e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Feb 2023 21:19:34 +0800 Subject: [PATCH 481/553] integrate GroupState, not finish --- .../cyfs-base/src/objects/object_map/mod.rs | 3 +- .../src/consensus/hotstuff/hotstuff.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 4 + .../cyfs-group/src/statepath/design.md | 26 +-- .../src/storage/engine/group_state_path.rs | 178 +++++++++++++++ .../cyfs-group/src/storage/engine/mod.rs | 9 + .../src/storage/engine/storage_engine.rs | 23 ++ .../engine/storage_engine_group_state.rs | 207 ++++++++++++++++++ .../storage_engine_mock.rs} | 53 ++--- .../cyfs-group/src/storage/group_storage.rs | 71 +++++- src/component/cyfs-group/src/storage/mod.rs | 4 +- 12 files changed, 524 insertions(+), 70 deletions(-) create mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs create mode 100644 src/component/cyfs-group/src/storage/engine/mod.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine.rs create mode 100644 src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs rename src/component/cyfs-group/src/storage/{storage_engine.rs => engine/storage_engine_mock.rs} (76%) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index be52c2ea5..3bbc5f131 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -2,6 +2,7 @@ mod access; mod cache; mod check; mod diff; +mod isolate_path_env; mod iterator; mod lock; mod object_map; @@ -13,7 +14,6 @@ mod path_iterator; mod root; mod single_env; mod visitor; -mod isolate_path_env; pub use access::*; pub use cache::*; @@ -25,4 +25,5 @@ pub use path::*; pub use path_env::*; pub use path_iterator::*; pub use root::*; +pub use single_env::*; pub use visitor::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index ff4e06380..e89498b83 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -18,7 +18,7 @@ use crate::{ consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** @@ -1461,12 +1461,13 @@ impl HotstuffRunner { continue; } - if let Some(ending) = proposal.effective_ending() { - if now >= bucky_time_to_system_time(ending) { - remove_proposals.push(proposal.desc().object_id()); - timeout_proposals.push(proposal); - continue; - } + let ending = proposal.effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), + |ending| bucky_time_to_system_time(ending)); + if now >= ending { + remove_proposals.push(proposal.desc().object_id()); + timeout_proposals.push(proposal); + continue; } match self.delegate.on_execute(&proposal, result_state_id).await { diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index aa7babc44..1170176b2 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -14,6 +14,7 @@ pub const NETWORK_TIMEOUT: Duration = Duration::from_millis(5000); pub const HOTSTUFF_TIMEOUT_DEFAULT: u64 = 5000; pub const CHANNEL_CAPACITY: usize = 1000; pub const TIME_PRECISION: Duration = Duration::from_millis(60000); +pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 56ef5e7d9..95c931720 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,6 +6,7 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, @@ -31,6 +32,7 @@ struct LocalInfo { non_driver: Arc>, datagram: DatagramTunnelGuard, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl GroupManager { signer: RsaCPUObjectSigner, non_driver: Box, bdt_stack: StackGuard, + global_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); @@ -50,6 +53,7 @@ impl GroupManager { non_driver: Arc::new(non_driver), datagram: datagram.clone(), bdt_stack, + global_state_mgr, }; let raw = GroupRPathMgrRaw { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index b73a46939..7ec71d4d5 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -7,22 +7,18 @@ | |--list-->Set | |--option-->GroupOption | -|--.dec-state // for dec;各Group的dec状态放这里 -| |--${group-id} // ${groupid}/.group/update 留着做group的版本同步 -| |--${dec-id} | .group // 一个dec管理的${r-path}状态 -| | | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--${r-path}-->ObjectId // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | -| -|--.link // 区块链结构,记录状态变更链条 -| |--${group-id} -| |--${dec-id} | .group // .group表示group本身的演变共识 +|--${group-id} +| |--${dec-id} +| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 +| | // APP控制的实体状态,通常是个map-id +| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 +| | // 其他内部逻辑隐藏掉 +| | // 每个${r-path}管理范围内是串行的 +| | // 不同${r-path}范围内的操作是并行的 +| | // 且不同${r-path}之间是并列的,不能嵌套 +| |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-chunk-->Chunk(Group) +| |--group-blob-->BLOB(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs new file mode 100644 index 000000000..4e67d6e1f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/group_state_path.rs @@ -0,0 +1,178 @@ +use cyfs_base::ObjectId; + +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; + +pub struct GroupStatePath { + rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, +} + +impl GroupStatePath { + pub fn new(rpath: String) -> Self { + Self { + rpath, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.rpath.as_str() + } + + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() + } + + pub fn link(&self) -> &str { + self.link.as_str() + } + + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() + } + + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() + } + + pub fn range(&self) -> &str { + self.range.as_str() + } + + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) + } + + pub fn commit_block(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn commit_proposals(&self, height: u64) -> String { + Self::join(&[ + self.link.as_str(), + height.to_string().as_str(), + GROUP_STATE_PATH_PROPOSALS, + ]) + } + + pub fn prepares(&self) -> &str { + self.prepares.as_str() + } + + pub fn prepare_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() + } + + pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.pre_commits.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() + } + + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() + } + + pub fn recycle(&self) -> &str { + self.recycle.as_str() + } + + pub fn adding(&self) -> &str { + self.adding.as_str() + } +} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs new file mode 100644 index 000000000..71d5cc49f --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -0,0 +1,9 @@ +mod group_state_path; +mod storage_engine; +mod storage_engine_group_state; +mod storage_engine_mock; + +pub(super) use group_state_path::*; +pub(super) use storage_engine::*; +pub(super) use storage_engine_group_state::*; +pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs new file mode 100644 index 000000000..e48e607bc --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -0,0 +1,23 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +#[async_trait::async_trait] +pub trait StorageWriter: Send + Sync + Drop { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; + async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) + -> BuckyResult<()>; + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()>; + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +pub trait StorageEngine { + async fn find_block_by_height(&self, height: u64) -> BuckyResult; + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs new file mode 100644 index 000000000..3aba73e31 --- /dev/null +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -0,0 +1,207 @@ +use std::{collections::HashSet, sync::Arc}; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, +}; + +use crate::StatePath; + +use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; + +const ACCESS: Option = None; + +#[derive(Clone)] +pub struct StorageEngineGroupState { + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, +} + +impl StorageEngineGroupState { + pub async fn load( + dec_group_state: ObjectMapRootManagerRef, + state_path: GroupStatePath, + ) -> BuckyResult { + Ok(Self { + state_mgr: todo!(), + state_path: Arc::new(state_path), + }) + } + + pub async fn create_writer(&self) -> BuckyResult { + Ok( + StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) + .await?, + ) + } +} + +#[async_trait::async_trait] +impl StorageEngine for StorageEngineGroupState { + async fn find_block_by_height(&self, height: u64) -> BuckyResult { + let op_env = self.state_mgr.create_op_env(ACCESS)?; + let block_id = op_env + .get_by_path(self.state_path.commit_block(height).as_str()) + .await?; + block_id.map_or( + Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), + |block_id| Ok(block_id), + ) + } +} + +#[derive(Clone)] +pub struct StorageEngineGroupStateWriter { + state_mgr: ObjectMapRootManagerRef, + op_env: ObjectMapPathOpEnvRef, + prepare_op_env: ObjectMapSingleOpEnvRef, + prepare_map_id: Option, + state_path: Arc, +} + +impl StorageEngineGroupStateWriter { + async fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: Arc, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; + let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; + match prepare_map_id.as_ref() { + Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, + None => { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await? + } + }; + + Ok(Self { + op_env, + prepare_op_env, + state_path, + state_mgr, + prepare_map_id, + }) + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; + new_prepare + .create_new(ObjectMapSimpleContentType::Map) + .await?; + new_prepare + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + let new_prepare_block = new_prepare.commit().await?; + + self.prepare_op_env + .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .await + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + if !self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str()) + .await? + .is_some() + { + assert!(false); + } + + // TODO + if is_instead { + self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); + } else { + if !self.engine.pre_commit_blocks.insert(block_id.clone()) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block pre-commit twice", + )); + } + } + + Ok(()) + } + + async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + if self + .engine + .commit_blocks + .insert(height, block_id.clone()) + .is_some() + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "block commit twice", + )); + } + + self.engine.block_height_range.1 = height; + + Ok(()) + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + for block_id in block_ids { + if !self.engine.prepare_blocks.remove(block_id) { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "try remove prepare not exists", + )); + } + } + Ok(()) + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option, + ) -> BuckyResult<()> { + if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + self.engine.finish_proposals.flip_timestamp = timestamp; + } + + for proposal_id in proposal_ids { + if !self + .engine + .finish_proposals + .adding + .insert(proposal_id.clone()) + { + assert!(false); + return Err(BuckyError::new( + BuckyErrorCode::AlreadyExists, + "dup finish proposal", + )); + } + } + + Ok(()) + } + + async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + self.engine.last_vote_round = round; + + Ok(()) + } +} + +impl<'a> Drop for StorageEngineGroupStateWriter<'a> { + fn drop(&mut self) {} +} diff --git a/src/component/cyfs-group/src/storage/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs similarity index 76% rename from src/component/cyfs-group/src/storage/storage_engine.rs rename to src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b9376618b..6208b0680 100644 --- a/src/component/cyfs-group/src/storage/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -2,28 +2,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -#[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; - async fn push_proposals( - &mut self, - proposal_ids: &[ObjectId], - timestamp: u64, - ) -> BuckyResult<()>; - - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; -} - -#[async_trait::async_trait] -pub trait StorageEngine { - async fn find_block_by_height(&self, height: u64) -> BuckyResult; - async fn create_writer(&mut self) -> BuckyResult; - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult; -} +use super::{StorageEngine, StorageWriter}; struct StorageEngineMockFinishProposalMgr { flip_timestamp: u64, @@ -58,6 +37,10 @@ impl StorageEngineMock { }, } } + + pub async fn create_writer(&mut self) -> BuckyResult { + Ok(StorageEngineMockWriter { engine: self }) + } } #[async_trait::async_trait] @@ -69,19 +52,15 @@ impl StorageEngine for StorageEngineMock { .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - async fn create_writer(&mut self) -> BuckyResult { - Ok(StorageEngineMockWriter { engine: self }) - } - - async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { - let is_finished = self - .finish_proposals - .adding - .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) - .is_some(); - Ok(is_finished) - } + // async fn is_proposal_finished(&self, proposal_id: &ObjectId) -> BuckyResult { + // let is_finished = self + // .finish_proposals + // .adding + // .get(proposal_id) + // .or(self.finish_proposals.over.get(proposal_id)) + // .is_some(); + // Ok(is_finished) + // } } pub struct StorageEngineMockWriter<'a> { @@ -164,9 +143,9 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: u64, + timestamp: Option, ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { + if let Some(timestamp) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 440613f51..bc9fc6009 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, time::SystemTime}; +use std::{ + collections::{HashMap, HashSet}, + time::SystemTime, +}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, @@ -6,10 +9,13 @@ use cyfs_base::{ }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; + +use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use crate::{storage::StorageWriter, NONDriverHelper, TIME_PRECISION}; +use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; -use super::{storage_engine::StorageEngineMock, StorageEngine}; +const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; pub enum BlockLinkState { Expired, @@ -23,6 +29,12 @@ pub enum BlockLinkState { InvalidBranch, } +struct FinishProposalMgr { + flip_timestamp: u64, + over: HashSet, + adding: HashSet, +} + pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -39,6 +51,8 @@ pub struct GroupStorage { prepares: HashMap, pre_commits: HashMap, + finish_proposals: FinishProposalMgr, + storage_engine: StorageEngineMock, } @@ -50,11 +64,19 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + // let group_state = root_state_mgr + // .load_root_state(group_id, Some(group_id.clone()), true) + // .await? + // .expect("create group state failed."); + + // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + Ok(Self { group, group_id: group_id.clone(), @@ -70,6 +92,11 @@ impl GroupStorage { pre_commits: HashMap::new(), storage_engine: StorageEngineMock::new(), local_device_id, + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, }) } @@ -78,6 +105,7 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, + // root_state_mgr: GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group @@ -240,10 +268,17 @@ impl GroupStorage { .iter() .map(|p| p.proposal.clone()) .collect(); - writer.push_proposals( - finish_proposals.as_slice(), - new_header.named_object().desc().create_time(), - ); + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + writer + .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } // update memory @@ -276,6 +311,20 @@ impl GroupStorage { if self.first_block.is_none() { self.first_block = self.header_block.clone(); } + + let timestamp = new_header.named_object().desc().create_time(); + if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.finish_proposals.over); + self.finish_proposals.flip_timestamp = timestamp; + } + + for proposal in new_header.proposals() { + let is_new = self.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } + return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -551,7 +600,13 @@ impl GroupStorage { // find in storage - self.storage_engine.is_proposal_finished(proposal_id).await + let is_finished = self + .finish_proposals + .adding + .get(proposal_id) + .or(self.finish_proposals.over.get(proposal_id)) + .is_some(); + Ok(is_finished) } pub fn block_with_max_round(&self) -> Option { diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d95cf7ddd..d4440419e 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,7 @@ mod dec_storage; +mod engine; mod group_storage; -mod storage_engine; pub use dec_storage::*; +use engine::*; pub use group_storage::*; -pub(crate) use storage_engine::*; From b1b419efe4db765e035fd146296a220ae6b291e7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 17:28:17 +0800 Subject: [PATCH 482/553] integrate GroupState update --- .../cyfs-group/src/statepath/design.md | 11 +- .../src/statepath/group_statepath.rs | 257 +++++------- .../src/storage/engine/group_state_path.rs | 178 --------- .../cyfs-group/src/storage/engine/mod.rs | 2 - .../src/storage/engine/storage_engine.rs | 17 +- .../engine/storage_engine_group_state.rs | 367 +++++++++++++----- .../src/storage/engine/storage_engine_mock.rs | 30 +- .../cyfs-group/src/storage/group_storage.rs | 30 +- .../cyfs-stack/src/stack/cyfs_stack.rs | 1 + 9 files changed, 439 insertions(+), 454 deletions(-) delete mode 100644 src/component/cyfs-group/src/storage/engine/group_state_path.rs diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 7ec71d4d5..70a61e428 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -25,15 +25,10 @@ | |--last-vote-round-->u64 // 最后一次投票的轮次 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height}) -| | |--block-->GroupConsensusBlock +| |--str(${height})->block | | -| |--prepares // Prepare状态的block -| | |--${block.id} -| | |--block -| |--pre-commits // pre-commit状态的block -| | |--${block.id} -| | |--block +| |--prepares->Set // Prepare状态的block +| |--pre-commits->Set // pre-commit状态的block | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index c0daef478..eade0f9e4 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,19 +1,17 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; -pub const STATEPATH_SEPARATOR: &str = "/"; - -pub const STATEPATH_GROUPS: &str = "groups"; - -pub const STATEPATH_DEC_STATE: &str = ".dec-state"; - -pub const STATEPATH_LINK: &str = ".link"; -pub const STATEPATH_GROUP_HASH: &str = "group-hash"; -pub const STATEPATH_USERS: &str = "users"; -pub const STATEPATH_USERS_NONCE: &str = "nonce"; -pub const STATEPATH_RANGE: &str = "range"; -pub const STATEPATH_BLOCK: &str = "block"; - -pub const STATEPATH_RPATHS: &str = ".r-paths"; +pub const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; +pub const GROUP_STATE_PATH_LINK: &str = ".link"; +pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_RANGE: &str = "range"; +pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; +pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; +pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; +pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; +pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; @@ -23,180 +21,131 @@ lazy_static::lazy_static! { pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); } -pub struct StatePath { - group_id: ObjectId, - group_id_str: String, - dec_id: ObjectId, - dec_id_str: String, +pub struct GroupStatePath { rpath: String, + dec_state: String, + link: String, + group_blob: String, + last_vote_round: String, + range: String, + prepares: String, + pre_commits: String, + finish_proposals: String, + flip_time: String, + recycle: String, + adding: String, } -impl StatePath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { +impl GroupStatePath { + pub fn new(rpath: String) -> Self { Self { - group_id_str: group_id.to_string(), - group_id, - dec_id_str: dec_id.to_string(), - dec_id, + dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + group_blob: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_GROUP_BLOB, + ]), + last_vote_round: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, + ]), + range: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_RANGE, + ]), + prepares: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PREPARES, + ]), + pre_commits: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_PRE_COMMITS, + ]), + finish_proposals: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + ]), + flip_time: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_FLIP_TIME, + ]), + recycle: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_RECYCLE, + ]), + adding: Self::join(&[ + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_FINISH_PROPOSALS, + GROUP_STATE_PATH_ADDING, + ]), rpath, } } pub fn join(fields: &[&str]) -> String { - fields.join(STATEPATH_SEPARATOR) - } - - pub fn dec_state() -> String { - STATEPATH_DEC_STATE.to_string() - } - - pub fn dec_state_group(&self) -> String { - Self::join(&[STATEPATH_DEC_STATE, self.group_id_str.as_str()]) - } - - pub fn dec_state_dec(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + fields.join(STATE_PATH_SEPARATOR) } - pub fn dec_state_rpath(&self) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn root(&self) -> &str { + self.rpath.as_str() } - pub fn dec_state_rpath_with_sub_path(&self, sub_path: &str) -> String { - Self::join(&[ - STATEPATH_DEC_STATE, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - sub_path, - ]) + pub fn dec_state(&self) -> &str { + self.dec_state.as_str() } - pub fn link() -> String { - STATEPATH_LINK.to_string() + pub fn link(&self) -> &str { + self.link.as_str() } - pub fn link_group(&self) -> String { - Self::join(&[STATEPATH_LINK, self.group_id_str.as_str()]) + pub fn group_blob(&self) -> &str { + self.group_blob.as_str() } - pub fn link_dec(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - ]) + pub fn last_vote_round(&self) -> &str { + self.last_vote_round.as_str() } - pub fn link_rpath(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - ]) + pub fn range(&self) -> &str { + self.range.as_str() } - pub fn link_group_hash(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_GROUP_HASH, - ]) + pub fn commit_height(&self, height: u64) -> String { + Self::join(&[self.link.as_str(), height.to_string().as_str()]) } - pub fn link_users(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - ]) + pub fn prepares(&self) -> &str { + self.prepares.as_str() } - pub fn link_user(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - ]) + pub fn pre_commits(&self) -> &str { + self.pre_commits.as_str() } - pub fn link_user_nonce(&self, user_id: &ObjectId) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_USERS, - user_id.to_string().as_str(), - STATEPATH_USERS_NONCE, - ]) + pub fn finish_proposals(&self) -> &str { + self.finish_proposals.as_str() } - pub fn link_range(&self) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - STATEPATH_RANGE, - ]) - } - - pub fn link_height(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - ]) - } - - pub fn link_block(&self, height_seq: u64) -> String { - Self::join(&[ - STATEPATH_LINK, - self.group_id_str.as_str(), - self.dec_id_str.as_str(), - self.rpath.as_str(), - height_seq.to_string().as_str(), - STATEPATH_BLOCK, - ]) - } - - pub fn rpaths(&self) -> String { - STATEPATH_RPATHS.to_string() - } -} - -pub struct GroupUpdateStatePath; - -impl GroupUpdateStatePath { - pub fn latest_version() -> &'static str { - STATEPATH_GROUP_DEC_LATEST_VERSION + pub fn flip_time(&self) -> &str { + self.flip_time.as_str() } - pub fn version_seq(version_seq: u64) -> String { - version_seq.to_string() + pub fn recycle(&self) -> &str { + self.recycle.as_str() } - pub fn group_hash(group_hash: &ObjectId) -> String { - group_hash.to_string() + pub fn adding(&self) -> &str { + self.adding.as_str() } } diff --git a/src/component/cyfs-group/src/storage/engine/group_state_path.rs b/src/component/cyfs-group/src/storage/engine/group_state_path.rs deleted file mode 100644 index 4e67d6e1f..000000000 --- a/src/component/cyfs-group/src/storage/engine/group_state_path.rs +++ /dev/null @@ -1,178 +0,0 @@ -use cyfs_base::ObjectId; - -pub const STATE_PATH_SEPARATOR: &str = "/"; -pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; -pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; -pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; -pub const GROUP_STATE_PATH_RANGE: &str = "range"; -pub const GROUP_STATE_PATH_BLOCK: &str = "block"; -pub const GROUP_STATE_PATH_PROPOSALS: &str = "proposals"; -pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; -pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; -pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; -pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; -pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; -pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; -pub const GROUP_STATE_PATH_ADDING: &str = "adding"; - -pub struct GroupStatePath { - rpath: String, - dec_state: String, - link: String, - group_blob: String, - last_vote_round: String, - range: String, - prepares: String, - pre_commits: String, - finish_proposals: String, - flip_time: String, - recycle: String, - adding: String, -} - -impl GroupStatePath { - pub fn new(rpath: String) -> Self { - Self { - rpath, - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, - ]), - last_vote_round: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, - ]), - range: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_RANGE, - ]), - prepares: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PREPARES, - ]), - pre_commits: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_PRE_COMMITS, - ]), - finish_proposals: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - ]), - flip_time: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_FLIP_TIME, - ]), - recycle: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_RECYCLE, - ]), - adding: Self::join(&[ - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_FINISH_PROPOSALS, - GROUP_STATE_PATH_ADDING, - ]), - } - } - - pub fn join(fields: &[&str]) -> String { - fields.join(STATE_PATH_SEPARATOR) - } - - pub fn root(&self) -> &str { - self.rpath.as_str() - } - - pub fn dec_state(&self) -> &str { - self.dec_state.as_str() - } - - pub fn link(&self) -> &str { - self.link.as_str() - } - - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() - } - - pub fn last_vote_round(&self) -> &str { - self.last_vote_round.as_str() - } - - pub fn range(&self) -> &str { - self.range.as_str() - } - - pub fn commit_height(&self, height: u64) -> String { - Self::join(&[self.link.as_str(), height.to_string().as_str()]) - } - - pub fn commit_block(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn commit_proposals(&self, height: u64) -> String { - Self::join(&[ - self.link.as_str(), - height.to_string().as_str(), - GROUP_STATE_PATH_PROPOSALS, - ]) - } - - pub fn prepares(&self) -> &str { - self.prepares.as_str() - } - - pub fn prepare_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.prepares.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn pre_commits(&self) -> &str { - self.pre_commits.as_str() - } - - pub fn pre_commit_block(&self, block_id: &ObjectId) -> String { - Self::join(&[ - self.pre_commits.as_str(), - block_id.to_string().as_str(), - GROUP_STATE_PATH_BLOCK, - ]) - } - - pub fn finish_proposals(&self) -> &str { - self.finish_proposals.as_str() - } - - pub fn flip_time(&self) -> &str { - self.flip_time.as_str() - } - - pub fn recycle(&self) -> &str { - self.recycle.as_str() - } - - pub fn adding(&self) -> &str { - self.adding.as_str() - } -} diff --git a/src/component/cyfs-group/src/storage/engine/mod.rs b/src/component/cyfs-group/src/storage/engine/mod.rs index 71d5cc49f..c185cb24c 100644 --- a/src/component/cyfs-group/src/storage/engine/mod.rs +++ b/src/component/cyfs-group/src/storage/engine/mod.rs @@ -1,9 +1,7 @@ -mod group_state_path; mod storage_engine; mod storage_engine_group_state; mod storage_engine_mock; -pub(super) use group_state_path::*; pub(super) use storage_engine::*; pub(super) use storage_engine_group_state::*; pub(super) use storage_engine_mock::*; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e48e607bc..e19c46b81 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,19 +1,28 @@ use cyfs_base::{BuckyResult, ObjectId}; #[async_trait::async_trait] -pub trait StorageWriter: Send + Sync + Drop { +pub trait StorageWriter: Send + Sync { async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) -> BuckyResult<()>; - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()>; + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()>; async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()>; - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()>; + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + + async fn commit(mut self) -> BuckyResult<()>; } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 3aba73e31..731725e95 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMapPathOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use crate::StatePath; +use crate::{ + GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, +}; -use super::{GroupStatePath, StorageEngine, StorageWriter, GROUP_STATE_PATH_BLOCK}; +use super::{StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -41,7 +44,7 @@ impl StorageEngine for StorageEngineGroupState { async fn find_block_by_height(&self, height: u64) -> BuckyResult { let op_env = self.state_mgr.create_op_env(ACCESS)?; let block_id = op_env - .get_by_path(self.state_path.commit_block(height).as_str()) + .get_by_path(self.state_path.commit_height(height).as_str()) .await?; block_id.map_or( Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")), @@ -57,6 +60,7 @@ pub struct StorageEngineGroupStateWriter { prepare_op_env: ObjectMapSingleOpEnvRef, prepare_map_id: Option, state_path: Arc, + write_result: BuckyResult<()>, } impl StorageEngineGroupStateWriter { @@ -65,16 +69,20 @@ impl StorageEngineGroupStateWriter { state_path: Arc, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; - let prepare_map_id = op_env.get_by_path(state_path.prepares()).await?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; - match prepare_map_id.as_ref() { - Some(prepare_map_id) => prepare_op_env.load(prepare_map_id).await?, - None => { - prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await? - } - }; + let prepare_map_id = + if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { + if err.code() == BuckyErrorCode::NotFound { + prepare_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + None + } else { + return Err(err); + } + } else { + prepare_op_env.get_current_root().await + }; Ok(Self { op_env, @@ -82,126 +90,299 @@ impl StorageEngineGroupStateWriter { state_path, state_mgr, prepare_map_id, + write_result: Ok(()), }) } -} - -#[async_trait::async_trait] -impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { - let new_prepare = self.state_mgr.create_single_op_env(ACCESS)?; - new_prepare - .create_new(ObjectMapSimpleContentType::Map) - .await?; - new_prepare - .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) - .await?; - let new_prepare_block = new_prepare.commit().await?; + async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { self.prepare_op_env - .insert_with_key(block_id.to_string().as_str(), &new_prepare_block) + .insert(block_id) .await + .map(|is_changed| assert!(is_changed)) } - async fn insert_pre_commit( + async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, is_instead: bool, ) -> BuckyResult<()> { - if !self - .prepare_op_env - .remove_with_key(block_id.to_string().as_str()) - .await? - .is_some() - { - assert!(false); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); - // TODO if is_instead { - self.engine.pre_commit_blocks = HashSet::from([block_id.clone()]); - } else { - if !self.engine.pre_commit_blocks.insert(block_id.clone()) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block pre-commit twice", - )); - } + self.op_env + .remove_with_path(self.state_path.pre_commits(), &None) + .await?; } - Ok(()) + self.op_env + .insert_with_path(self.state_path.pre_commits(), block_id) + .await } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { - if self - .engine - .commit_blocks - .insert(height, block_id.clone()) - .is_some() - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "block commit twice", - )); - } + async fn push_commit_inner( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.op_env + .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) + .await?; - self.engine.block_height_range.1 = height; + let range_obj = make_range_obj(min_height, height); + if height == 1 { + self.op_env + .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) + .await?; + } else { + let prev_range = make_range_obj(min_height, height - 1); + let prev_value = self + .op_env + .set_with_key( + self.state_path.link(), + GROUP_STATE_PATH_RANGE, + &range_obj, + &Some(prev_range), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_range); + }; + + // update state from dec-app + if result_state_id == prev_result_state_id { + return Ok(()); + } else { + match result_state_id { + Some(result_state_id) => { + if prev_result_state_id.is_none() { + self.op_env + .insert_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + ) + .await?; + } else { + let prev_value = self + .op_env + .set_with_key( + self.state_path.root(), + GROUP_STATE_PATH_DEC_STATE, + result_state_id, + prev_result_state_id, + false, + ) + .await?; + assert_eq!(&prev_value, prev_result_state_id); + } + } + None => { + self.op_env + .remove_with_path(self.state_path.dec_state(), prev_result_state_id) + .await?; + } + } + } Ok(()) } - async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - if !self.engine.prepare_blocks.remove(block_id) { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::ErrorState, - "try remove prepare not exists", - )); - } + let is_changed = self.prepare_op_env.remove(block_id).await?; + assert!(is_changed); } Ok(()) } - async fn push_proposals( + async fn push_proposals_inner( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if timestamp - self.engine.finish_proposals.flip_timestamp > 60000 { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); - self.engine.finish_proposals.flip_timestamp = timestamp; + if proposal_ids.is_empty() { + return Ok(()); } - for proposal_id in proposal_ids { - if !self - .engine - .finish_proposals - .adding - .insert(proposal_id.clone()) - { - assert!(false); - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "dup finish proposal", - )); + let add_single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + + if let Some((timestamp, prev_timestamp)) = timestamp { + let new_over = self + .op_env + .remove_with_path(self.state_path.adding(), &None) + .await?; + + if let Some(new_over) = new_over.as_ref() { + self.op_env + .set_with_path(self.state_path.recycle(), new_over, &None, true) + .await?; } + + let timestamp_obj = make_u64_obj(timestamp); + if prev_timestamp != 0 { + let prev_timestamp_obj = make_u64_obj(prev_timestamp); + let prev_value = self + .op_env + .set_with_path( + self.state_path.flip_time(), + ×tamp_obj, + &Some(prev_timestamp_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_timestamp_obj); + } else { + self.op_env + .insert_with_key( + self.state_path.finish_proposals(), + GROUP_STATE_PATH_FLIP_TIME, + ×tamp_obj, + ) + .await?; + } + + add_single_op_env + .create_new(ObjectMapSimpleContentType::Set) + .await?; + } else { + add_single_op_env + .load_by_path(self.state_path.adding()) + .await?; } + for proposal_id in proposal_ids { + let is_new = add_single_op_env.insert(proposal_id).await?; + assert!(is_new); + } + let adding_set_id = add_single_op_env.commit().await?; + let prev_value = self + .op_env + .set_with_path(self.state_path.adding(), &adding_set_id, &None, true) + .await?; + Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - self.engine.last_vote_round = round; + async fn set_last_vote_round_inner(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert!(round > prev_value); + if round == prev_value { + return Ok(()); + } - Ok(()) + let round_obj = make_u64_obj(round); + + if prev_value == 0 { + self.op_env + .insert_with_path(self.state_path.last_vote_round(), &round_obj) + .await + } else { + let prev_obj = make_u64_obj(prev_value); + let prev_value = self + .op_env + .set_with_path( + self.state_path.last_vote_round(), + &round_obj, + &Some(prev_obj), + false, + ) + .await?; + assert_eq!(prev_value.unwrap(), prev_obj); + Ok(()) + } + } +} + +#[async_trait::async_trait] +impl StorageWriter for StorageEngineGroupStateWriter { + async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result.clone() + } + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + is_instead: bool, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result.clone() + } + + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self + .push_commit_inner( + height, + block_id, + result_state_id, + prev_result_state_id, + min_height, + ) + .await; + self.write_result.clone() + } + + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.remove_prepares_inner(block_ids).await; + self.write_result.clone() + } + + async fn push_proposals( + &mut self, + proposal_ids: &[ObjectId], + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first + ) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.push_proposals_inner(proposal_ids, timestamp).await; + self.write_result.clone() + } + + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.set_last_vote_round_inner(round, prev_value).await; + self.write_result.clone() + } + + async fn commit(mut self) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + + let prepare_map_id = self.prepare_op_env.commit().await?; + self.op_env + .set_with_path( + self.state_path.prepares(), + &prepare_map_id, + &self.prepare_map_id, + self.prepare_map_id.is_none(), + ) + .await?; + self.op_env.commit().await.map(|_| ()) } } -impl<'a> Drop for StorageEngineGroupStateWriter<'a> { - fn drop(&mut self) {} +fn make_range_obj(min: u64, max: u64) -> ObjectId { + let mut range_buf = [0u8; 24]; + let (low, high) = range_buf.split_at_mut(12); + low.copy_from_slice(&min.to_le_bytes()); + high.copy_from_slice(&max.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() +} + +fn make_u64_obj(value: u64) -> ObjectId { + let mut range_buf = [0u8; 8]; + range_buf.copy_from_slice(&value.to_le_bytes()); + ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 6208b0680..b944d3735 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -13,6 +13,7 @@ struct StorageEngineMockFinishProposalMgr { pub struct StorageEngineMock { last_vote_round: u64, + result_state_id: Option, block_height_range: (u64, u64), commit_blocks: HashMap, @@ -30,6 +31,7 @@ impl StorageEngineMock { commit_blocks: HashMap::new(), prepare_blocks: HashSet::new(), pre_commit_blocks: HashSet::new(), + result_state_id: None, finish_proposals: StorageEngineMockFinishProposalMgr { flip_timestamp: 0, over: HashSet::new(), @@ -108,7 +110,18 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn push_commit(&mut self, height: u64, block_id: &ObjectId) -> BuckyResult<()> { + async fn push_commit( + &mut self, + height: u64, + block_id: &ObjectId, + result_state_id: &Option, + prev_result_state_id: &Option, + min_height: u64, + ) -> BuckyResult<()> { + assert!(height > min_height); + assert_eq!(height, self.engine.block_height_range.1 + 1); + assert_eq!(prev_result_state_id, &self.engine.result_state_id); + if self .engine .commit_blocks @@ -123,6 +136,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { } self.engine.block_height_range.1 = height; + self.engine.result_state_id = result_state_id.clone(); Ok(()) } @@ -143,12 +157,13 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn push_proposals( &mut self, proposal_ids: &[ObjectId], - timestamp: Option, + timestamp: Option<(u64, u64)>, // (timestamp, prev_timestamp), 0 if the first ) -> BuckyResult<()> { - if let Some(timestamp) = timestamp { + if let Some((timestamp, prev_timestamp)) = timestamp { let mut new_over = HashSet::new(); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.adding); std::mem::swap(&mut new_over, &mut self.engine.finish_proposals.over); + assert_eq!(prev_timestamp, self.engine.finish_proposals.flip_timestamp); self.engine.finish_proposals.flip_timestamp = timestamp; } @@ -170,13 +185,14 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } - async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { + async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()> { + assert_eq!(self.engine.last_vote_round, prev_value); self.engine.last_vote_round = round; Ok(()) } -} -impl<'a> Drop for StorageEngineMockWriter<'a> { - fn drop(&mut self) {} + async fn commit(mut self) -> BuckyResult<()> { + Ok(()) + } } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index bc9fc6009..a7284f403 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -13,7 +13,7 @@ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; -use super::{storage_engine_mock::StorageEngineMock, StorageEngine}; +use super::{engine::StorageEngineMock, StorageEngine}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -42,15 +42,14 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, + group_chunk_id: ObjectId, dec_state_id: Option, // commited/header state id - group_chunk_id: ObjectId, last_vote_round: u64, // 参与投票的最后一个轮次 header_block: Option, first_block: Option, prepares: HashMap, pre_commits: HashMap, - finish_proposals: FinishProposalMgr, storage_engine: StorageEngineMock, @@ -258,7 +257,15 @@ impl GroupStorage { } if let Some(new_header) = new_header.as_ref() { writer - .push_commit(new_header.height(), new_header.block_id().object_id()) + .push_commit( + new_header.height(), + new_header.block_id().object_id(), + new_header.result_state_id(), + self.header_block + .as_ref() + .map_or(&None, |b| b.result_state_id()), + self.first_block.as_ref().map_or(0, |b| b.height()), + ) .await?; writer.remove_prepares(remove_prepares.as_slice()).await?; @@ -272,7 +279,10 @@ impl GroupStorage { let timestamp = new_header.named_object().desc().create_time(); if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer - .push_proposals(finish_proposals.as_slice(), Some(timestamp)) + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.finish_proposals.flip_timestamp)), + ) .await?; } else { writer @@ -281,6 +291,8 @@ impl GroupStorage { } } + writer.commit().await?; + // update memory if self .prepares @@ -293,7 +305,6 @@ impl GroupStorage { match new_header { Some(new_header) => { self.dec_state_id = new_header.result_state_id().clone(); - self.header_block = Some(new_header); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); self.prepares.remove(&new_pre_commit.0); @@ -309,7 +320,7 @@ impl GroupStorage { } if self.first_block.is_none() { - self.first_block = self.header_block.clone(); + self.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); @@ -325,6 +336,7 @@ impl GroupStorage { assert!(is_new); } + self.header_block = Some(new_header); return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); } None => { @@ -359,7 +371,9 @@ impl GroupStorage { // storage let mut writer = self.storage_engine.create_writer().await?; - writer.set_last_vote_round(round).await?; + writer + .set_last_vote_round(round, self.last_vote_round) + .await?; self.last_vote_round = round; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index d208f57cf..8cf9bcad0 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -435,6 +435,7 @@ impl CyfsStackImpl { signer, Box::new(GroupNONDriver::new(non_service.clone())), bdt_stack.clone(), + global_state_manager.clone_processor(), )?; let mut stack = Self { From d243a170869c240c6ffcd1bf4206a793a7e4f3cc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Feb 2023 20:15:19 +0800 Subject: [PATCH 483/553] integrate GroupState load --- .../cyfs-group/src/dec/group_manager.rs | 12 +- .../src/storage/engine/storage_engine.rs | 37 ++++ .../engine/storage_engine_group_state.rs | 180 ++++++++++++++-- .../cyfs-group/src/storage/group_storage.rs | 198 ++++++++++-------- 4 files changed, 327 insertions(+), 100 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95c931720..5ecfcdba2 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -372,6 +372,7 @@ impl GroupManager { let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -379,7 +380,15 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let store = GroupStorage::load(group_id, dec_id, rpath, non_driver.clone()).await; + let store = GroupStorage::load( + group_id, + dec_id, + rpath, + non_driver.clone(), + local_device_id.object_id().clone(), + &root_state_mgr, + ) + .await; let store = match store { Ok(store) => Some(store), Err(e) => { @@ -430,6 +439,7 @@ impl GroupManager { init_state, non_driver.clone(), local_device_id.object_id().clone(), + &root_state_mgr, ) .await? } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index e19c46b81..735277a3a 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,4 +1,41 @@ +use std::collections::{HashMap, HashSet}; + use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::GroupConsensusBlock; + +pub struct FinishProposalMgr { + pub flip_timestamp: u64, + pub over: HashSet, + pub adding: HashSet, +} + +pub struct StorageCacheInfo { + pub dec_state_id: Option, // commited/header state id + pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub header_block: Option, + pub first_block: Option, + pub prepares: HashMap, + pub pre_commits: HashMap, + pub finish_proposals: FinishProposalMgr, +} + +impl StorageCacheInfo { + pub fn new(init_state_id: Option) -> Self { + Self { + dec_state_id: init_state_id, + last_vote_round: 0, + header_block: None, + first_block: None, + prepares: HashMap::new(), + pre_commits: HashMap::new(), + finish_proposals: FinishProposalMgr { + flip_timestamp: 0, + over: HashSet::new(), + adding: HashSet::new(), + }, + } + } +} #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 731725e95..ee429a78f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -1,16 +1,18 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapPathOpEnvRef, - ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, + ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - GroupStatePath, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_LAST_VOTE_ROUNDS, GROUP_STATE_PATH_RANGE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, + GROUP_STATE_PATH_RANGE, }; -use super::{StorageEngine, StorageWriter}; +use super::{StorageCacheInfo, StorageEngine, StorageWriter}; const ACCESS: Option = None; @@ -21,14 +23,110 @@ pub struct StorageEngineGroupState { } impl StorageEngineGroupState { - pub async fn load( - dec_group_state: ObjectMapRootManagerRef, - state_path: GroupStatePath, - ) -> BuckyResult { - Ok(Self { - state_mgr: todo!(), + pub(crate) async fn load_cache( + state_mgr: &ObjectMapRootManagerRef, + non_driver: &NONDriverHelper, + state_path: &GroupStatePath, + ) -> BuckyResult { + let op_env = state_mgr.create_op_env(ACCESS)?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; + + let last_vote_round = op_env + .get_by_path(state_path.last_vote_round()) + .await? + .map(|id| parse_u64_obj(&id)); + + let mut first_header_block_ids: Vec = vec![]; + let commit_range = op_env + .get_by_path(state_path.range()) + .await? + .map(|id| parse_range_obj(&id)); + let commit_block = match commit_range { + Some((first_height, header_height)) => { + let first_block_id = op_env + .get_by_path(state_path.commit_height(first_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(first_block_id); + + if header_height == first_height { + Some((first_block_id, first_block_id)) + } else { + let header_block_id = op_env + .get_by_path(state_path.commit_height(header_height).as_str()) + .await? + .expect("first block is lost"); + first_header_block_ids.push(header_block_id); + Some((first_block_id, header_block_id)) + } + } + None => None, + }; + + let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let pre_commit_block_ids = + load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + + let flip_timestamp = op_env + .get_by_path(state_path.flip_time()) + .await? + .map_or(0, |id| parse_u64_obj(&id)); + + let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; + let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + + let load_block_ids = [ + first_header_block_ids.as_slice(), + prepare_block_ids.as_slice(), + pre_commit_block_ids.as_slice(), + ] + .concat(); + + let load_blocks = futures::future::join_all( + load_block_ids + .iter() + .map(|id| non_driver.get_block(id, None)), + ) + .await; + + let mut cache = StorageCacheInfo::new(dec_state_id); + cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); + cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); + cache.finish_proposals.flip_timestamp = flip_timestamp; + + let prepare_block_pos = match commit_block { + Some((first_block_id, header_block_id)) => { + cache.first_block = Some(load_blocks.get(0).unwrap().clone()?); + if header_block_id == first_block_id { + cache.header_block = cache.first_block.clone(); + 1 + } else { + cache.header_block = Some(load_blocks.get(1).unwrap().clone()?); + 2 + } + } + None => 0, + }; + + let (prepare_blocks, pre_commit_blocks) = + load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); + for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { + cache.prepares.insert(block_id, block.clone()?); + } + for (block, block_id) in pre_commit_blocks.iter().zip(pre_commit_block_ids) { + cache.pre_commits.insert(block_id, block.clone()?); + } + + Ok(cache) + } + + pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + Self { + state_mgr, state_path: Arc::new(state_path), - }) + } } pub async fn create_writer(&self) -> BuckyResult { @@ -132,12 +230,14 @@ impl StorageEngineGroupStateWriter { .insert_with_path(self.state_path.commit_height(height).as_str(), block_id) .await?; - let range_obj = make_range_obj(min_height, height); if height == 1 { + let range_obj = make_range_obj(1, height); self.op_env .insert_with_key(self.state_path.link(), GROUP_STATE_PATH_RANGE, &range_obj) .await?; } else { + assert!(min_height < height); + let range_obj = make_range_obj(min_height, height); let prev_range = make_range_obj(min_height, height - 1); let prev_value = self .op_env @@ -376,13 +476,63 @@ impl StorageWriter for StorageEngineGroupStateWriter { fn make_range_obj(min: u64, max: u64) -> ObjectId { let mut range_buf = [0u8; 24]; let (low, high) = range_buf.split_at_mut(12); - low.copy_from_slice(&min.to_le_bytes()); - high.copy_from_slice(&max.to_le_bytes()); + low[..8].copy_from_slice(&min.to_le_bytes()); + high[..8].copy_from_slice(&max.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } +fn parse_range_obj(obj: &ObjectId) -> (u64, u64) { + let range_buf = obj.data(); + assert_eq!(range_buf.len(), 24); + let (low_buf, high_buf) = range_buf.split_at(12); + let mut low = [0u8; 8]; + low.copy_from_slice(&low_buf[..8]); + let mut high = [0u8; 8]; + high.copy_from_slice(&high_buf[..8]); + + (u64::from_le_bytes(low), u64::from_le_bytes(high)) +} + fn make_u64_obj(value: u64) -> ObjectId { let mut range_buf = [0u8; 8]; range_buf.copy_from_slice(&value.to_le_bytes()); ObjectIdDataBuilder::new().data(&range_buf).build().unwrap() } + +fn parse_u64_obj(obj: &ObjectId) -> u64 { + let mut buf = [0u8; 8]; + buf.copy_from_slice(obj.data()); + u64::from_le_bytes(buf) +} + +async fn load_object_ids_with_path( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Set(id) => object_ids.push(id.clone()), + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a7284f403..5ad19ea15 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -11,9 +11,14 @@ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; use cyfs_lib::GlobalStateManagerRawProcessorRef; -use crate::{storage::StorageWriter, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION}; +use crate::{ + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, +}; -use super::{engine::StorageEngineMock, StorageEngine}; +use super::{ + engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + StorageEngine, +}; const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; @@ -29,12 +34,6 @@ pub enum BlockLinkState { InvalidBranch, } -struct FinishProposalMgr { - flip_timestamp: u64, - over: HashSet, - adding: HashSet, -} - pub struct GroupStorage { group: Group, group_id: ObjectId, @@ -44,15 +43,9 @@ pub struct GroupStorage { non_driver: NONDriverHelper, group_chunk_id: ObjectId, - dec_state_id: Option, // commited/header state id - last_vote_round: u64, // 参与投票的最后一个轮次 - header_block: Option, - first_block: Option, - prepares: HashMap, - pre_commits: HashMap, - finish_proposals: FinishProposalMgr, + cache: StorageCacheInfo, - storage_engine: StorageEngineMock, + storage_engine: StorageEngineGroupState, } impl GroupStorage { @@ -63,18 +56,18 @@ impl GroupStorage { init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); - // let group_state = root_state_mgr - // .load_root_state(group_id, Some(group_id.clone()), true) - // .await? - // .expect("create group state failed."); + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); - // let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; Ok(Self { group, @@ -82,20 +75,13 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - dec_state_id: init_state_id, group_chunk_id: group_chunk_id.object_id(), - last_vote_round: 0, - header_block: None, - first_block: None, - prepares: HashMap::new(), - pre_commits: HashMap::new(), - storage_engine: StorageEngineMock::new(), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + GroupStatePath::new(rpath.to_string()), + ), local_device_id, - finish_proposals: FinishProposalMgr { - flip_timestamp: 0, - over: HashSet::new(), - adding: HashSet::new(), - }, + cache: StorageCacheInfo::new(init_state_id), }) } @@ -104,37 +90,62 @@ impl GroupStorage { dec_id: &ObjectId, rpath: &str, non_driver: NONDriverHelper, - // root_state_mgr: GlobalStateManagerRawProcessorRef, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { // 用hash加载chunk // 从chunk解析group - // unimplemented!() - Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) + let group = non_driver.get_group(group_id, None, None).await?; + let group_chunk = ChunkMeta::from(&group); + let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group state failed."); + + let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + + let state_path = GroupStatePath::new(rpath.to_string()); + let cache = + StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + + Ok(Self { + group, + group_id: group_id.clone(), + dec_id: dec_id.clone(), + rpath: rpath.to_string(), + non_driver, + group_chunk_id: group_chunk_id.object_id(), + storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + local_device_id, + cache: cache, + }) } pub fn header_block(&self) -> &Option { - &self.header_block + &self.cache.header_block } pub fn header_round(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.round()) + self.cache.header_block.as_ref().map_or(0, |b| b.round()) } pub fn header_height(&self) -> u64 { - self.header_block.as_ref().map_or(0, |b| b.height()) + self.cache.header_block.as_ref().map_or(0, |b| b.height()) } pub fn first_block(&self) -> &Option { - &self.first_block + &self.cache.first_block } pub fn prepares(&self) -> &HashMap { - &self.prepares + &self.cache.prepares } pub fn pre_commits(&self) -> &HashMap { - &self.pre_commits + &self.cache.pre_commits } pub fn group(&self) -> &Group { @@ -146,34 +157,37 @@ impl GroupStorage { } pub fn dec_state_id(&self) -> &Option { - &self.dec_state_id + &self.cache.dec_state_id } pub async fn get_block_by_height(&self, height: u64) -> BuckyResult { let header_height = self.header_height(); let block = match height.cmp(&header_height) { std::cmp::Ordering::Less => { - if height == self.first_block.as_ref().map_or(0, |b| b.height()) { - self.first_block.clone() + if height == self.cache.first_block.as_ref().map_or(0, |b| b.height()) { + self.cache.first_block.clone() } else { // find in storage let block_id = self.storage_engine.find_block_by_height(height).await?; Some(self.non_driver.get_block(&block_id, None).await?) } } - std::cmp::Ordering::Equal => self.header_block.clone(), + std::cmp::Ordering::Equal => self.cache.header_block.clone(), std::cmp::Ordering::Greater => { if height == header_height + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.height() == height) .or(self + .cache .prepares .iter() .find(|(_, block)| block.height() == height)) .map(|(_, block)| block.clone()) } else if height == header_height + 2 { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.height() == height) .map(|(_, block)| block.clone()) @@ -202,16 +216,17 @@ impl GroupStorage { // prepare update memory if let Some(prev_block_id) = prev_block_id { - if let Some(prev_block) = self.prepares.get(prev_block_id) { + if let Some(prev_block) = self.cache.prepares.get(prev_block_id) { new_pre_commit = Some((prev_block_id.clone(), prev_block.clone())); if let Some(prev_prev_block_id) = prev_block.prev_block_id() { - if let Some(prev_prev_block) = self.pre_commits.get(prev_prev_block_id) { + if let Some(prev_prev_block) = self.cache.pre_commits.get(prev_prev_block_id) { assert_eq!(block.height(), header_height + 3); assert_eq!(prev_prev_block.height(), header_height + 1); assert_eq!( prev_prev_block.prev_block_id(), - self.header_block + self.cache + .header_block .as_ref() .map(|b| b.block_id().object_id().clone()) .as_ref() @@ -220,7 +235,7 @@ impl GroupStorage { new_header = Some(prev_prev_block.clone()); let new_header_id = prev_prev_block.block_id().object_id(); - for (id, block) in self.prepares.iter() { + for (id, block) in self.cache.prepares.iter() { if block.prev_block_id().map(|prev_id| { assert_ne!(prev_id, prev_block_id); prev_id == new_header_id @@ -261,10 +276,11 @@ impl GroupStorage { new_header.height(), new_header.block_id().object_id(), new_header.result_state_id(), - self.header_block + self.cache + .header_block .as_ref() .map_or(&None, |b| b.result_state_id()), - self.first_block.as_ref().map_or(0, |b| b.height()), + self.cache.first_block.as_ref().map_or(0, |b| b.height()), ) .await?; @@ -277,11 +293,11 @@ impl GroupStorage { .collect(); let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { writer .push_proposals( finish_proposals.as_slice(), - Some((timestamp, self.finish_proposals.flip_timestamp)), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), ) .await?; } else { @@ -295,6 +311,7 @@ impl GroupStorage { // update memory if self + .cache .prepares .insert(block_id.object_id().clone(), block) .is_some() @@ -304,53 +321,60 @@ impl GroupStorage { match new_header { Some(new_header) => { - self.dec_state_id = new_header.result_state_id().clone(); + self.cache.dec_state_id = new_header.result_state_id().clone(); let new_pre_commit = new_pre_commit.expect("shoud got new pre-commit block"); - self.prepares.remove(&new_pre_commit.0); + self.cache.prepares.remove(&new_pre_commit.0); let mut removed_blocks = HashMap::from([new_pre_commit]); - std::mem::swap(&mut self.pre_commits, &mut removed_blocks); + std::mem::swap(&mut self.cache.pre_commits, &mut removed_blocks); let mut removed_blocks: Vec = removed_blocks.into_values().collect(); for id in remove_prepares.iter() { - removed_blocks.push(self.prepares.remove(id).unwrap()); + removed_blocks.push(self.cache.prepares.remove(id).unwrap()); } - if self.first_block.is_none() { - self.first_block = Some(new_header.clone()); + if self.cache.first_block.is_none() { + self.cache.first_block = Some(new_header.clone()); } let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MS + { let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.finish_proposals.over); - self.finish_proposals.flip_timestamp = timestamp; + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; } for proposal in new_header.proposals() { - let is_new = self.finish_proposals.adding.insert(proposal.proposal); + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); assert!(is_new); } - self.header_block = Some(new_header); - return Ok(Some((self.header_block.as_ref().unwrap(), removed_blocks))); + self.cache.header_block = Some(new_header); + return Ok(Some(( + self.cache.header_block.as_ref().unwrap(), + removed_blocks, + ))); } None => { if let Some(new_pre_commit) = new_pre_commit { assert!(remove_prepares.is_empty()); if self + .cache .pre_commits .insert(new_pre_commit.0, new_pre_commit.1) .is_some() { assert!(false); } - self.prepares + self.cache + .prepares .remove(&new_pre_commit.0) .expect("any block in pre-commit should be from prepare"); } @@ -361,21 +385,21 @@ impl GroupStorage { } pub fn last_vote_round(&self) -> u64 { - self.last_vote_round + self.cache.last_vote_round } pub async fn set_last_vote_round(&mut self, round: u64) -> BuckyResult<()> { - if round <= self.last_vote_round { + if round <= self.cache.last_vote_round { return Ok(()); } // storage let mut writer = self.storage_engine.create_writer().await?; writer - .set_last_vote_round(round, self.last_vote_round) + .set_last_vote_round(round, self.cache.last_vote_round) .await?; - self.last_vote_round = round; + self.cache.last_vote_round = round; Ok(()) } @@ -533,15 +557,16 @@ impl GroupStorage { } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { - if let Some(block) = self.header_block.as_ref() { + if let Some(block) = self.cache.header_block.as_ref() { if block.block_id().object_id() == block_id { return Ok(block.clone()); } } - self.prepares + self.cache + .prepares .get(block_id) - .or(self.pre_commits.get(block_id)) + .or(self.cache.pre_commits.get(block_id)) .ok_or(BuckyError::new(BuckyErrorCode::NotFound, "not found")) .map(|block| block.clone()) } @@ -553,20 +578,24 @@ impl GroupStorage { std::cmp::Ordering::Less => { return Err(BuckyError::new(BuckyErrorCode::NotFound, "not found")) } - std::cmp::Ordering::Equal => self.header_block.as_ref(), + std::cmp::Ordering::Equal => self.cache.header_block.as_ref(), std::cmp::Ordering::Greater => if round == header_round + 1 { - self.pre_commits + self.cache + .pre_commits .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .prepares .iter() .find(|(_, block)| block.round() == round)) } else { - self.prepares + self.cache + .prepares .iter() .find(|(_, block)| block.round() == round) .or(self + .cache .pre_commits .iter() .find(|(_, block)| block.round() == round)) @@ -615,10 +644,11 @@ impl GroupStorage { // find in storage let is_finished = self + .cache .finish_proposals .adding .get(proposal_id) - .or(self.finish_proposals.over.get(proposal_id)) + .or(self.cache.finish_proposals.over.get(proposal_id)) .is_some(); Ok(is_finished) } @@ -647,7 +677,7 @@ impl GroupStorage { &self, round: u64, ) -> (BuckyResult, Vec) { - if self.header_block.is_none() { + if self.cache.header_block.is_none() { return ( Err(BuckyError::new(BuckyErrorCode::NotFound, "not exist")), vec![], @@ -655,7 +685,7 @@ impl GroupStorage { } let mut blocks = vec![]; - let mut block = self.header_block.clone().unwrap(); + let mut block = self.cache.header_block.clone().unwrap(); let mut min_height = 1; let mut min_round = 1; let mut max_height = block.height(); From bd402f561431d3581adcdcedd4898e05d848b1e7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 15:20:55 +0800 Subject: [PATCH 484/553] update example for GroupState --- src/tests/group-example/src/main.rs | 479 +++++++++++++++++++--------- 1 file changed, 332 insertions(+), 147 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ffb45ccec..e7948f740 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -3,27 +3,28 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, }; use cyfs_stack::CyfsStack; -use Common::{ - create_stack, dummy, EXAMPLE_ADMINS, EXAMPLE_APP_NAME, EXAMPLE_DEC_APP_ID, EXAMPLE_GROUP, - EXAMPLE_RPATH, -}; +use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; + mod Common { - use std::sync::Arc; + use std::{fmt::format, io::ErrorKind, sync::Arc}; + use async_std::{fs, stream::StreamExt}; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, TypelessCoreObject, - UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, + SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -35,113 +36,109 @@ mod Common { CyfsStackKnownObjects, CyfsStackKnownObjectsInitMode, CyfsStackMetaParams, CyfsStackNOCParams, CyfsStackParams, }; - use rand::Rng; lazy_static::lazy_static! { - pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); + // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); - pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); + // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); + // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); + // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); } - fn create_members( + fn create_member( name_prefix: &str, - count: usize, - ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + index: usize, + port: u16, + ) -> ((People, PrivateKey), (Device, PrivateKey)) { log::info!("create members"); - let port_begin = rand::thread_rng().gen_range(30000u16..60000u16); - let mut members = vec![]; + let name = format!("{}-{}", name_prefix, index); + let private_key = PrivateKey::generate_rsa(1024).unwrap(); + let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); + let mut owner = + People::new(None, vec![], private_key.public(), None, Some(name), None).build(); + + let mut endpoint = Endpoint::default(); + endpoint.set_protocol(Protocol::Udp); + endpoint + .mut_addr() + .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); + endpoint.mut_addr().set_port(port); + endpoint.set_area(EndpointArea::Wan); + + let mut device = Device::new( + Some(owner.desc().object_id()), + UniqueId::create_with_random(), + vec![endpoint], + vec![], // TODO: 当前版本是否支持无SN? + vec![], + device_private_key.public(), + Area::default(), + DeviceCategory::PC, + ) + .build(); + + owner + .ood_list_mut() + .push(DeviceId::try_from(device.desc().object_id()).unwrap()); + + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); + let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); + let device_desc_hash = device.desc().raw_hash_value().unwrap(); + let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); + + let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = + async_std::task::block_on(async move { + let owner_desc_signature = signer + .sign( + owner_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); - for i in 0..count { - let name = format!("{}-{}", name_prefix, i); - let private_key = PrivateKey::generate_rsa(1024).unwrap(); - let device_private_key = PrivateKey::generate_rsa(1024).unwrap(); - let mut owner = - People::new(None, vec![], private_key.public(), None, Some(name), None).build(); - - let mut endpoint = Endpoint::default(); - endpoint.set_protocol(Protocol::Udp); - endpoint - .mut_addr() - .set_ip(IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 100, 120))); - endpoint.mut_addr().set_port(port_begin + i as u16); - endpoint.set_area(EndpointArea::Wan); - - let mut device = Device::new( - Some(owner.desc().object_id()), - UniqueId::create_with_random(), - vec![endpoint], - vec![], // TODO: 当前版本是否支持无SN? - vec![], - device_private_key.public(), - Area::default(), - DeviceCategory::PC, - ) - .build(); - - owner - .ood_list_mut() - .push(DeviceId::try_from(device.desc().object_id()).unwrap()); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - - let owner_desc_hash = owner.desc().raw_hash_value().unwrap(); - let owner_body_hash = owner.body().as_ref().unwrap().raw_hash_value().unwrap(); - let device_desc_hash = device.desc().raw_hash_value().unwrap(); - let device_body_hash = device.body().as_ref().unwrap().raw_hash_value().unwrap(); - - let (owner_desc_signature, owner_body_signature, desc_signature, body_signature) = - async_std::task::block_on(async move { - let owner_desc_signature = signer - .sign( - owner_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let owner_body_signature = signer - .sign( - owner_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), - ) - .await - .unwrap(); - - let desc_signature = signer - .sign( - device_desc_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - let body_signature = signer - .sign( - device_body_hash.as_slice(), - &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), - ) - .await - .unwrap(); - - ( - owner_desc_signature, - owner_body_signature, - desc_signature, - body_signature, + let owner_body_signature = signer + .sign( + owner_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), ) - }); + .await + .unwrap(); - device.signs_mut().set_desc_sign(desc_signature.clone()); - device.signs_mut().set_body_sign(body_signature); + let desc_signature = signer + .sign( + device_desc_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); - log::info!( + let body_signature = signer + .sign( + device_body_hash.as_slice(), + &cyfs_base::SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + + ( + owner_desc_signature, + owner_body_signature, + desc_signature, + body_signature, + ) + }); + + device.signs_mut().set_desc_sign(desc_signature.clone()); + device.signs_mut().set_body_sign(body_signature); + + log::info!( "people: {:?}/{:?}, device: {:?}, public-key: {:?}, private-key: {:?}, sign: {:?}, object: {:?}", owner.name().unwrap(), owner.desc().object_id(), @@ -152,12 +149,9 @@ mod Common { owner.body().as_ref().unwrap().raw_hash_value().unwrap().to_hex() ); - owner.signs_mut().set_desc_sign(owner_desc_signature); - owner.signs_mut().set_body_sign(owner_body_signature); - members.push(((owner, private_key), (device, device_private_key))); - } - - members + owner.signs_mut().set_desc_sign(owner_desc_signature); + owner.signs_mut().set_body_sign(owner_body_signature); + ((owner, private_key), (device, device_private_key)) } fn create_group( @@ -194,16 +188,167 @@ mod Common { group } + // (succ, not-found) + fn check_read_buf(file_path: &str, result: &std::io::Result>) -> (bool, bool) { + match result.as_ref() { + Ok(b) => { + if b.len() == 0 { + (false, true) + } else { + (true, false) + } + } + Err(err) if ErrorKind::NotFound == err.kind() => (false, true), + Err(err) => { + log::warn!("read file {} failed: {:?}", file_path, err); + (false, false) + } + } + } + + async fn init_member_from_dir( + save_path: &str, + name_prefix: &str, + count: usize, + ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + fs::create_dir_all(save_path) + .await + .expect(format!("create dir {} failed", save_path).as_str()); + + let min_port = 30217_u16; + + let mut members = vec![]; + + for i in 0..count { + let index = i + 1; + let people_desc_file_path = format!("{}/people-{}.desc", save_path, index); + let people_sec_file_path = format!("{}/people-{}.sec", save_path, index); + let device_desc_file_path = format!("{}/device-{}.desc", save_path, index); + let device_sec_file_path = format!("{}/device-{}.sec", save_path, index); + + let people_desc_r = fs::read(people_desc_file_path.clone()).await; + let people_sec_r = fs::read(people_sec_file_path.clone()).await; + let device_desc_r = fs::read(device_desc_file_path.clone()).await; + let device_sec_r = fs::read(device_sec_file_path.clone()).await; + + let (is_people_desc_succ, is_people_desc_not_found) = + check_read_buf(people_desc_file_path.as_str(), &people_desc_r); + let (is_people_sec_succ, is_people_sec_not_found) = + check_read_buf(people_sec_file_path.as_str(), &people_sec_r); + let (is_device_desc_succ, is_device_desc_not_found) = + check_read_buf(device_desc_file_path.as_str(), &device_desc_r); + let (is_device_sec_succ, is_device_sec_not_found) = + check_read_buf(device_sec_file_path.as_str(), &device_sec_r); + + if is_people_desc_succ + && is_people_sec_succ + && is_device_desc_succ + && is_device_sec_succ + { + // decode + let people_desc = People::raw_decode(people_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_desc_file_path).as_str()) + .0; + let people_sec = PrivateKey::raw_decode(people_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", people_sec_file_path).as_str()) + .0; + let device_desc = Device::raw_decode(device_desc_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_desc_file_path).as_str()) + .0; + let device_sec = PrivateKey::raw_decode(device_sec_r.unwrap().as_slice()) + .expect(format!("decode file {} failed", device_sec_file_path).as_str()) + .0; + members.push(((people_desc, people_sec), (device_desc, device_sec))); + } else if is_people_desc_not_found + && is_people_sec_not_found + && is_device_desc_not_found + && is_device_sec_not_found + { + // create & save + let member = create_member(name_prefix, index, min_port + i as u16); + fs::write( + people_desc_file_path.as_str(), + member.0 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", people_desc_file_path).as_str()); + fs::write(people_sec_file_path.as_str(), member.0 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", people_sec_file_path).as_str()); + fs::write( + device_desc_file_path.as_str(), + member.1 .0.to_vec().unwrap(), + ) + .await + .expect(format!("save file {} failed", device_desc_file_path).as_str()); + fs::write(device_sec_file_path.as_str(), member.1 .1.to_vec().unwrap()) + .await + .expect(format!("save file {} failed", device_sec_file_path).as_str()); + + members.push(member); + } else { + println!("read members failed!"); + std::process::exit(-1); + } + } + + members + } + + pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/admins", "admin", 4).await + } + + pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { + init_member_from_dir("./test-group/members", "member", 9).await + } + + pub async fn init_group( + admins: Vec<&People>, + members: Vec<&People>, + oods: Vec<&Device>, + ) -> Group { + fs::create_dir_all("./test-group") + .await + .expect("create dir ./test-group failed"); + + let read_group_r = fs::read("./test-group/group.desc").await; + match read_group_r { + Ok(buf) => { + if buf.len() > 0 { + return Group::raw_decode(buf.as_slice()) + .expect("decode ./test-group/group.desc failed") + .0; + } + } + Err(err) => { + if ErrorKind::NotFound != err.kind() { + println!("read group failed: {:?}", err); + std::process::exit(-1); + } + } + } + + let group = create_group(admins.get(0).unwrap(), admins, members, oods); + fs::write("./test-group/group.desc", group.to_vec().unwrap()) + .await + .expect("save file ./test-group/group.desc failed"); + group + } + fn init_stack_params( people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); - let mut admin_device: Vec = EXAMPLE_ADMINS.iter().map(|m| m.1 .0.clone()).collect(); - let mut member_device: Vec = - EXAMPLE_MEMBERS.iter().map(|m| m.1 .0.clone()).collect(); + let mut admin_device: Vec = admins.iter().map(|m| m.1.clone()).collect(); + let mut member_device: Vec = members.iter().map(|m| m.1.clone()).collect(); let known_device = vec![admin_device, member_device].concat(); let bdt_param = BdtStackParams { @@ -242,7 +387,7 @@ mod Common { mode: CyfsStackKnownObjectsInitMode::Sync, }; - for ((member, _), (device, _)) in EXAMPLE_ADMINS.iter() { + for (member, device) in admins.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -260,7 +405,7 @@ mod Common { )); } - for ((member, _), (device, _)) in EXAMPLE_MEMBERS.iter() { + for (member, device) in members.iter() { known_objects.list.push(NONObjectInfo::new( member.desc().object_id(), member.to_vec().unwrap(), @@ -279,17 +424,17 @@ mod Common { } known_objects.list.push(NONObjectInfo::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_GROUP.to_vec().unwrap(), + group.desc().object_id(), + group.to_vec().unwrap(), Some(Arc::new(AnyNamedObject::Standard(StandardObject::Group( - EXAMPLE_GROUP.clone(), + group.clone(), )))), )); - let dec_app_vec = EXAMPLE_DEC_APP.to_vec().unwrap(); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( - EXAMPLE_DEC_APP.desc().object_id(), + dec_app.desc().object_id(), dec_app_vec, Some(Arc::new(AnyNamedObject::Core(typeless))), )); @@ -301,8 +446,13 @@ mod Common { people: People, private_key: &PrivateKey, device: Device, + admins: Vec<(People, Device)>, + members: Vec<(People, Device)>, + group: Group, + dec_app: DecApp, ) -> CyfsStack { - let params = init_stack_params(people, private_key, device); + let params = + init_stack_params(people, private_key, device, admins, members, group, dec_app); log::info!("cyfs-stack.open"); @@ -316,10 +466,6 @@ mod Common { stack } - - pub fn dummy(people: People, device: Device) { - log::info!("common::dummy"); - } } mod Client { @@ -352,22 +498,21 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, + DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + GroupProposalObject, }; use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; use cyfs_stack::CyfsStack; - use crate::Common::EXAMPLE_DEC_APP_ID; - pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String) { + pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { let group_mgr = cyfs_stack.group_mgr(); group_mgr .register( - EXAMPLE_DEC_APP_ID.clone(), + dec_app_id.clone(), Box::new(GroupRPathDelegateFactory { local_name }), ) .await @@ -575,13 +720,14 @@ mod GroupDecService { } } -fn create_proposal(delta: u64, owner: ObjectId) -> GroupProposal { +fn create_proposal( + delta: u64, + owner: ObjectId, + group_id: ObjectId, + dec_id: ObjectId, +) -> GroupProposal { GroupProposal::create( - GroupRPath::new( - EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id().clone(), - EXAMPLE_RPATH.clone(), - ), + GroupRPath::new(group_id, dec_id, EXAMPLE_RPATH.to_string()), "add".to_string(), Some(Vec::from(delta.to_be_bytes())), None, @@ -614,23 +760,57 @@ async fn main_run() { log::info!("will open stacks"); + let admins = init_admins().await; + let members = init_members().await; + let group = init_group( + admins.iter().map(|m| &m.0 .0).collect(), + members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| &m.1 .0).collect(), + ) + .await; + let group_id = group.desc().object_id(); + let dec_app = DecApp::create( + admins.get(0).unwrap().0 .0.desc().object_id(), + EXAMPLE_APP_NAME.as_str(), + ); + let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); + let mut admin_stacks: Vec = vec![]; - for ((admin, _), (device, private_key)) in EXAMPLE_ADMINS.iter() { - // dummy(admin.clone(), device.clone()); - let cyfs_stack = create_stack(admin.clone(), private_key, device.clone()).await; + for ((admin, _), (device, private_key)) in admins.iter() { + let cyfs_stack = create_stack( + admin.clone(), + private_key, + device.clone(), + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + group.clone(), + dec_app.clone(), + ) + .await; admin_stacks.push(cyfs_stack); } for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = EXAMPLE_ADMINS.get(i).unwrap(); - DecService::run(&stack, admin.name().unwrap().to_string()).await; + let ((admin, _), _) = admins.get(i).unwrap(); + DecService::run( + &stack, + admin.name().unwrap().to_string(), + dec_app_id.clone(), + ) + .await; let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group.desc().object_id(), + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -647,14 +827,19 @@ async fn main_run() { let PROPOSAL_COUNT = 1000usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let owner = &EXAMPLE_ADMINS.get(i % EXAMPLE_ADMINS.len()).unwrap().0 .0; - let proposal = create_proposal(i as u64, owner.desc().object_id()); + let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let proposal = create_proposal( + i as u64, + owner.desc().object_id(), + group_id, + dec_app_id.object_id().clone(), + ); let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) @@ -676,7 +861,7 @@ async fn main_run() { zone: None, zone_category: DeviceZoneCategory::CurrentDevice, }, - dec: EXAMPLE_DEC_APP_ID.object_id().clone(), + dec: dec_app_id.object_id().clone(), verified: None, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), @@ -700,8 +885,8 @@ async fn main_run() { let control = stack .group_mgr() .find_rpath_control( - &EXAMPLE_GROUP.desc().object_id(), - EXAMPLE_DEC_APP_ID.object_id(), + &group_id, + dec_app_id.object_id(), &EXAMPLE_RPATH, IsCreateRPath::Yes(None), ) From fac8c6774839c82d880ae74ea1e51748caeb66a2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 17:36:21 +0800 Subject: [PATCH 485/553] fix: path error --- .../src/statepath/group_statepath.rs | 13 ++++++++-- src/tests/group-example/src/main.rs | 26 +++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index eade0f9e4..280fb6948 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -39,51 +39,60 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { - dec_state: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), - link: Self::join(&[rpath.as_str(), GROUP_STATE_PATH_LINK]), + dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), + link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_GROUP_BLOB, ]), last_vote_round: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), range: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_RANGE, ]), prepares: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PREPARES, ]), pre_commits: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_PRE_COMMITS, ]), finish_proposals: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, ]), flip_time: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_FLIP_TIME, ]), recycle: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, GROUP_STATE_PATH_RECYCLE, ]), adding: Self::join(&[ + "", rpath.as_str(), GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_FINISH_PROPOSALS, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e7948f740..e29b1be6d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -337,13 +337,13 @@ mod Common { } fn init_stack_params( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -443,13 +443,13 @@ mod Common { } pub async fn create_stack( - people: People, + people: &People, private_key: &PrivateKey, - device: Device, + device: &Device, admins: Vec<(People, Device)>, members: Vec<(People, Device)>, - group: Group, - dec_app: DecApp, + group: &Group, + dec_app: &DecApp, ) -> CyfsStack { let params = init_stack_params(people, private_key, device, admins, members, group, dec_app); @@ -778,9 +778,9 @@ async fn main_run() { let mut admin_stacks: Vec = vec![]; for ((admin, _), (device, private_key)) in admins.iter() { let cyfs_stack = create_stack( - admin.clone(), + admin, private_key, - device.clone(), + device, admins .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) @@ -789,8 +789,8 @@ async fn main_run() { .iter() .map(|m| (m.0 .0.clone(), m.1 .0.clone())) .collect(), - group.clone(), - dec_app.clone(), + &group, + &dec_app, ) .await; admin_stacks.push(cyfs_stack); @@ -898,7 +898,7 @@ async fn main_run() { }); if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(200)).await; + async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } From d9187f52ef38a042e53cbae00e98832108fe6c27 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 18:34:11 +0800 Subject: [PATCH 486/553] fix: commit storage --- src/component/cyfs-group/src/storage/group_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 5ad19ea15..30fc08cad 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -398,6 +398,7 @@ impl GroupStorage { writer .set_last_vote_round(round, self.cache.last_vote_round) .await?; + writer.commit().await?; self.cache.last_vote_round = round; From ebba8962bd2232dd1d4752500cfcdf4ef7a9ff62 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 487/553] fix: type of pre-commits --- .../cyfs-group/src/dec/group_manager.rs | 21 ++++++++++--------- .../engine/storage_engine_group_state.rs | 20 +++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5ecfcdba2..7ba376368 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,16 +289,17 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - let rpath = header_block.r_path(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::StateChangeNotify(header_block, qc_block), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = header_block.r_path(); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::StateChangeNotify(header_block, qc_block), + // remote, + // ) + // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index ee429a78f..c6acb7b52 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,7 +5,6 @@ use cyfs_base::{ ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -213,9 +212,11 @@ impl StorageEngineGroupStateWriter { .await?; } - self.op_env - .insert_with_path(self.state_path.pre_commits(), block_id) - .await + let is_changed = self.op_env + .insert(self.state_path.pre_commits(), block_id) + .await?; + assert!(is_changed); + Ok(()) } async fn push_commit_inner( @@ -469,7 +470,16 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.prepare_map_id.is_none(), ) .await?; - self.op_env.commit().await.map(|_| ()) + self.op_env.commit().await.map_or_else( + |err| { + if err.code() == BuckyErrorCode::AlreadyExists { + Ok(()) + } else { + Err(err) + } + }, + |_| Ok(()), + ) } } From 055e3c5dc401cbcf51d9923ac670e8a892d93f6d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:42:12 +0800 Subject: [PATCH 488/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e29b1be6d..316630f6a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: None, + isolate: Some(device.desc().object_id()), sync_service: false, shared_stack: false, }, From 79a8bcefdaad1a3ba07bb1994df3ee855f6c38e2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Feb 2023 19:49:08 +0800 Subject: [PATCH 489/553] isolate for test example --- src/tests/group-example/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 316630f6a..d69fcae2d 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -363,7 +363,7 @@ mod Common { let stack_param = CyfsStackParams { config: CyfsStackConfigParams { - isolate: Some(device.desc().object_id()), + isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: false, }, From 00a37a0f1f5418a88e2f633ee8ce7085d38fe47f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 21 Feb 2023 19:52:57 +0800 Subject: [PATCH 490/553] fix: the round for the first block when restart --- src/component/cyfs-core/src/coreobj.rs | 1 + .../src/group/group_quorum_certificate.rs | 144 ++++++++++++++++++ src/component/cyfs-core/src/group/mod.rs | 2 + .../src/consensus/hotstuff/hotstuff.rs | 60 +++++++- .../cyfs-group/src/dec/group_manager.rs | 34 +++-- .../cyfs-group/src/network/non_driver.rs | 30 +++- .../cyfs-group/src/statepath/design.md | 1 + .../src/statepath/group_statepath.rs | 16 +- .../src/storage/engine/storage_engine.rs | 5 +- .../engine/storage_engine_group_state.rs | 130 ++++++++++++---- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 136 ++++++++++++----- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- src/tests/group-example/src/main.rs | 24 +-- 14 files changed, 493 insertions(+), 100 deletions(-) create mode 100644 src/component/cyfs-core/src/group/group_quorum_certificate.rs diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 724f0debb..30bf0e013 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupRPathStatus = 703, GroupAction = 704, + GroupQuorumCertificate = 705, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs new file mode 100644 index 000000000..7c3ad77fc --- /dev/null +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -0,0 +1,144 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, DescContent, EmptyBodyContent, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBuilder, NamedObjectId, RawDecode, RawEncode, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_RAW, +}; + +use crate::{CoreObjectType, HotstuffBlockQC, HotstuffTimeout}; + +#[derive(Clone)] +pub enum GroupQuorumCertificateDescContent { + QC(HotstuffBlockQC), + TC(HotstuffTimeout), +} + +impl DescContent for GroupQuorumCertificateDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupQuorumCertificate as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupQuorumCertificateDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +pub type GroupQuorumCertificateType = + NamedObjType; +pub type GroupQuorumCertificateBuilder = + NamedObjectBuilder; + +pub type GroupQuorumCertificateId = NamedObjectId; +pub type GroupQuorumCertificate = NamedObjectBase; + +pub trait GroupQuorumCertificateObject { + fn quorum_round(&self) -> u64; +} + +impl GroupQuorumCertificateObject for GroupQuorumCertificate { + fn quorum_round(&self) -> u64 { + match self.desc().content() { + GroupQuorumCertificateDescContent::QC(qc) => qc.round, + GroupQuorumCertificateDescContent::TC(tc) => tc.round, + } + } +} + +impl RawEncode for GroupQuorumCertificateDescContent { + fn raw_measure( + &self, + purpose: &Option, + ) -> cyfs_base::BuckyResult { + let len = match self { + GroupQuorumCertificateDescContent::QC(qc) => qc.raw_measure(purpose)?, + GroupQuorumCertificateDescContent::TC(tc) => tc.raw_measure(purpose)?, + }; + + Ok(len + 1) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> cyfs_base::BuckyResult<&'a mut [u8]> { + match self { + GroupQuorumCertificateDescContent::QC(qc) => { + buf[0] = 0; + let buf = &mut buf[1..]; + qc.raw_encode(buf, purpose) + } + GroupQuorumCertificateDescContent::TC(tc) => { + buf[0] = 1; + let buf = &mut buf[1..]; + tc.raw_encode(buf, purpose) + } + } + } +} + +impl<'de> RawDecode<'de> for GroupQuorumCertificateDescContent { + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let obj_type = buf[0]; + let buf = &buf[1..]; + match obj_type { + 0 => { + let (qc, remain) = HotstuffBlockQC::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::QC(qc), remain)) + } + 1 => { + let (qc, remain) = HotstuffTimeout::raw_decode(buf)?; + Ok((GroupQuorumCertificateDescContent::TC(qc), remain)) + } + _ => Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown qc")), + } + } +} + +impl From for GroupQuorumCertificate { + fn from(qc: HotstuffBlockQC) -> Self { + let desc = GroupQuorumCertificateDescContent::QC(qc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl From for GroupQuorumCertificate { + fn from(tc: HotstuffTimeout) -> Self { + let desc = GroupQuorumCertificateDescContent::TC(tc); + GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::QC(qc) => Ok(qc), + GroupQuorumCertificateDescContent::TC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is tc, expect qc")) + } + } + } +} + +impl TryInto for GroupQuorumCertificate { + type Error = BuckyError; + + fn try_into(self) -> Result { + match self.into_desc().into_content() { + GroupQuorumCertificateDescContent::TC(tc) => Ok(tc), + GroupQuorumCertificateDescContent::QC(_) => { + Err(BuckyError::new(BuckyErrorCode::Unmatch, "is qc, expect tc")) + } + } + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4c315c090..c153ab1ba 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,6 +1,7 @@ mod group_consensus_block; mod group_proposal; mod group_proposal_decide_param; +mod group_quorum_certificate; mod group_rpath; mod group_rpath_status; mod group_update_group_proposal_param; @@ -8,6 +9,7 @@ mod group_update_group_proposal_param; pub use group_consensus_block::*; pub use group_proposal::*; pub use group_proposal_decide_param::*; +pub use group_quorum_certificate::*; pub use group_rpath::*; pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e89498b83..7868a7f90 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,7 +9,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; @@ -238,11 +238,36 @@ impl HotstuffRunner { rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); + let last_qc = store.last_qc(); + let (tc, qc) = last_qc + .as_ref() + .map_or((None, None), |qc| { + match qc.desc().content() { + cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), + cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), + } + }); - let round = store - .last_vote_round() - .max(max_round_block.as_ref().map_or(1, |block| block.round())); - let high_qc = max_round_block.map_or(None, |block| block.qc().clone()); + let last_vote_round = store + .last_vote_round(); + let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); + let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); + + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" + , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + + let max_round_qc_round = max_round_block + .as_ref() + .map_or(0, |block| + block.qc().as_ref().map_or(0, |qc| qc.round) + ); + let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); + let high_qc = if max_round_qc_round >= last_qc_round { + max_round_block.map_or(None, |b| b.qc().clone()) + } else { + qc + }; let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); @@ -277,7 +302,7 @@ impl HotstuffRunner { rpath, proposal_consumer, rx_proposal_waiter: None, - tc: None, + tc, state_pusher, tx_block_gen, rx_block_gen, @@ -627,6 +652,16 @@ impl HotstuffRunner { * 验证过的块执行这个函数 */ + if let Err(err) = self.non_driver.put_block(block).await { + if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + log::warn!( + "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", + self, block.block_id(), block.height(), block.round() + ); + return Err(err); + } + } + log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", self, block.block_id(), block.height(), block.round() @@ -1072,6 +1107,10 @@ impl HotstuffRunner { let qc_round = qc.round; let qc_prev_block_id = qc.prev_block_id; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); + + self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.process_qc(&Some(qc)).await; let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { @@ -1211,10 +1250,14 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", @@ -1324,6 +1367,10 @@ impl HotstuffRunner { err })?; + log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + + self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1814,6 +1861,7 @@ impl HotstuffRunner { match max_round_block { Some(max_round_block) if max_round_block.owner() == &self.local_id + && max_round_block.round() == self.round && latest_group.is_ok() && last_group.is_ok() && last_group diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7ba376368..70fb10ba6 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -302,22 +302,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: 暂时不实现 + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.r_path(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); @@ -397,6 +398,7 @@ impl GroupManager { return Err(e); } if let BuckyErrorCode::NotFound = e.code() { + log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); None } else { return Err(e); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4212a0355..979451b79 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,7 +7,9 @@ use cyfs_base::{ TypelessCoreObject, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, +}; use cyfs_lib::NONObjectInfo; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -106,6 +108,32 @@ impl NONDriverHelper { Ok(()) } + pub async fn get_qc( + &self, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let obj = self.get_object(object_id, from).await?; + let (block, remain) = GroupQuorumCertificate::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + Ok(block) + } + + pub async fn put_qc(&self, qc: &GroupQuorumCertificate) -> BuckyResult<()> { + let buf = qc.to_vec()?; + let block_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + + let qc = NONObjectInfo { + object_id: qc.desc().object_id(), + object_raw: qc.to_vec()?, + object: Some(block_any), + }; + self.put_object(qc).await?; + Ok(()) + } + pub async fn get_proposal( &self, object_id: &ObjectId, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 70a61e428..cb964e066 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -23,6 +23,7 @@ | | |--${user-id} | | |--xxx | |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 280fb6948..0e6a887b0 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -5,6 +5,7 @@ pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; +pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -23,10 +24,12 @@ lazy_static::lazy_static! { pub struct GroupStatePath { rpath: String, + root: String, dec_state: String, link: String, group_blob: String, last_vote_round: String, + last_qc: String, range: String, prepares: String, pre_commits: String, @@ -39,6 +42,7 @@ pub struct GroupStatePath { impl GroupStatePath { pub fn new(rpath: String) -> Self { Self { + root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), group_blob: Self::join(&[ @@ -53,6 +57,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_VOTE_ROUNDS, ]), + last_qc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_QC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -107,7 +117,7 @@ impl GroupStatePath { } pub fn root(&self) -> &str { - self.rpath.as_str() + self.root.as_str() } pub fn dec_state(&self) -> &str { @@ -126,6 +136,10 @@ impl GroupStatePath { self.last_vote_round.as_str() } + pub fn last_qc(&self) -> &str { + self.last_qc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index 735277a3a..aebf6fb96 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,6 +12,7 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 + pub last_qc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -33,6 +34,7 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, + last_qc: None, } } } @@ -58,6 +60,7 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index c6acb7b52..2b61dbc47 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, }; use crate::{ @@ -27,26 +27,35 @@ impl StorageEngineGroupState { non_driver: &NONDriverHelper, state_path: &GroupStatePath, ) -> BuckyResult { - let op_env = state_mgr.create_op_env(ACCESS)?; - - let dec_state_id = op_env.get_by_path(state_path.dec_state()).await?; - - let last_vote_round = op_env - .get_by_path(state_path.last_vote_round()) - .await? - .map(|id| parse_u64_obj(&id)); + let op_env = state_mgr.create_op_env(ACCESS).map_err(|err| { + log::warn!("create_op_env failed {:?}", err); + err + })?; + + let dec_state_id = op_env.get_by_path(state_path.dec_state()).await; + let dec_state_id = map_not_found_option_to_option(dec_state_id)?; + + let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; + let last_vote_round = + map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; + let last_qc = map_not_found_option_to_option(last_qc)?; + let last_qc = match last_qc.as_ref() { + Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + None => None, + }; let mut first_header_block_ids: Vec = vec![]; - let commit_range = op_env - .get_by_path(state_path.range()) - .await? - .map(|id| parse_range_obj(&id)); + let commit_range = op_env.get_by_path(state_path.range()).await; + let commit_range = + map_not_found_option_to_option(commit_range)?.map(|id| parse_range_obj(&id)); let commit_block = match commit_range { Some((first_height, header_height)) => { let first_block_id = op_env .get_by_path(state_path.commit_height(first_height).as_str()) - .await? - .expect("first block is lost"); + .await; + let first_block_id = + map_not_found_option_to_option(first_block_id)?.expect("first block is lost"); first_header_block_ids.push(first_block_id); if header_height == first_height { @@ -54,7 +63,8 @@ impl StorageEngineGroupState { } else { let header_block_id = op_env .get_by_path(state_path.commit_height(header_height).as_str()) - .await? + .await; + let header_block_id = map_not_found_option_to_option(header_block_id)? .expect("first block is lost"); first_header_block_ids.push(header_block_id); Some((first_block_id, header_block_id)) @@ -64,13 +74,27 @@ impl StorageEngineGroupState { }; let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + if prepare_block_ids.len() == 0 && commit_range.is_none() { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "not found in storage", + )); + } + let pre_commit_block_ids = load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; - let flip_timestamp = op_env - .get_by_path(state_path.flip_time()) - .await? - .map_or(0, |id| parse_u64_obj(&id)); + let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; + let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { + let n = parse_u64_obj(&id); + // log::debug!( + // "load flip timestamp {}/{} -> {}", + // id, + // id.to_hex().unwrap(), + // n + // ); + n + }); let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; @@ -82,15 +106,18 @@ impl StorageEngineGroupState { ] .concat(); - let load_blocks = futures::future::join_all( - load_block_ids - .iter() - .map(|id| non_driver.get_block(id, None)), - ) + let load_blocks = futures::future::join_all(load_block_ids.iter().map(|id| async { + let id = id.clone(); + non_driver.get_block(&id, None).await.map_err(|err| { + log::warn!("get block {} failed {:?}", id, err); + err + }) + })) .await; let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); + cache.last_qc = last_qc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -212,7 +239,8 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self.op_env + let is_changed = self + .op_env .insert(self.state_path.pre_commits(), block_id) .await?; assert!(is_changed); @@ -326,6 +354,15 @@ impl StorageEngineGroupStateWriter { let timestamp_obj = make_u64_obj(timestamp); if prev_timestamp != 0 { let prev_timestamp_obj = make_u64_obj(prev_timestamp); + // log::debug!( + // "will update flip-time from {} -> {}/{} to {} -> {}/{}", + // prev_timestamp, + // prev_timestamp_obj, + // prev_timestamp_obj.to_hex().unwrap(), + // timestamp, + // timestamp_obj, + // timestamp_obj.to_hex().unwrap(), + // ); let prev_value = self .op_env .set_with_path( @@ -337,6 +374,7 @@ impl StorageEngineGroupStateWriter { .await?; assert_eq!(prev_value.unwrap(), prev_timestamp_obj); } else { + // log::debug!("will update flip-time from None to {}", timestamp); self.op_env .insert_with_key( self.state_path.finish_proposals(), @@ -395,6 +433,13 @@ impl StorageEngineGroupStateWriter { Ok(()) } } + + async fn save_last_qc_inner(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_qc(), qc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -458,6 +503,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_qc_inner(qc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; @@ -522,6 +573,7 @@ async fn load_object_ids_with_path( let content = match op_env.list(full_path).await { Ok(content) => content, Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); if err.code() == BuckyErrorCode::NotFound { return Ok(vec![]); } else { @@ -546,3 +598,29 @@ async fn load_object_ids_with_path( Ok(object_ids) } + +fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { + match r { + Ok(t) => Ok(Some(t)), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} + +fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult> { + match r { + Ok(t) => Ok(t), + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + Ok(None) + } else { + Err(err) + } + } + } +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index b944d3735..79491b186 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -192,6 +192,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 30fc08cad..3f9fc9910 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -8,7 +8,10 @@ use cyfs_base::{ ObjectDesc, ObjectId, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupQuorumCertificateObject, HotstuffTimeout, +}; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ @@ -20,7 +23,7 @@ use super::{ StorageEngine, }; -const PROPOSAL_MAX_TIMEOUT_AS_MS: u64 = PROPOSAL_MAX_TIMEOUT.as_millis() as u64; +const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() as u64; pub enum BlockLinkState { Expired, @@ -96,16 +99,32 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver.get_group(group_id, None, None).await?; + let group = non_driver + .get_group(group_id, None, None) + .await + .map_err(|err| { + log::warn!("get group {} from noc failed {:?}", group_id, err); + err + })?; let group_chunk = ChunkMeta::from(&group); let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) - .await? + .await + .map_err(|err| { + log::warn!("load root state for group {} failed {:?}", group_id, err); + err + })? .expect("create group state failed."); - let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let dec_group_state = group_state + .get_dec_root_manager(dec_id, true) + .await + .map_err(|err| { + log::warn!("get root state manager for dec {} failed {:?}", dec_id, err); + err + })?; let state_path = GroupStatePath::new(rpath.to_string()); let cache = @@ -120,7 +139,7 @@ impl GroupStorage { group_chunk_id: group_chunk_id.object_id(), storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, - cache: cache, + cache, }) } @@ -286,24 +305,33 @@ impl GroupStorage { writer.remove_prepares(remove_prepares.as_slice()).await?; - let finish_proposals: Vec = new_header - .proposals() - .iter() - .map(|p| p.proposal.clone()) - .collect(); - - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp > PROPOSAL_MAX_TIMEOUT_AS_MS { - writer - .push_proposals( - finish_proposals.as_slice(), - Some((timestamp, self.cache.finish_proposals.flip_timestamp)), - ) - .await?; - } else { - writer - .push_proposals(finish_proposals.as_slice(), None) - .await?; + if new_header.proposals().len() > 0 { + let finish_proposals: Vec = new_header + .proposals() + .iter() + .map(|p| p.proposal.clone()) + .collect(); + + let timestamp = new_header.named_object().desc().create_time(); + // log::debug!( + // "push proposals storage flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + writer + .push_proposals( + finish_proposals.as_slice(), + Some((timestamp, self.cache.finish_proposals.flip_timestamp)), + ) + .await?; + } else { + writer + .push_proposals(finish_proposals.as_slice(), None) + .await?; + } } } @@ -340,19 +368,28 @@ impl GroupStorage { self.cache.first_block = Some(new_header.clone()); } - let timestamp = new_header.named_object().desc().create_time(); - if timestamp - self.cache.finish_proposals.flip_timestamp - > PROPOSAL_MAX_TIMEOUT_AS_MS - { - let mut new_over = HashSet::new(); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); - std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); - self.cache.finish_proposals.flip_timestamp = timestamp; - } + if new_header.proposals().len() > 0 { + let timestamp = new_header.named_object().desc().create_time(); + + // log::debug!( + // "push proposals flip-time from {} to {}", + // self.cache.finish_proposals.flip_timestamp, + // timestamp + // ); + + if timestamp - self.cache.finish_proposals.flip_timestamp + > PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC + { + let mut new_over = HashSet::new(); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.adding); + std::mem::swap(&mut new_over, &mut self.cache.finish_proposals.over); + self.cache.finish_proposals.flip_timestamp = timestamp; + } - for proposal in new_header.proposals() { - let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); - assert!(is_new); + for proposal in new_header.proposals() { + let is_new = self.cache.finish_proposals.adding.insert(proposal.proposal); + assert!(is_new); + } } self.cache.header_block = Some(new_header); @@ -405,6 +442,33 @@ impl GroupStorage { Ok(()) } + pub fn last_qc(&self) -> &Option { + &self.cache.last_qc + } + + pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { + let quorum_round = qc.quorum_round(); + if quorum_round < self.cache.last_vote_round + || quorum_round + <= self + .cache + .last_qc + .as_ref() + .map_or(0, |qc| qc.quorum_round()) + { + return Ok(()); + } + + self.non_driver.put_qc(&qc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_qc(&qc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_qc = Some(qc); + Ok(()) + } + pub async fn block_linked(&self, block: &GroupConsensusBlock) -> BuckyResult { log::debug!( "[group storage] {} block_linked {} step1", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9414cda7c..fcb0dd6da 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, @@ -55,6 +55,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { } async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let access = AccessString::full(); + log::debug!("put object {} with access {}", obj.object_id, access); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { @@ -76,7 +78,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { flags: 0, }, object: obj, - access: None, // TODO access + access: Some(AccessString::full()), // TODO access }) .await .map(|_| ()) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d69fcae2d..b5b6f4ce4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,7 +1,8 @@ use std::{clone, sync::Arc, time::Duration}; use cyfs_base::{ - AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group::IsCreateRPath; @@ -23,8 +24,8 @@ mod Common { AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, - TypelessCoreObject, UniqueId, SIGNATURE_SOURCE_REFINDEX_OWNER, - SIGNATURE_SOURCE_REFINDEX_SELF, + TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; @@ -210,13 +211,12 @@ mod Common { save_path: &str, name_prefix: &str, count: usize, + min_port: u16, ) -> Vec<((People, PrivateKey), (Device, PrivateKey))> { fs::create_dir_all(save_path) .await .expect(format!("create dir {} failed", save_path).as_str()); - let min_port = 30217_u16; - let mut members = vec![]; for i in 0..count { @@ -296,11 +296,13 @@ mod Common { } pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/admins", "admin", 4).await + let min_port = 30217_u16; + init_member_from_dir("./test-group/admins", "admin", 4, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { - init_member_from_dir("./test-group/members", "member", 9).await + let min_port = 31217_u16; + init_member_from_dir("./test-group/members", "member", 9, min_port).await } pub async fn init_group( @@ -369,7 +371,7 @@ mod Common { }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { - bdt_listeners: vec![], + bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], tcp_listeners: vec![], ws_listener: None, }, @@ -868,7 +870,7 @@ async fn main_run() { storage_category: NamedObjectStorageCategory::Storage, context: None, last_access_rpath: None, - access_string: None, + access_string: Some(AccessString::full().value()), }; noc.put_object(&req).await; proposals.push(proposal); @@ -878,8 +880,8 @@ async fn main_run() { log::info!("proposals prepared."); - for i in 0..(PROPOSAL_COUNT - 1) { - let proposal = proposals.get(i).unwrap().clone(); + for i in 1..PROPOSAL_COUNT { + let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let control = stack From b8fdfe34d05fbd0bcf2a722e17d34b5a5c775488 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 16:04:16 +0800 Subject: [PATCH 491/553] fix: first block with tc --- .../src/consensus/hotstuff/hotstuff.rs | 75 ++++++++++--------- .../src/statepath/group_statepath.rs | 12 +++ .../src/storage/engine/storage_engine.rs | 9 ++- .../engine/storage_engine_group_state.rs | 35 ++++++++- .../src/storage/engine/storage_engine_mock.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 41 +++++++--- src/tests/group-example/src/main.rs | 2 + 7 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7868a7f90..a2a5e8f70 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -239,36 +239,30 @@ impl HotstuffRunner { ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); - let (tc, qc) = last_qc - .as_ref() - .map_or((None, None), |qc| { - match qc.desc().content() { - cyfs_core::GroupQuorumCertificateDescContent::QC(qc) => (None, Some(qc.clone())), - cyfs_core::GroupQuorumCertificateDescContent::TC(tc) => (Some(tc.clone()), None), - } - }); + let last_tc = store.last_tc(); let last_vote_round = store .last_vote_round(); - let quorum_round = last_qc.as_ref().map_or(0, |qc| qc.quorum_round()); - let max_round_block_round = max_round_block.as_ref().map_or(0, |block| block.round()); + let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); + let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); + let quorum_round = block_quorum_round.max(timeout_quorum_round); + let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}, max_round_block_round = {}" - , rpath, local_device_id, round, last_vote_round, quorum_round, max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" + , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); - let max_round_qc_round = max_round_block - .as_ref() - .map_or(0, |block| - block.qc().as_ref().map_or(0, |qc| qc.round) - ); - let last_qc_round = qc.as_ref().map_or(0, |qc| qc.round); - let high_qc = if max_round_qc_round >= last_qc_round { + let high_qc = if max_round_qc_round >= block_quorum_round { max_round_block.map_or(None, |b| b.qc().clone()) } else { - qc + last_qc.clone() }; + let tc = last_tc.clone(); + let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); let max_height = store.header_height() + 2; @@ -954,18 +948,22 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - && qc_round - >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; if !is_valid_round { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {}", + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for invalid round {}, qc-round {}, tc-round {:?}", self, block.block_id(), block.round(), qc_round, - block.tc().as_ref().map_or(0, |tc| tc.votes.iter().map(|v| v.high_qc_round).max().unwrap())); + block.tc().as_ref().map_or((0, 0), |tc| { + let qc_round = tc.votes.iter().map(|v| v.high_qc_round).max().unwrap(); + (tc.round, qc_round) + })); return None; } @@ -1109,7 +1107,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, qc_round); - self.store.save_qc(GroupQuorumCertificate::from(qc.clone())).await?; + self.store.save_qc(&qc).await?; self.process_qc(&Some(qc)).await; @@ -1125,7 +1123,7 @@ impl HotstuffRunner { })?; if self.local_device_id == new_leader { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } Ok(()) } @@ -1251,12 +1249,12 @@ impl HotstuffRunner { max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( @@ -1367,9 +1365,9 @@ impl HotstuffRunner { err })?; - log::debug!("[hotstuff] local: {:?}, save-qc round {}", self, tc.round); + log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - self.store.save_qc(GroupQuorumCertificate::from(tc.clone())).await?; + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1535,7 +1533,7 @@ impl HotstuffRunner { self.remove_pending_proposals(remove_proposals).await; if self - .try_wait_proposals(executed_proposals.as_slice(), &prev_block) + .try_wait_proposals(executed_proposals.len(), &prev_block) .await { log::debug!( @@ -1739,12 +1737,12 @@ impl HotstuffRunner { async fn try_wait_proposals( &mut self, - executed_proposals: &[(GroupProposal, ExecuteResult)], + proposal_count: usize, pre_block: &Option, ) -> bool { // empty block, qc only, it's unuseful when no block to qc let mut will_wait_proposals = false; - if executed_proposals.len() == 0 { + if proposal_count == 0 { match pre_block.as_ref() { None => { log::warn!( @@ -1814,14 +1812,17 @@ impl HotstuffRunner { assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); - let tc = self.tc.as_ref().map_or(None, |tc| { + self.generate_block(self.with_tc()).await + } + + fn with_tc(&self) -> Option { + self.tc.as_ref().map_or(None, |tc| { if tc.round + 1 == self.round { Some(tc.clone()) } else { None } - }); - self.generate_block(tc).await + }) } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { @@ -1876,7 +1877,7 @@ impl HotstuffRunner { ); } _ => { - self.generate_block(None).await; + self.generate_block(self.with_tc()).await; } } } diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0e6a887b0..72f48e601 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -6,6 +6,7 @@ pub const GROUP_STATE_PATH_LINK: &str = ".link"; pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; +pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; @@ -30,6 +31,7 @@ pub struct GroupStatePath { group_blob: String, last_vote_round: String, last_qc: String, + last_tc: String, range: String, prepares: String, pre_commits: String, @@ -63,6 +65,12 @@ impl GroupStatePath { GROUP_STATE_PATH_LINK, GROUP_STATE_PATH_LAST_QC, ]), + last_tc: Self::join(&[ + "", + rpath.as_str(), + GROUP_STATE_PATH_LINK, + GROUP_STATE_PATH_LAST_TC, + ]), range: Self::join(&[ "", rpath.as_str(), @@ -140,6 +148,10 @@ impl GroupStatePath { self.last_qc.as_str() } + pub fn last_tc(&self) -> &str { + self.last_tc.as_str() + } + pub fn range(&self) -> &str { self.range.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index aebf6fb96..c4803d6ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupQuorumCertificate}; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { pub flip_timestamp: u64, @@ -12,7 +12,8 @@ pub struct FinishProposalMgr { pub struct StorageCacheInfo { pub dec_state_id: Option, // commited/header state id pub last_vote_round: u64, // 参与投票的最后一个轮次 - pub last_qc: Option, + pub last_qc: Option, + pub last_tc: Option, pub header_block: Option, pub first_block: Option, pub prepares: HashMap, @@ -25,6 +26,8 @@ impl StorageCacheInfo { Self { dec_state_id: init_state_id, last_vote_round: 0, + last_qc: None, + last_tc: None, header_block: None, first_block: None, prepares: HashMap::new(), @@ -34,7 +37,6 @@ impl StorageCacheInfo { over: HashSet::new(), adding: HashSet::new(), }, - last_qc: None, } } } @@ -61,6 +63,7 @@ pub trait StorageWriter: Send + Sync { async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 2b61dbc47..b3a01fd60 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, RawConvertTo, + ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; +use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -38,10 +39,26 @@ impl StorageEngineGroupState { let last_vote_round = op_env.get_by_path(state_path.last_vote_round()).await; let last_vote_round = map_not_found_option_to_option(last_vote_round)?.map(|id| parse_u64_obj(&id)); + let last_qc = op_env.get_by_path(state_path.last_qc()).await; let last_qc = map_not_found_option_to_option(last_qc)?; let last_qc = match last_qc.as_ref() { - Some(qc_id) => Some(non_driver.get_qc(qc_id, None).await?), + Some(qc_id) => non_driver + .get_qc(qc_id, None) + .await? + .try_into() + .map_or(None, |qc| Some(qc)), + None => None, + }; + + let last_tc = op_env.get_by_path(state_path.last_tc()).await; + let last_tc = map_not_found_option_to_option(last_tc)?; + let last_tc = match last_tc.as_ref() { + Some(tc_id) => non_driver + .get_qc(tc_id, None) + .await? + .try_into() + .map_or(None, |tc| Some(tc)), None => None, }; @@ -118,6 +135,7 @@ impl StorageEngineGroupState { let mut cache = StorageCacheInfo::new(dec_state_id); cache.last_vote_round = last_vote_round.map_or(0, |round| round); cache.last_qc = last_qc; + cache.last_tc = last_tc; cache.finish_proposals.adding = HashSet::from_iter(adding_proposal_ids.into_iter()); cache.finish_proposals.over = HashSet::from_iter(over_proposal_ids.into_iter()); cache.finish_proposals.flip_timestamp = flip_timestamp; @@ -440,6 +458,13 @@ impl StorageEngineGroupStateWriter { .await .map(|_| ()) } + + async fn save_last_tc_inner(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.op_env + .set_with_path(self.state_path.last_tc(), tc_id, &None, true) + .await + .map(|_| ()) + } } #[async_trait::async_trait] @@ -509,6 +534,12 @@ impl StorageWriter for StorageEngineGroupStateWriter { self.write_result.clone() } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + self.write_result.as_ref().map_err(|e| e.clone())?; + self.write_result = self.save_last_tc_inner(tc_id).await; + self.write_result.clone() + } + async fn commit(mut self) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index 79491b186..ebeedd7ca 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -196,6 +196,10 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { Ok(()) } + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()> { + Ok(()) + } + async fn commit(mut self) -> BuckyResult<()> { Ok(()) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3f9fc9910..ee2618cde 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -10,7 +10,7 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffTimeout, + GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; @@ -442,30 +442,49 @@ impl GroupStorage { Ok(()) } - pub fn last_qc(&self) -> &Option { + pub fn last_qc(&self) -> &Option { &self.cache.last_qc } - pub async fn save_qc(&mut self, qc: GroupQuorumCertificate) -> BuckyResult<()> { - let quorum_round = qc.quorum_round(); + pub async fn save_qc(&mut self, qc: &HotstuffBlockQC) -> BuckyResult<()> { + let quorum_round = qc.round; if quorum_round < self.cache.last_vote_round - || quorum_round - <= self - .cache - .last_qc - .as_ref() - .map_or(0, |qc| qc.quorum_round()) + || quorum_round <= self.cache.last_qc.as_ref().map_or(0, |qc| qc.round) { return Ok(()); } + let qc = GroupQuorumCertificate::from(qc.clone()); self.non_driver.put_qc(&qc).await?; let mut writer = self.storage_engine.create_writer().await?; writer.save_last_qc(&qc.desc().object_id()).await?; writer.commit().await?; - self.cache.last_qc = Some(qc); + self.cache.last_qc = Some(qc.try_into().unwrap()); + Ok(()) + } + + pub fn last_tc(&self) -> &Option { + &self.cache.last_tc + } + + pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + let quorum_round = tc.round; + if quorum_round < self.cache.last_vote_round + || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) + { + return Ok(()); + } + + let tc = GroupQuorumCertificate::from(tc.clone()); + self.non_driver.put_qc(&tc).await?; + + let mut writer = self.storage_engine.create_writer().await?; + writer.save_last_tc(&tc.desc().object_id()).await?; + writer.commit().await?; + + self.cache.last_tc = Some(tc.try_into().unwrap()); Ok(()) } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b5b6f4ce4..2ba99716e 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -798,6 +798,8 @@ async fn main_run() { admin_stacks.push(cyfs_stack); } + async_std::task::sleep(Duration::from_millis(10000)).await; + for i in 0..admin_stacks.len() { let stack = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); From c99b5e2a244bc3cd59ca2ec0d54eb513f3b699d8 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:23:03 +0800 Subject: [PATCH 492/553] prepare for verify --- .../cyfs-core/protos/core_objects.proto | 14 -- src/component/cyfs-core/src/coreobj.rs | 1 - .../src/group/group_consensus_block.rs | 23 +++ .../cyfs-core/src/group/group_rpath_status.rs | 17 --- src/component/cyfs-core/src/group/mod.rs | 2 - .../protos/group_bft_protocol.proto | 6 + src/component/cyfs-group/src/crypto/crypto.rs | 14 -- src/component/cyfs-group/src/crypto/mod.rs | 3 - .../cyfs-group/src/dec/group_manager.rs | 35 +++-- .../src/dec_state/dec_state_requestor.rs | 32 ++-- src/component/cyfs-group/src/helper/verify.rs | 6 +- src/component/cyfs-group/src/lib.rs | 2 - .../src/objects/group_rpath_status.rs | 89 +++++++++++ src/component/cyfs-group/src/objects/mod.rs | 2 + .../cyfs-group/src/objects/protocol.rs | 140 +++++++++++++----- .../cyfs-group/src/storage/dec_storage.rs | 6 +- 16 files changed, 259 insertions(+), 133 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_rpath_status.rs delete mode 100644 src/component/cyfs-group/src/crypto/crypto.rs delete mode 100644 src/component/cyfs-group/src/crypto/mod.rs create mode 100644 src/component/cyfs-group/src/objects/group_rpath_status.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 164c6bcd6..487ece4bd 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -431,20 +431,6 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } -message GroupRPathSubStatus { - string sub_path = 1; - repeated bytes state_id = 2; // for set -} - -message GroupRPathStatusDescContent { - bytes block_id = 1; - optional bytes sub_status_hash = 2; -} - -message GroupRPathStatusBodyContent { - repeated GroupRPathSubStatus sub_status = 1; -} - message GroupActionDescContent { // target GroupRPath r_path = 1; diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 30bf0e013..3d53a082f 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -64,7 +64,6 @@ pub enum CoreObjectType { GroupProposal = 700, GroupUpdateGroup = 701, GroupConsensusBlock = 702, - GroupRPathStatus = 703, GroupAction = 704, GroupQuorumCertificate = 705, diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 5d6d114c0..35c418552 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -38,6 +38,28 @@ impl DescContent for GroupConsensusBlockDescContent { type PublicKeyType = SubDescNone; } +impl GroupConsensusBlockDescContent { + pub fn rpath(&self) -> &GroupRPath { + &self.r_path + } + + pub fn result_state_id(&self) -> &Option { + &self.result_state_id + } + + pub fn height(&self) -> u64 { + self.height + } + + pub fn round(&self) -> u64 { + self.round + } + + pub fn group_chunk_id(&self) -> &ObjectId { + &self.group_chunk_id + } +} + #[derive(Clone, ProtobufTransformType)] #[cyfs_protobuf_type(crate::codec::protos::hotstuff_block_qc::VoteSignature)] pub struct HotstuffBlockQCSign { @@ -175,6 +197,7 @@ impl BodyContent for GroupConsensusBlockBodyContent { } } +pub type GroupConsensusBlockDesc = NamedObjectDesc; type GroupConsensusBlockType = NamedObjType; type GroupConsensusBlockBuilder = diff --git a/src/component/cyfs-core/src/group/group_rpath_status.rs b/src/component/cyfs-core/src/group/group_rpath_status.rs deleted file mode 100644 index c55c41243..000000000 --- a/src/component/cyfs-core/src/group/group_rpath_status.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::atomic::{AtomicU8, Ordering}; - -use crate::CoreObjectType; -use cyfs_base::*; -use serde::Serialize; -use sha2::Digest; - -// TODO: 后面再封装这个对象 -#[derive(Clone, RawEncode, RawDecode)] -pub struct GroupRPathStatus { - pub value_object_id: ObjectId, - pub block_id: ObjectId, - pub qc_block_id: ObjectId, -} - -#[cfg(test)] -mod test {} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index c153ab1ba..b2885d637 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -3,7 +3,6 @@ mod group_proposal; mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_rpath_status; mod group_update_group_proposal_param; pub use group_consensus_block::*; @@ -11,5 +10,4 @@ pub use group_proposal::*; pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_rpath_status::*; pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto index 6ed8c3afe..621186522 100644 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group/protos/group_bft_protocol.proto @@ -15,3 +15,9 @@ message HotstuffTimeoutVote { bytes voter = 3; bytes signature = 4; } + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} \ No newline at end of file diff --git a/src/component/cyfs-group/src/crypto/crypto.rs b/src/component/cyfs-group/src/crypto/crypto.rs deleted file mode 100644 index 9949f7a67..000000000 --- a/src/component/cyfs-group/src/crypto/crypto.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cyfs_base::{HashValue, ObjectId, Signature}; - -#[derive(Clone)] -pub struct Crypto {} - -impl Crypto { - pub fn sign(&self, hash: &HashValue) -> Signature { - unimplemented!() - } - - pub fn verify(&self, hash: &HashValue, sign: &Signature, object_id: &ObjectId) -> bool { - unimplemented!() - } -} diff --git a/src/component/cyfs-group/src/crypto/mod.rs b/src/component/cyfs-group/src/crypto/mod.rs deleted file mode 100644 index 066e79b6b..000000000 --- a/src/component/cyfs-group/src/crypto/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod crypto; - -pub use crypto::*; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 70fb10ba6..2f2229890 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -289,7 +289,7 @@ impl GroupManager { .await; } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { - // TODO: 暂时不实现 + // TODO: unimplemented // let rpath = header_block.r_path(); // let client = self // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) @@ -302,23 +302,22 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - // TODO: 暂时不实现 - // let rpath = result.as_ref().map_or_else( - // |(_, target)| target.check_rpath(), - // |(_, block, _)| block.r_path(), - // ); - // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - // .await?; - // client - // .on_message( - // HotstuffMessage::ProposalResult( - // proposal_id, - // result.map_err(|(err, _)| err), - // ), - // remote, - // ) - // .await; + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |(_, block, _)| block.r_path(), + ); + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message( + HotstuffMessage::ProposalResult( + proposal_id, + result.map_err(|(err, _)| err), + ), + remote, + ) + .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index e30c0a5a7..369b3db6e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,10 +3,13 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath, GroupRPathStatus}; +use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; -use crate::{helper::verify_rpath_value, storage::DecStorage, HotstuffMessage, CHANNEL_CAPACITY}; +use crate::{ + helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + CHANNEL_CAPACITY, +}; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -143,7 +146,7 @@ impl DecStateRequestorRunner { let result = self .verify_verifiable_state(sub_path.as_str(), &result, &remote) .await - .map(|_| result.value_object_id); + .map(|_| unimplemented!()); // TODO: 搜索目标值 self.query_state_notifier.reply(&sub_path, result).await } @@ -157,25 +160,22 @@ impl DecStateRequestorRunner { result: &GroupRPathStatus, remote: &ObjectId, ) -> BuckyResult<()> { - let header_block = self - .non_driver - .get_block(&result.block_id, Some(remote)) - .await?; - let qc_block = self - .non_driver - .get_block(&result.qc_block_id, Some(remote)) - .await?; + // let header_block = self + // .non_driver + // .get_block(&result.block_id, Some(remote)) + // .await?; + // let qc_block = self + // .non_driver + // .get_block(&result.qc_block_id, Some(remote)) + // .await?; - let qc = match qc_block.qc() { - Some(qc) => qc, - None => return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, "no qc")), - }; + let qc = &result.certificate; let group = self .non_driver .get_group( self.rpath.group_id(), - Some(header_block.group_chunk_id()), + Some(result.block_desc.content().group_chunk_id()), Some(&remote), ) .await?; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 2a384d1cf..b8ab12b69 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPathStatus, HotstuffBlockQC, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; + +use crate::GroupRPathStatus; pub async fn verify_block( block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index fefe3f808..ba8e83569 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -1,6 +1,5 @@ mod consensus; mod constant; -mod crypto; mod dec; mod dec_state; mod helper; @@ -12,7 +11,6 @@ mod utils; pub use consensus::*; pub use constant::*; -pub(crate) use crypto::*; pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs new file mode 100644 index 000000000..f266d3dbd --- /dev/null +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use cyfs_base::*; +use cyfs_core::{GroupConsensusBlockDesc, HotstuffBlockQC}; +use cyfs_lib::NONObjectInfo; +use prost::Message; + +#[derive(Clone)] +pub struct GroupRPathStatus { + pub block_desc: GroupConsensusBlockDesc, + pub certificate: HotstuffBlockQC, + pub status_map: HashMap, +} + +impl RawEncode for GroupRPathStatus { + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + Ok(proto.encoded_len()) + } + + fn raw_encode<'a>( + &self, + mut buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + let block_desc = self.block_desc.to_vec()?; + let certificate = self.certificate.to_vec()?; + let mut status_list = vec![]; + for (_, obj) in self.status_map.iter() { + status_list.push(obj.to_vec()?); + } + + let proto = crate::protos::GroupRPathStatus { + block_desc, + certificate, + status_list, + }; + + proto.encode_raw(&mut buf); + + Ok(buf) + } +} + +impl<'de> RawDecode<'de> for GroupRPathStatus { + fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); + log::error!("{}", msg); + BuckyError::new(BuckyErrorCode::Failed, msg) + })?; + + let (block_desc, remain) = + GroupConsensusBlockDesc::raw_decode(proto.block_desc.as_slice())?; + assert_eq!(remain.len(), 0); + let (certificate, remain) = HotstuffBlockQC::raw_decode(proto.certificate.as_slice())?; + assert_eq!(remain.len(), 0); + let mut status_map = HashMap::new(); + for obj_buf in proto.status_list.iter() { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status_map.insert(status.object_id, status); + } + + Ok(( + Self { + block_desc, + certificate, + status_map, + }, + buf, + )) + } +} + +#[cfg(test)] +mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs index d6de55d79..5d1a8b13f 100644 --- a/src/component/cyfs-group/src/objects/mod.rs +++ b/src/component/cyfs-group/src/objects/mod.rs @@ -1,7 +1,9 @@ mod group_decide_proposal; +mod group_rpath_status; mod group_update_proposal; mod protocol; pub use group_decide_proposal::*; +pub use group_rpath_status::*; pub use group_update_proposal::*; pub use protocol::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 3e5f513df..6c9f89e96 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -2,16 +2,15 @@ pub mod protos { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } -use std::result; - use cyfs_base::*; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, GroupRPathStatus, HotstuffBlockQC, - HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use sha2::Digest; +use crate::GroupRPathStatus; + #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { Height(u64), @@ -163,20 +162,16 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::ProposalResult({}, {:?})", proposal_id, - result.as_ref().map_or_else( - |err| { Err(err) }, - |(obj, block, qc)| { - let ok = format!( - "({:?}, {}/{}, {}/{})", - obj.as_ref().map(|o| o.object_id), - block.block_id(), - block.round(), - qc.block_id(), - qc.round() - ); - Ok(ok) - } - ) + result.as_ref().map(|(obj, block, qc)| { + format!( + "({:?}, {}/{}, {}/{})", + obj.as_ref().map(|o| o.object_id), + block.block_id(), + block.round(), + qc.block_id(), + qc.round() + ) + }) ) } Self::QueryState(sub_path) => { @@ -187,7 +182,17 @@ impl std::fmt::Debug for HotstuffMessage { f, "HotstuffMessage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map(|status| { + let desc = status.block_desc.content(); + format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ) + }) ) } } @@ -196,6 +201,7 @@ impl std::fmt::Debug for HotstuffMessage { const PACKAGE_FLAG_BITS: usize = 1; const PACKAGE_FLAG_PROPOSAL_RESULT_OK: u8 = 0x80u8; +const PACKAGE_FLAG_QUERY_STATE_RESULT_OK: u8 = 0x80u8; #[derive(Clone)] pub(crate) enum HotstuffPackage { @@ -220,7 +226,10 @@ pub(crate) enum HotstuffPackage { >, ), // (proposal-id, ExecuteResult) QueryState(ProtocolAddress, String), - VerifiableState(ProtocolAddress, String, BuckyResult), + VerifiableState( + String, + Result, + ), } impl std::fmt::Debug for HotstuffPackage { @@ -296,12 +305,26 @@ impl std::fmt::Debug for HotstuffPackage { Self::QueryState(_, sub_path) => { write!(f, "HotstuffPackage::QueryState({})", sub_path) } - Self::VerifiableState(_, sub_path, result) => { + Self::VerifiableState(sub_path, result) => { write!( f, "HotstuffPackage::VerifiableState({}, {:?})", sub_path, - result.as_ref().map(|status| unimplemented!()) + result.as_ref().map_or_else( + |(err, _)| { Err(err) }, + |status| { + let desc = status.block_desc.content(); + let ok = format!( + "({:?}/{:?}, {}/{}/{})", + desc.result_state_id(), + status.block_desc.object_id(), + desc.height(), + desc.round(), + status.certificate.round + ); + Ok(ok) + } + ) ) } } @@ -323,7 +346,10 @@ impl HotstuffPackage { |(_, block, _)| block.r_path(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), - HotstuffPackage::VerifiableState(addr, _, _) => addr.check_rpath(), + HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( + |(_, addr)| addr.check_rpath(), + |status| status.block_desc.content().rpath(), + ), } } } @@ -399,10 +425,14 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::QueryState(addr, sub_path) => { addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { - 2 + addr.raw_measure(purpose)? - + sub_path.raw_measure(purpose)? - + result.raw_measure(purpose)? + HotstuffPackage::VerifiableState(sub_path, result) => { + sub_path.raw_measure(purpose)? + + match result { + Ok(status) => status.raw_measure(purpose)?, + Err((err, addr)) => { + err.raw_measure(purpose)? + addr.raw_measure(purpose)? + } + } } }; @@ -459,7 +489,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; if result.is_ok() { - buf[0] &= PACKAGE_FLAG_PROPOSAL_RESULT_OK; + buf[0] |= PACKAGE_FLAG_PROPOSAL_RESULT_OK; } let buf = &mut buf[1..]; @@ -482,12 +512,20 @@ impl RawEncode for HotstuffPackage { let buf = sub_path.raw_encode(buf, purpose)?; addr.raw_encode(buf, purpose) } - HotstuffPackage::VerifiableState(addr, sub_path, result) => { + HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; + if result.is_ok() { + buf[0] |= PACKAGE_FLAG_QUERY_STATE_RESULT_OK; + } let buf = &mut buf[1..]; - let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = sub_path.raw_encode(buf, purpose)?; - result.raw_encode(buf, purpose) + match result { + Ok(status) => status.raw_encode(buf, purpose), + Err((err, addr)) => { + let buf = err.raw_encode(buf, purpose)?; + addr.raw_encode(buf, purpose) + } + } } } } @@ -502,24 +540,28 @@ impl<'de> RawDecode<'de> for HotstuffPackage { 0 => { let buf = &buf[1..]; let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { @@ -527,17 +569,20 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } 7 => { @@ -549,6 +594,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), buf, @@ -557,6 +603,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { false => { let (err, buf) = BuckyError::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } } @@ -565,17 +612,29 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let buf = &buf[1..]; let (sub_path, buf) = String::raw_decode(buf)?; let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } 9 => { + let is_ok = (buf[0] & PACKAGE_FLAG_QUERY_STATE_RESULT_OK) != 0; let buf = &buf[1..]; - let (addr, buf) = decode_with_length(buf, 3)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (result, buf) = BuckyResult::::raw_decode(buf)?; - Ok(( - HotstuffPackage::VerifiableState(addr, sub_path, result), - buf, - )) + match is_ok { + true => { + let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) + } + false => { + let (err, buf) = BuckyError::raw_decode(buf)?; + let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + assert_eq!(buf.len(), 0); + Ok(( + HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), + buf, + )) + } + } } _ => unreachable!("unknown protocol"), } @@ -613,9 +672,10 @@ impl HotstuffPackage { HotstuffMessage::QueryState(sub_path) => { HotstuffPackage::QueryState(ProtocolAddress::Full(rpath), sub_path) } - HotstuffMessage::VerifiableState(sub_path, result) => { - HotstuffPackage::VerifiableState(ProtocolAddress::Full(rpath), sub_path, result) - } + HotstuffMessage::VerifiableState(sub_path, result) => HotstuffPackage::VerifiableState( + sub_path, + result.map_err(|err| (err, ProtocolAddress::Full(rpath))), + ), } } } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 12e3629d8..cce00e736 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use async_std::sync::RwLock; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupRPathStatus}; +use cyfs_core::GroupConsensusBlock; + +use crate::GroupRPathStatus; #[derive(Clone)] pub struct DecStorageCache { @@ -11,8 +13,6 @@ pub struct DecStorageCache { pub qc_block: GroupConsensusBlock, } -// TODO: storage - #[derive(Clone)] pub struct DecStorage { cache: Arc>>, From dc17e2802edbdf47645dfb9cb9117f0640ee0de9 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 22 Feb 2023 21:28:28 +0800 Subject: [PATCH 493/553] compile --- .../cyfs-group/src/dec/group_manager.rs | 12 +++++++++--- .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 14 +++++++++----- src/component/cyfs-group/src/helper/verify.rs | 16 +++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 2f2229890..0d863e17b 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -328,13 +328,19 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - HotstuffPackage::VerifiableState(target, sub_path, result) => { - let rpath = target.check_rpath(); + HotstuffPackage::VerifiableState(sub_path, result) => { + let rpath = result.as_ref().map_or_else( + |(_, target)| target.check_rpath(), + |status| status.block_desc.content().rpath(), + ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) .await?; client - .on_message(HotstuffMessage::VerifiableState(sub_path, result), remote) + .on_message( + HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), + remote, + ) .await; } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 369b3db6e..b5c3b107e 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -180,7 +180,7 @@ impl DecStateRequestorRunner { ) .await?; - if !verify_rpath_value(&result, sub_path, &header_block, qc, &group).await? { + if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { Err(BuckyError::new( BuckyErrorCode::InvalidSignature, "verify failed", diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 1f33ec5fa..73afb0ad0 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -315,10 +315,7 @@ impl DecStateSynchronizerRunner { remote: ObjectId, ) -> BuckyResult<()> { if qc_block.qc().is_none() { - log::warn!( - "the qc is none for qc-block({})", - qc_block.block_id() - ); + log::warn!("the qc is none for qc-block({})", qc_block.block_id()); return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); } @@ -365,7 +362,14 @@ impl DecStateSynchronizerRunner { } }; - if verify_block(&header_block, qc_block.qc().as_ref().unwrap(), &group.1).await? { + if header_block.check() + && verify_block( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + &group.1, + ) + .await? + { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index b8ab12b69..759bf2c4a 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -1,15 +1,17 @@ use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, +}; use crate::GroupRPathStatus; pub async fn verify_block( - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { - let block_id = block.block_id().object_id(); - if qc.round != block.round() || &qc.block_id != block_id { + let block_id = block_desc.object_id(); + if qc.round != block_desc.content().round() || qc.block_id != block_id { log::error!( "the qc-block({}) should be next block({})", qc.round, @@ -18,17 +20,13 @@ pub async fn verify_block( return Ok(false); } - if !block.check() { - return Ok(false); - } - unimplemented!() } pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, - block: &GroupConsensusBlock, + block_desc: &GroupConsensusBlockDesc, qc: &HotstuffBlockQC, group: &Group, ) -> BuckyResult { From 00f92a6e45721b6a95dc4e6124096b2a165a1827 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 23 Feb 2023 21:02:07 +0800 Subject: [PATCH 494/553] Verify the value on sub-path from anyone OOD in group --- .../src/consensus/hotstuff/hotstuff.rs | 28 ++++- .../src/consensus/vote/committee.rs | 66 ++++++++++- .../cyfs-group/src/dec/group_manager.rs | 54 ++++++--- .../cyfs-group/src/dec/rpath_client.rs | 34 ++++-- .../cyfs-group/src/dec/rpath_control.rs | 4 +- .../src/dec_state/dec_state_requestor.rs | 73 ++++++------ .../src/dec_state/dec_state_synchronizer.rs | 80 ++++++-------- src/component/cyfs-group/src/helper/verify.rs | 18 --- .../src/objects/group_rpath_status.rs | 4 +- .../cyfs-group/src/storage/dec_storage.rs | 76 ++++++++++++- .../src/storage/engine/storage_engine.rs | 4 +- .../engine/storage_engine_group_state.rs | 23 +++- .../cyfs-group/src/storage/group_storage.rs | 104 +++++++++++++++++- src/component/cyfs-group/src/utils.rs | 2 +- src/tests/group-example/src/main.rs | 6 +- 15 files changed, 410 insertions(+), 166 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index a2a5e8f70..667966a6c 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -187,6 +187,19 @@ impl Hotstuff { self.state_pusher.request_last_state(remote).await; } + + pub async fn on_query_state(&self, sub_path: String, remote: ObjectId) { + log::debug!( + "[hotstuff] local: {:?}, on_query_state: sub_path: {}, remote: {:?},", + self, + sub_path, + remote + ); + + self.tx_message + .send((HotstuffMessage::QueryState(sub_path), remote)) + .await; + } } struct HotstuffRunner { @@ -1834,6 +1847,19 @@ impl HotstuffRunner { Ok(()) } + async fn handle_query_state(&self, sub_path: String, remote: ObjectId) -> BuckyResult<()> { + let result = self.store.get_by_path(sub_path.as_str()).await; + self.network_sender + .post_message( + HotstuffMessage::VerifiableState(sub_path, result), + self.rpath.clone(), + &remote, + ) + .await; + + Ok(()) + } + async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; @@ -1918,7 +1944,7 @@ impl HotstuffRunner { Ok((HotstuffMessage::LastStateRequest, _)) => panic!("should process by StatePusher"), Ok((HotstuffMessage::StateChangeNotify(_, _), _)) => panic!("should process by DecStateSynchronizer"), Ok((HotstuffMessage::ProposalResult(_, _), _)) => panic!("should process by DecStateSynchronizer"), - Ok((HotstuffMessage::QueryState(_), _)) => panic!("should process by DecStateRequestor"), + Ok((HotstuffMessage::QueryState(sub_path), remote)) => self.handle_query_state(sub_path, remote).await, Ok((HotstuffMessage::VerifiableState(_, _), _)) => panic!("should process by DecStateRequestor"), Err(e) => { log::warn!("[hotstuff] rx_message closed."); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d3fbd489c..ad3a21e35 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,9 +10,13 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_chunk_lib::ChunkMeta; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{ + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, +}; +use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; #[derive(Clone)] pub(crate) struct Committee { @@ -136,6 +140,47 @@ impl Committee { Ok(()) } + pub async fn verify_block_desc_with_qc( + &self, + block_desc: &GroupConsensusBlockDesc, + qc: &HotstuffBlockQC, + from: ObjectId, + ) -> BuckyResult<()> { + let block_id = block_desc.object_id(); + + log::debug!( + "[group committee] {} verify block desc {} step1", + self.local_device_id, + block_id + ); + + if block_id != qc.block_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the block id is unmatch with the qc", + )); + } + + self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + .await?; + + log::debug!( + "[group committee] {} verify block desc {} step2", + self.local_device_id, + block_id + ); + + self.verify_qc_with_desc(qc, block_desc.content()).await?; + + log::debug!( + "[group committee] {} verify block desc {} step3", + self.local_device_id, + block_id + ); + + Ok(()) + } + pub async fn verify_vote(&self, vote: &HotstuffBlockQCVote) -> BuckyResult<()> { let hash = vote.hash(); let device = self.non_driver.get_device(&vote.voter).await?; @@ -250,8 +295,17 @@ impl Committee { qc: &HotstuffBlockQC, prev_block: &GroupConsensusBlock, ) -> BuckyResult<()> { - if qc.round != prev_block.round() { - log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block.round()); + self.verify_qc_with_desc(qc, prev_block.named_object().desc().content()) + .await + } + + pub async fn verify_qc_with_desc( + &self, + qc: &HotstuffBlockQC, + prev_block_desc: &GroupConsensusBlockDescContent, + ) -> BuckyResult<()> { + if qc.round != prev_block_desc.round() { + log::warn!("[group committee] round is not match with prev-block in qc, round: {}, prev_round: {}", qc.round, prev_block_desc.round()); return Err(BuckyError::new( BuckyErrorCode::NotMatch, "round not match in qc", @@ -261,7 +315,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block.group_chunk_id()), + Some(prev_block_desc.group_chunk_id()), ) .await?; @@ -291,7 +345,7 @@ impl Committee { .map_or(Ok(()), |e| e) } - async fn check_group( + pub async fn check_group( &self, chunk_id: Option<&ObjectId>, from: Option<&ObjectId>, diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 0d863e17b..f7b7fbbbe 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -123,6 +123,7 @@ impl GroupManager { let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); + let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), @@ -143,9 +144,13 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let state_proccessor = state_mgr + .load_root_state(local_device_id.object_id(), Some(local_id), true) + .await?; let client = RPathClient::load( - local_id, + local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + state_proccessor.unwrap(), non_driver, network_sender, ) @@ -199,7 +204,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, Some(&block), Some(&remote), ) @@ -215,7 +220,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -231,7 +236,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -247,7 +252,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -263,7 +268,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -279,7 +284,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, None, Some(&remote), ) @@ -321,12 +326,32 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) - .await?; - client - .on_message(HotstuffMessage::QueryState(sub_path), remote) + let control = self + .find_rpath_control_inner( + rpath.group_id(), + rpath.dec_id(), + rpath.r_path(), + IsCreateRPath::No, + None, + Some(&remote), + ) .await; + + match control { + Ok(control) => { + control + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + _ => { + let client = self + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .await?; + client + .on_message(HotstuffMessage::QueryState(sub_path), remote) + .await; + } + } } HotstuffPackage::VerifiableState(sub_path, result) => { let rpath = result.as_ref().map_or_else( @@ -436,15 +461,10 @@ impl GroupManager { let store = match store { Some(store) => store, None => { - let init_state = match is_auto_create { - IsCreateRPath::Yes(init_state) => init_state, - _ => unreachable!(), - }; GroupStorage::create( group_id, dec_id, rpath, - init_state, non_driver.clone(), local_device_id.object_id().clone(), &root_state_mgr, diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 9f1d08579..8a1dd34a7 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -5,18 +5,18 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, storage::DecStorage, - HotstuffMessage, CLIENT_POLL_TIMEOUT, + Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; struct RPathClientRaw { rpath: GroupRPath, - local_id: ObjectId, + local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, @@ -28,22 +28,31 @@ pub struct RPathClient(Arc); impl RPathClient { pub(crate) async fn load( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, network_sender: crate::network::Sender, ) -> BuckyResult { - let dec_store = DecStorage::load().await?; + let dec_store = DecStorage::load(state_processor).await?; + let committee = Committee::new( + rpath.group_id().clone(), + non_driver.clone(), + local_device_id, + ); + let state_sync = DecStateSynchronizer::new( - local_id, + local_device_id, rpath.clone(), + committee.clone(), non_driver.clone(), dec_store.clone(), ); let state_requestor = DecStateRequestor::new( - local_id, + local_device_id, rpath.clone(), + committee, network_sender.clone(), non_driver.clone(), dec_store.clone(), @@ -53,7 +62,7 @@ impl RPathClient { rpath, non_driver, network_sender, - local_id, + local_device_id, state_sync, state_requestor, }; @@ -77,7 +86,7 @@ impl RPathClient { .non_driver .get_group(proposal.r_path().group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); let non_proposal = NONObjectInfo::new(proposal_id, proposal.to_vec()?, None); @@ -143,7 +152,7 @@ impl RPathClient { .get_group(&self.0.rpath.group_id(), None, None) .await?; - let oods = group.ood_list_with_distance(&self.0.local_id); + let oods = group.ood_list_with_distance(&self.0.local_device_id); let random = rand::thread_rng().gen_range(0..oods.len()); let ood = oods.get(random).unwrap().clone(); @@ -154,14 +163,15 @@ impl RPathClient { Ok(()) } - pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 .non_driver .get_group(self.0.rpath.group_id(), None, None) .await?; - let members = group.select_members_with_distance(&self.0.local_id, GroupMemberScope::All); + let members = + group.select_members_with_distance(&self.0.local_device_id, GroupMemberScope::All); let req_msg = HotstuffMessage::QueryState(sub_path.to_string()); let waiter = self diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 101b34075..7abff1ec1 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -89,7 +89,9 @@ impl RPathControl { HotstuffMessage::LastStateRequest => self.0.hotstuff.request_last_state(remote).await, HotstuffMessage::StateChangeNotify(_, _) => unreachable!(), HotstuffMessage::ProposalResult(_, _) => unreachable!(), - HotstuffMessage::QueryState(_) => unreachable!(), + HotstuffMessage::QueryState(sub_path) => { + self.0.hotstuff.on_query_state(sub_path, remote).await + } HotstuffMessage::VerifiableState(_, _) => unreachable!(), } } diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index b5c3b107e..0a3544c09 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,10 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::verify_rpath_value, storage::DecStorage, GroupRPathStatus, HotstuffMessage, + helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, CHANNEL_CAPACITY, }; @@ -19,9 +20,9 @@ enum DecStateRequestorMessage { } struct DecStateRequestorRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_req_message: async_std::channel::Sender<(DecStateRequestorMessage, ObjectId)>, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } #[derive(Clone)] @@ -29,8 +30,9 @@ pub struct DecStateRequestor(Arc); impl DecStateRequestor { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, store: DecStorage, @@ -39,8 +41,9 @@ impl DecStateRequestor { let notifier = CallReplyNotifier::new(); let mut runner = DecStateRequestorRunner::new( - local_id, + local_device_id, rpath, + committee, rx, store, network_sender, @@ -51,7 +54,7 @@ impl DecStateRequestor { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateRequestorRaw { - local_id, + local_device_id, tx_dec_state_req_message: tx, query_state_notifier: notifier, })) @@ -60,7 +63,7 @@ impl DecStateRequestor { pub async fn wait_query_state( &self, sub_path: String, - ) -> CallReplyWaiter> { + ) -> CallReplyWaiter>> { self.0.query_state_notifier.prepare(sub_path).await } @@ -88,21 +91,23 @@ impl DecStateRequestor { } struct DecStateRequestorRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<(DecStateRequestorMessage, ObjectId)>, // timer: Timer, store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, } impl DecStateRequestorRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, rx_dec_state_req_message: async_std::channel::Receiver<( DecStateRequestorMessage, ObjectId, @@ -110,10 +115,10 @@ impl DecStateRequestorRunner { store: DecStorage, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, - query_state_notifier: CallReplyNotifier>, + query_state_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, rx_dec_state_req_message, // timer: Timer::new(SYNCHRONIZER_TIMEOUT), @@ -121,6 +126,7 @@ impl DecStateRequestorRunner { query_state_notifier, network_sender, non_driver, + committee, } } @@ -144,9 +150,9 @@ impl DecStateRequestorRunner { match result { Ok(result) => { let result = self - .verify_verifiable_state(sub_path.as_str(), &result, &remote) + .check_sub_path_value(sub_path.as_str(), &result, &remote) .await - .map(|_| unimplemented!()); // TODO: 搜索目标值 + .map(|r| r.cloned()); self.query_state_notifier.reply(&sub_path, result).await } @@ -154,40 +160,23 @@ impl DecStateRequestorRunner { } } - async fn verify_verifiable_state( + async fn check_sub_path_value<'a>( &self, sub_path: &str, - result: &GroupRPathStatus, + verifiable_status: &'a GroupRPathStatus, remote: &ObjectId, - ) -> BuckyResult<()> { - // let header_block = self - // .non_driver - // .get_block(&result.block_id, Some(remote)) - // .await?; - // let qc_block = self - // .non_driver - // .get_block(&result.qc_block_id, Some(remote)) - // .await?; - - let qc = &result.certificate; - - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(result.block_desc.content().group_chunk_id()), - Some(&remote), + ) -> BuckyResult> { + self.committee + .verify_block_desc_with_qc( + &verifiable_status.block_desc, + &verifiable_status.certificate, + remote.clone(), ) .await?; - if !verify_rpath_value(&result, sub_path, &result.block_desc, qc, &group).await? { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "verify failed", - )) - } else { - Ok(()) - } + self.store + .check_sub_path_value(sub_path, verifiable_status) + .await } async fn run(&mut self) { diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 73afb0ad0..7272b3882 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -10,10 +10,10 @@ use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::{verify_block, Timer}, + helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, - CHANNEL_CAPACITY, + Committee, CHANNEL_CAPACITY, }; use super::{CallReplyNotifier, CallReplyWaiter}; @@ -32,7 +32,7 @@ enum DecStateSynchronizerMessage { } struct DecStateSynchronizerRaw { - local_id: ObjectId, + local_device_id: ObjectId, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, proposal_result_notifier: CallReplyNotifier>>, } @@ -42,8 +42,9 @@ pub struct DecStateSynchronizer(Arc); impl DecStateSynchronizer { pub(crate) fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, non_driver: crate::network::NONDriverHelper, store: DecStorage, ) -> Self { @@ -51,8 +52,9 @@ impl DecStateSynchronizer { let notifier = CallReplyNotifier::new(); let mut runner = DecStateSynchronizerRunner::new( - local_id, + local_device_id, rpath, + committee, tx.clone(), rx, store, @@ -63,7 +65,7 @@ impl DecStateSynchronizer { async_std::task::spawn(async move { runner.run().await }); Self(Arc::new(DecStateSynchronizerRaw { - local_id, + local_device_id, tx_dec_state_sync_message: tx, proposal_result_notifier: notifier, })) @@ -126,8 +128,9 @@ struct UpdateNotifyInfo { } struct DecStateSynchronizerRunner { - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<(DecStateSynchronizerMessage, ObjectId)>, rx_dec_state_sync_message: async_std::channel::Receiver<(DecStateSynchronizerMessage, ObjectId)>, @@ -142,8 +145,9 @@ struct DecStateSynchronizerRunner { impl DecStateSynchronizerRunner { fn new( - local_id: ObjectId, + local_device_id: ObjectId, rpath: GroupRPath, + committee: Committee, tx_dec_state_sync_message: async_std::channel::Sender<( DecStateSynchronizerMessage, ObjectId, @@ -157,7 +161,7 @@ impl DecStateSynchronizerRunner { proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { - local_id, + local_device_id, rpath, tx_dec_state_sync_message, rx_dec_state_sync_message, @@ -167,6 +171,7 @@ impl DecStateSynchronizerRunner { update_notifies: None, non_driver, proposal_result_notifier, + committee, } } @@ -330,52 +335,29 @@ impl DecStateSynchronizerRunner { } } - let group = match self.update_notifies.as_ref() { - Some(n) => Some((n.group_chunk_id, n.group.clone())), - None => self - .check_cache() - .await - .as_ref() - .map(|c| (c.group_chunk_id, c.group.clone())), - } - .map_or(None, |(chunk_id, group)| { - if &chunk_id == header_block.group_chunk_id() { - Some((chunk_id, group)) - } else { - None - } - }); - - // group changed - let group = match group { - Some(group) => group, - None => { - let group = self - .non_driver - .get_group( - self.rpath.group_id(), - Some(header_block.group_chunk_id()), - Some(&remote), - ) - .await?; - (header_block.group_chunk_id().clone(), group) - } - }; - if header_block.check() - && verify_block( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - &group.1, - ) - .await? + && self + .committee + .verify_block_desc_with_qc( + header_block.named_object().desc(), + qc_block.qc().as_ref().unwrap(), + remote, + ) + .await + .is_ok() { + let group = self + .committee + .check_group(Some(header_block.group_chunk_id()), None) + .await?; + let group_chunk_id = header_block.group_chunk_id().clone(); + self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc_block: qc_block, remotes: HashSet::from([remote]), - group_chunk_id: group.0, - group: group.1, + group_chunk_id, + group, }); }; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs index 759bf2c4a..ef3e34495 100644 --- a/src/component/cyfs-group/src/helper/verify.rs +++ b/src/component/cyfs-group/src/helper/verify.rs @@ -5,24 +5,6 @@ use cyfs_core::{ use crate::GroupRPathStatus; -pub async fn verify_block( - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - let block_id = block_desc.object_id(); - if qc.round != block_desc.content().round() || qc.block_id != block_id { - log::error!( - "the qc-block({}) should be next block({})", - qc.round, - block_id - ); - return Ok(false); - } - - unimplemented!() -} - pub async fn verify_rpath_value( value: &GroupRPathStatus, sub_path: &str, diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index f266d3dbd..858c37fff 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -13,7 +13,7 @@ pub struct GroupRPathStatus { } impl RawEncode for GroupRPathStatus { - fn raw_measure(&self, purpose: &Option) -> BuckyResult { + fn raw_measure(&self, _purpose: &Option) -> BuckyResult { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; let mut status_list = vec![]; @@ -33,7 +33,7 @@ impl RawEncode for GroupRPathStatus { fn raw_encode<'a>( &self, mut buf: &'a mut [u8], - purpose: &Option, + _purpose: &Option, ) -> BuckyResult<&'a mut [u8]> { let block_desc = self.block_desc.to_vec()?; let certificate = self.certificate.to_vec()?; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index cce00e736..de5a0fd4a 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -1,10 +1,14 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, + ObjectTypeCode, RawDecode, +}; use cyfs_core::GroupConsensusBlock; +use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::GroupRPathStatus; +use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; #[derive(Clone)] pub struct DecStorageCache { @@ -16,13 +20,15 @@ pub struct DecStorageCache { #[derive(Clone)] pub struct DecStorage { cache: Arc>>, + pub state_processor: GlobalStateRawProcessorRef, } impl DecStorage { - pub async fn load() -> BuckyResult { - unimplemented!(); + pub async fn load(state_processor: GlobalStateRawProcessorRef) -> BuckyResult { + // unimplemented!(); let obj = Self { cache: Arc::new(RwLock::new(None)), + state_processor, }; Ok(obj) @@ -45,4 +51,64 @@ impl DecStorage { pub async fn get_by_path(&self, path: &str) -> BuckyResult { unimplemented!() } + + pub async fn check_sub_path_value<'a>( + &self, + sub_path: &str, + verifiable_status: &'a GroupRPathStatus, + ) -> BuckyResult> { + let block_desc = &verifiable_status.block_desc; + let qc = &verifiable_status.certificate; + + let mut parent_state_id = match block_desc.content().result_state_id() { + Some(state_id) => state_id.clone(), + None => return Ok(None), + }; + + let root_cache = self.state_processor.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { + Some(state) => state, + None => return Ok(None), + }; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(None); + } + } + } + + Ok(verifiable_status.status_map.get(&parent_state_id)) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index c4803d6ff..eb0ede98f 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -22,9 +22,9 @@ pub struct StorageCacheInfo { } impl StorageCacheInfo { - pub fn new(init_state_id: Option) -> Self { + pub fn new(dec_state_id: Option) -> Self { Self { - dec_state_id: init_state_id, + dec_state_id, last_vote_round: 0, last_qc: None, last_tc: None, diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index b3a01fd60..604e44744 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,10 +2,10 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, - ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, + ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{HotstuffBlockQC, HotstuffTimeout}; +use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, @@ -154,6 +154,19 @@ impl StorageEngineGroupState { None => 0, }; + let dec_state_id_in_header = cache + .header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); + + assert_eq!(dec_state_id, dec_state_id_in_header); + if dec_state_id != dec_state_id_in_header { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "the state should same as it in header-block", + )); + } + let (prepare_blocks, pre_commit_blocks) = load_blocks.as_slice()[prepare_block_pos..].split_at(prepare_block_ids.len()); for (block, block_id) in prepare_blocks.iter().zip(prepare_block_ids) { @@ -179,6 +192,10 @@ impl StorageEngineGroupState { .await?, ) } + + pub fn root_cache(&self) -> &ObjectMapRootCacheRef { + self.state_mgr.root_cache() + } } #[async_trait::async_trait] diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index ee2618cde..d233025ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -5,7 +5,7 @@ use std::{ use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, + ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -15,7 +15,8 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ @@ -56,7 +57,6 @@ impl GroupStorage { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - init_state_id: Option, non_driver: NONDriverHelper, local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, @@ -84,7 +84,7 @@ impl GroupStorage { GroupStatePath::new(rpath.to_string()), ), local_device_id, - cache: StorageCacheInfo::new(init_state_id), + cache: StorageCacheInfo::new(None), }) } @@ -809,4 +809,100 @@ impl GroupStorage { ) } } + + pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + let (header_block, qc) = match self.cache.header_block.as_ref() { + Some(block) => { + let (_, qc_block) = self + .cache + .pre_commits + .iter() + .next() + .expect("pre-commit should not be empty"); + + assert_eq!( + qc_block.prev_block_id().unwrap(), + block.block_id().object_id(), + "the prev-block for all pre-commits should be the header" + ); + + (block, qc_block.qc().as_ref().unwrap()) + } + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + "the header block is none", + )); + } + }; + + let mut parent_state_id = match header_block.result_state_id() { + Some(state_id) => state_id.clone(), + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map: HashMap::new(), + }) + } + }; + + let mut status_map = HashMap::new(); + + let root_cache = self.storage_engine.root_cache(); + let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); + + for folder in sub_path.split(STATE_PATH_SEPARATOR) { + let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; + + if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { + let msg = format!( + "unmatch object type at path {} in folder {}, expect: ObjectMap, got: {:?}", + sub_path, + folder, + parent_state.object().obj_type_code() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let (parent, remain) = ObjectMap::raw_decode(parent_state.object_raw.as_slice()) + .map_err(|err| { + let msg = format!( + "decode failed at path {} in folder {}, {:?}", + sub_path, folder, err + ); + log::warn!("{}", msg); + BuckyError::new(err.code(), msg) + })?; + + assert_eq!(remain.len(), 0); + + status_map.insert(parent_state_id, parent_state); + + let sub_map_id = parent.get_by_key(&cache, folder).await?; + match sub_map_id { + Some(sub_map_id) => { + // for next folder + parent_state_id = sub_map_id; + } + None => { + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } + } + } + + let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + status_map.insert(parent_state_id, leaf_state); + + return Ok(GroupRPathStatus { + block_desc: header_block.named_object().desc().clone(), + certificate: qc.clone(), + status_map, + }); + } } diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs index 9fbc4eb4f..5d005a726 100644 --- a/src/component/cyfs-group/src/utils.rs +++ b/src/component/cyfs-group/src/utils.rs @@ -4,5 +4,5 @@ pub type Round = u64; pub enum IsCreateRPath { No, - Yes(Option), // init state + Yes, } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 2ba99716e..0401c55a0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -816,7 +816,7 @@ async fn main_run() { &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -845,7 +845,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); @@ -892,7 +892,7 @@ async fn main_run() { &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, - IsCreateRPath::Yes(None), + IsCreateRPath::Yes, ) .await .unwrap(); From 1dad2ec854f5632f61aed2c21b23554c41b365c3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 17:03:44 +0800 Subject: [PATCH 495/553] Example for APP-State as tree --- .../src/consensus/hotstuff/hotstuff.rs | 9 +- .../cyfs-group/src/dec/delegate_factory.rs | 10 +- .../src/storage/engine/storage_engine.rs | 2 +- .../engine/storage_engine_group_state.rs | 23 ++- .../cyfs-group/src/storage/group_storage.rs | 18 +- src/tests/group-example/src/main.rs | 155 +++++++++++++++--- 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 667966a6c..d9773bd88 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -9,13 +9,13 @@ use cyfs_base::{ use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupQuorumCertificateObject, GroupQuorumCertificate, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - consensus::{synchronizer::Synchronizer, proposal}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, @@ -499,7 +499,7 @@ impl HotstuffRunner { if self .delegate - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -851,6 +851,7 @@ impl HotstuffRunner { .on_commited( &proposal_obj, pre_state_id, + self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1528,7 +1529,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id).await { + match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index bdcb98f60..0b13d97ce 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, Group, ObjectId}; +use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -34,12 +34,14 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult; @@ -47,7 +49,13 @@ pub trait RPathDelegate: Sync + Send { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ); } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index eb0ede98f..cbb5d99df 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC, HotstuffTimeout}; pub struct FinishProposalMgr { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 604e44744..aae81394b 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -8,8 +8,8 @@ use cyfs_base::{ use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, - GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -672,3 +672,22 @@ fn map_not_found_option_to_option(r: BuckyResult>) -> BuckyResult Self { + Self { + state_mgr: state_mgr.clone(), + } + } +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { + async fn create_single_op_env(&self) -> BuckyResult { + self.state_mgr.create_single_op_env(ACCESS) + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index d233025ab..3a1c20f2a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -15,12 +15,15 @@ use cyfs_core::{ use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, }; use super::{ - engine::{StorageCacheInfo, StorageEngineGroupState, StorageEngineMock}, + engine::{ + GroupObjectMapProcessorGroupState, StorageCacheInfo, StorageEngineGroupState, + StorageEngineMock, + }, StorageEngine, }; @@ -50,6 +53,7 @@ pub struct GroupStorage { cache: StorageCacheInfo, storage_engine: StorageEngineGroupState, + object_map_processor: GroupObjectMapProcessorGroupState, } impl GroupStorage { @@ -71,6 +75,7 @@ impl GroupStorage { .expect("create group state failed."); let dec_group_state = group_state.get_dec_root_manager(dec_id, true).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -85,6 +90,7 @@ impl GroupStorage { ), local_device_id, cache: StorageCacheInfo::new(None), + object_map_processor, }) } @@ -129,6 +135,7 @@ impl GroupStorage { let state_path = GroupStatePath::new(rpath.to_string()); let cache = StorageEngineGroupState::load_cache(&dec_group_state, &non_driver, &state_path).await?; + let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { group, @@ -140,6 +147,7 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), local_device_id, cache, + object_map_processor, }) } @@ -905,4 +913,8 @@ impl GroupStorage { status_map, }); } + + pub fn get_object_map_processor(&self) -> &dyn GroupObjectMapProcessor { + &self.object_map_processor + } } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0401c55a0..0fae6dd53 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -38,16 +38,18 @@ mod Common { CyfsStackNOCParams, CyfsStackParams, }; - lazy_static::lazy_static! { - // pub static ref EXAMPLE_ADMINS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("admin", 4); - // pub static ref EXAMPLE_MEMBERS: Vec<((People, PrivateKey), (Device, PrivateKey))> = create_members("member", 9); + /** + * |--root + * |--folder1 + * |--folder2 + * |--value-->u64 + */ - // pub static ref EXAMPLE_GROUP: Group = create_group(&EXAMPLE_ADMINS.get(0).unwrap().0.0, EXAMPLE_ADMINS.iter().map(|m| &m.0.0).collect(), EXAMPLE_MEMBERS.iter().map(|m| &m.0.0).collect(), EXAMPLE_ADMINS.iter().map(|m| &m.1.0).collect()); - // pub static ref EXAMPLE_GROUP_CHUNK: ChunkMeta = ChunkMeta::from(&*EXAMPLE_GROUP); + lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - // pub static ref EXAMPLE_DEC_APP: DecApp = DecApp::create(EXAMPLE_ADMINS.get(0).unwrap().0.0.desc().object_id(), EXAMPLE_APP_NAME.as_str()); - // pub static ref EXAMPLE_DEC_APP_ID: DecAppId = DecAppId::try_from(EXAMPLE_DEC_APP.desc().object_id()).unwrap(); pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); + pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } fn create_member( @@ -495,7 +497,7 @@ mod Client { } mod GroupDecService { - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, fmt::format, sync::Arc}; use async_std::sync::Mutex; use cyfs_base::*; @@ -503,9 +505,11 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; + use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; use cyfs_stack::CyfsStack; + use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; + pub struct DecService {} impl DecService { @@ -580,17 +584,78 @@ mod GroupDecService { } impl MyRPathDelegate { - pub fn execute( + pub async fn get_value_from_state_tree_with_single_op_envs( + pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<( + Option, + Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + )> { + let mut single_op_envs = vec![]; + let mut parent_map_id = pre_state_id; + for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + let single_op_env = object_map_processor.create_single_op_env().await.expect( + format!( + "create_single_op_env load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + parent_map_id = match parent_map_id { + Some(parent_map_id) => { + single_op_env.load(&parent_map_id).await.expect( + format!( + "load folder {} parent with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + single_op_env.get_by_key(folder).await.expect( + format!( + "load folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ) + } + None => { + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!( + "create folder {} with obj_id {:?} failed", + folder, parent_map_id + ) + .as_str(), + ); + None + } + }; + single_op_envs.push((single_op_env, folder, parent_map_id)); + } + + Ok((parent_map_id, single_op_envs)) + } + + pub async fn execute( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let result_state_id = { + let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await?; + + let result_value = { /** * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_state_id.map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); + let pre_value = pre_value.map_or(0, |pre_value| { + let buf = pre_value.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) @@ -608,6 +673,32 @@ mod GroupDecService { .unwrap() }; + let result_state_id = { + let mut sub_folder_value = result_value; + for (parent_single_op_env, folder, sub_folder_prev_value) in + single_op_envs.into_iter().rev() + { + parent_single_op_env + .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + .await + .expect( + format!( + "update folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + sub_folder_value = parent_single_op_env.commit().await.expect( + format!( + "commit folder {} value from {:?} to {:?} failed", + folder, sub_folder_prev_value, sub_folder_value + ) + .as_str(), + ); + } + sub_folder_value + }; + let receipt = { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? @@ -623,7 +714,7 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_state_id + proposal + context + * (result_state_id, return_object) = pre_value + proposal + context */ Ok(ExecuteResult { context, @@ -632,17 +723,20 @@ mod GroupDecService { }) } - pub fn verify( + pub async fn verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) * == pre_state_id + proposal + execute_result.context */ - let result = self.execute(proposal, pre_state_id)?; + let result = self + .execute(proposal, pre_state_id, object_map_processor) + .await?; let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() @@ -658,23 +752,28 @@ mod GroupDecService { &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id) + self.execute(proposal, pre_state_id, object_map_processor) + .await } async fn on_verify( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) + self.verify(proposal, pre_state_id, object_map_processor, execute_result) + .await } async fn on_commited( &self, proposal: &GroupProposal, pre_state_id: Option, + object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { @@ -685,14 +784,28 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = pre_state_id.map_or(0, |pre_state_id| { + let pre_value = Self::get_value_from_state_tree_with_single_op_envs( + pre_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; pre_value.copy_from_slice(&buf[..8]); u64::from_be_bytes(pre_value) }); - let result_value = execute_result.result_state_id.map_or(0, |result_id| { + let result_value = Self::get_value_from_state_tree_with_single_op_envs( + execute_result.result_state_id, + object_map_processor, + ) + .await + .unwrap() + .0 + .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; result_value.copy_from_slice(&buf[..8]); @@ -901,7 +1014,7 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 10 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } From 09dcf2a04118b24f7c87d4d8e88595b9e5ef1217 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 19:51:46 +0800 Subject: [PATCH 496/553] Fix: Update the state structure, mount the template dec-state of blocks in prepare/pre-commit, to avoid it's recycled. --- .../cyfs-base/src/objects/object_map/mod.rs | 1 + .../cyfs-group/src/dec/delegate_factory.rs | 5 +- .../cyfs-group/src/statepath/design.md | 12 +- .../src/statepath/group_statepath.rs | 34 +++ .../src/storage/engine/storage_engine.rs | 20 +- .../engine/storage_engine_group_state.rs | 139 ++++++++-- .../src/storage/engine/storage_engine_mock.rs | 7 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 248 +++++++++++------- 9 files changed, 351 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-base/src/objects/object_map/mod.rs b/src/component/cyfs-base/src/objects/object_map/mod.rs index 3bbc5f131..75589834b 100644 --- a/src/component/cyfs-base/src/objects/object_map/mod.rs +++ b/src/component/cyfs-base/src/objects/object_map/mod.rs @@ -18,6 +18,7 @@ mod visitor; pub use access::*; pub use cache::*; pub use diff::*; +pub use isolate_path_env::*; pub use iterator::*; pub use object_map::*; pub use op_env::*; diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-group/src/dec/delegate_factory.rs index 0b13d97ce..f5092dbfc 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-group/src/dec/delegate_factory.rs @@ -1,4 +1,6 @@ -use cyfs_base::{BuckyResult, Group, ObjectId, ObjectMapSingleOpEnvRef}; +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -58,4 +60,5 @@ pub trait RPathDelegate: Sync + Send { #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; } diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index cb964e066..885888d5b 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -22,14 +22,20 @@ | |--users | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的轮次 +| |--last-vote-round-->u64 // 最后一次投票的 轮次 | |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 | | | |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 | |--str(${height})->block | | -| |--prepares->Set // Prepare状态的block -| |--pre-commits->Set // pre-commit状态的block +| |--prepares // Prepare状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) +| |--pre-commits // pre-commit状态的block +| | |--${block.id} +| | |--block +| | |--result-state-->ObjectId(result-state) | | | |--finish-proposals | | |--flip-time-->Timestamp // 取block时间戳 diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 72f48e601..0ed0abd25 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -10,6 +10,8 @@ pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; pub const GROUP_STATE_PATH_RANGE: &str = "range"; pub const GROUP_STATE_PATH_PREPARES: &str = "prepares"; pub const GROUP_STATE_PATH_PRE_COMMITS: &str = "pre-commits"; +pub const GROUP_STATE_PATH_BLOCK: &str = "block"; +pub const GROUP_STATE_PATH_RESULT_STATE: &str = "result-state"; pub const GROUP_STATE_PATH_FINISH_PROPOSALS: &str = "finish-proposals"; pub const GROUP_STATE_PATH_FLIP_TIME: &str = "flip-time"; pub const GROUP_STATE_PATH_RECYCLE: &str = "recycle"; @@ -164,10 +166,42 @@ impl GroupStatePath { self.prepares.as_str() } + pub fn prepares_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn prepares_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn pre_commits(&self) -> &str { self.pre_commits.as_str() } + pub fn pre_commits_block(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_BLOCK, + ]) + } + + pub fn pre_commits_result_state(&self, block_id: &ObjectId) -> String { + Self::join(&[ + self.prepares.as_str(), + block_id.to_string().as_str(), + GROUP_STATE_PATH_RESULT_STATE, + ]) + } + pub fn finish_proposals(&self) -> &str { self.finish_proposals.as_str() } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine.rs b/src/component/cyfs-group/src/storage/engine/storage_engine.rs index cbb5d99df..e14445695 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine.rs @@ -43,9 +43,19 @@ impl StorageCacheInfo { #[async_trait::async_trait] pub trait StorageWriter: Send + Sync { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()>; - async fn insert_pre_commit(&mut self, block_id: &ObjectId, is_instead: bool) - -> BuckyResult<()>; + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()>; + + async fn insert_pre_commit( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + is_instead: bool, + ) -> BuckyResult<()>; + async fn push_commit( &mut self, height: u64, @@ -54,7 +64,9 @@ pub trait StorageWriter: Send + Sync { prev_result_state_id: &Option, min_height: u64, ) -> BuckyResult<()>; + async fn remove_prepares(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()>; + async fn push_proposals( &mut self, proposal_ids: &[ObjectId], @@ -62,7 +74,9 @@ pub trait StorageWriter: Send + Sync { ) -> BuckyResult<()>; async fn set_last_vote_round(&mut self, round: u64, prev_value: u64) -> BuckyResult<()>; + async fn save_last_qc(&mut self, qc_id: &ObjectId) -> BuckyResult<()>; + async fn save_last_tc(&mut self, tc_id: &ObjectId) -> BuckyResult<()>; async fn commit(mut self) -> BuckyResult<()>; diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index aae81394b..8b8799207 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -2,14 +2,15 @@ use std::{collections::HashSet, sync::Arc}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectIdDataBuilder, ObjectMapContentItem, - ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, - ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, + ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, + ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; @@ -90,7 +91,8 @@ impl StorageEngineGroupState { None => None, }; - let prepare_block_ids = load_object_ids_with_path(&op_env, state_path.prepares()).await?; + let prepare_block_ids = + load_object_ids_with_path_map_key(&op_env, state_path.prepares()).await?; if prepare_block_ids.len() == 0 && commit_range.is_none() { return Err(BuckyError::new( BuckyErrorCode::NotFound, @@ -99,7 +101,7 @@ impl StorageEngineGroupState { } let pre_commit_block_ids = - load_object_ids_with_path(&op_env, state_path.pre_commits()).await?; + load_object_ids_with_path_map_key(&op_env, state_path.pre_commits()).await?; let flip_timestamp = op_env.get_by_path(state_path.flip_time()).await; let flip_timestamp = map_not_found_option_to_option(flip_timestamp)?.map_or(0, |id| { @@ -113,8 +115,10 @@ impl StorageEngineGroupState { n }); - let adding_proposal_ids = load_object_ids_with_path(&op_env, state_path.adding()).await?; - let over_proposal_ids = load_object_ids_with_path(&op_env, state_path.recycle()).await?; + let adding_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.adding()).await?; + let over_proposal_ids = + load_object_ids_with_path_set(&op_env, state_path.recycle()).await?; let load_block_ids = [ first_header_block_ids.as_slice(), @@ -233,7 +237,7 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new(ObjectMapSimpleContentType::Map) .await?; None } else { @@ -253,20 +257,51 @@ impl StorageEngineGroupStateWriter { }) } - async fn insert_prepares_inner(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn create_block_result_object_map( + &self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult { + let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; + single_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await?; + single_op_env + .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) + .await?; + if let Some(state_id) = result_state_id.as_ref() { + single_op_env + .insert_with_key(GROUP_STATE_PATH_RESULT_STATE, state_id) + .await?; + } + + single_op_env.commit().await + } + + async fn insert_prepares_inner( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) + .await?; self.prepare_op_env - .insert(block_id) + .insert_with_key(block_id.to_string().as_str(), &block_result_pair) .await - .map(|is_changed| assert!(is_changed)) } async fn insert_pre_commit_inner( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); if is_instead { self.op_env @@ -274,12 +309,17 @@ impl StorageEngineGroupStateWriter { .await?; } - let is_changed = self - .op_env - .insert(self.state_path.pre_commits(), block_id) + let block_result_pair = self + .create_block_result_object_map(block_id, result_state_id) .await?; - assert!(is_changed); - Ok(()) + + self.op_env + .insert_with_key( + self.state_path.pre_commits(), + block_id.to_string().as_str(), + &block_result_pair, + ) + .await } async fn push_commit_inner( @@ -357,8 +397,11 @@ impl StorageEngineGroupStateWriter { async fn remove_prepares_inner(&mut self, block_ids: &[ObjectId]) -> BuckyResult<()> { for block_id in block_ids { - let is_changed = self.prepare_op_env.remove(block_id).await?; - assert!(is_changed); + let block_result_pair = self + .prepare_op_env + .remove_with_key(block_id.to_string().as_str(), &None) + .await?; + assert!(block_result_pair.is_some()); } Ok(()) } @@ -486,19 +529,26 @@ impl StorageEngineGroupStateWriter { #[async_trait::async_trait] impl StorageWriter for StorageEngineGroupStateWriter { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_prepares_inner(block_id).await; + self.write_result = self.insert_prepares_inner(block_id, result_state_id).await; self.write_result.clone() } async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { self.write_result.as_ref().map_err(|e| e.clone())?; - self.write_result = self.insert_pre_commit_inner(block_id, is_instead).await; + self.write_result = self + .insert_pre_commit_inner(block_id, result_state_id, is_instead) + .await; self.write_result.clone() } @@ -614,7 +664,7 @@ fn parse_u64_obj(obj: &ObjectId) -> u64 { u64::from_le_bytes(buf) } -async fn load_object_ids_with_path( +async fn load_object_ids_with_path_set( op_env: &ObjectMapPathOpEnvRef, full_path: &str, ) -> BuckyResult> { @@ -647,6 +697,41 @@ async fn load_object_ids_with_path( Ok(object_ids) } +async fn load_object_ids_with_path_map_key( + op_env: &ObjectMapPathOpEnvRef, + full_path: &str, +) -> BuckyResult> { + let content = match op_env.list(full_path).await { + Ok(content) => content, + Err(err) => { + log::warn!("list by path {} failed {:?}", full_path, err); + if err.code() == BuckyErrorCode::NotFound { + return Ok(vec![]); + } else { + return Err(err); + } + } + }; + + let mut object_ids: Vec = vec![]; + for item in content.list.iter() { + match item { + ObjectMapContentItem::Map((key_id_base58, _)) => { + object_ids.push(ObjectId::from_base58(key_id_base58)?) + } + _ => { + log::error!("should be a set in path {}", full_path); + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + format!("should be a set in path {}", full_path), + )); + } + } + } + + Ok(object_ids) +} + fn map_not_found_to_option(r: BuckyResult) -> BuckyResult> { match r { Ok(t) => Ok(Some(t)), @@ -690,4 +775,8 @@ impl GroupObjectMapProcessor for GroupObjectMapProcessorGroupState { async fn create_single_op_env(&self) -> BuckyResult { self.state_mgr.create_single_op_env(ACCESS) } + + async fn create_sub_tree_op_env(&self) -> BuckyResult { + self.state_mgr.create_isolate_path_op_env(ACCESS) + } } diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs index ebeedd7ca..fbc7cafdc 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_mock.rs @@ -71,7 +71,11 @@ pub struct StorageEngineMockWriter<'a> { #[async_trait::async_trait] impl<'a> StorageWriter for StorageEngineMockWriter<'a> { - async fn insert_prepares(&mut self, block_id: &ObjectId) -> BuckyResult<()> { + async fn insert_prepares( + &mut self, + block_id: &ObjectId, + result_state_id: &Option, + ) -> BuckyResult<()> { if !self.engine.prepare_blocks.insert(block_id.clone()) { assert!(false); return Err(BuckyError::new( @@ -85,6 +89,7 @@ impl<'a> StorageWriter for StorageEngineMockWriter<'a> { async fn insert_pre_commit( &mut self, block_id: &ObjectId, + result_state_id: &Option, is_instead: bool, ) -> BuckyResult<()> { if !self.engine.prepare_blocks.remove(block_id) { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a1c20f2a..491d029dd 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -291,10 +291,16 @@ impl GroupStorage { */ // storage let mut writer = self.storage_engine.create_writer().await?; - writer.insert_prepares(block_id.object_id()).await?; - if let Some((new_pre_commit, _)) = new_pre_commit.as_ref() { + writer + .insert_prepares(block_id.object_id(), block.result_state_id()) + .await?; + if let Some((new_pre_commit_id, new_pre_commit)) = new_pre_commit.as_ref() { writer - .insert_pre_commit(new_pre_commit, new_header.is_some()) + .insert_pre_commit( + new_pre_commit_id, + new_pre_commit.result_state_id(), + new_header.is_some(), + ) .await?; } if let Some(new_header) = new_header.as_ref() { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 0fae6dd53..394b15acb 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -584,59 +584,59 @@ mod GroupDecService { } impl MyRPathDelegate { - pub async fn get_value_from_state_tree_with_single_op_envs( - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, - ) -> BuckyResult<( - Option, - Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - )> { - let mut single_op_envs = vec![]; - let mut parent_map_id = pre_state_id; - for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - let single_op_env = object_map_processor.create_single_op_env().await.expect( - format!( - "create_single_op_env load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - parent_map_id = match parent_map_id { - Some(parent_map_id) => { - single_op_env.load(&parent_map_id).await.expect( - format!( - "load folder {} parent with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - single_op_env.get_by_key(folder).await.expect( - format!( - "load folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ) - } - None => { - single_op_env - .create_new(ObjectMapSimpleContentType::Map) - .await - .expect( - format!( - "create folder {} with obj_id {:?} failed", - folder, parent_map_id - ) - .as_str(), - ); - None - } - }; - single_op_envs.push((single_op_env, folder, parent_map_id)); - } - - Ok((parent_map_id, single_op_envs)) - } + // pub async fn get_value_from_state_tree_with_single_op_envs( + // pre_state_id: Option, + // object_map_processor: &dyn GroupObjectMapProcessor, + // ) -> BuckyResult<( + // Option, + // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, + // )> { + // let mut single_op_envs = vec![]; + // let mut parent_map_id = pre_state_id; + // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { + // let single_op_env = object_map_processor.create_single_op_env().await.expect( + // format!( + // "create_single_op_env load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // parent_map_id = match parent_map_id { + // Some(parent_map_id) => { + // single_op_env.load(&parent_map_id).await.expect( + // format!( + // "load folder {} parent with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // single_op_env.get_by_key(folder).await.expect( + // format!( + // "load folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ) + // } + // None => { + // single_op_env + // .create_new(ObjectMapSimpleContentType::Map) + // .await + // .expect( + // format!( + // "create folder {} with obj_id {:?} failed", + // folder, parent_map_id + // ) + // .as_str(), + // ); + // None + // } + // }; + // single_op_envs.push((single_op_env, folder, parent_map_id)); + // } + + // Ok((parent_map_id, single_op_envs)) + // } pub async fn execute( &self, @@ -644,11 +644,30 @@ mod GroupDecService { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - let (pre_value, single_op_envs) = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await?; + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + let pre_value = match pre_state_id { + Some(pre_state_id) => { + state_op_env.load(&pre_state_id).await?; + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ) + } + None => { + state_op_env + .create_new(ObjectMapSimpleContentType::Map) + .await + .expect( + format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), + ); + None + } + }; let result_value = { /** @@ -674,29 +693,50 @@ mod GroupDecService { }; let result_state_id = { - let mut sub_folder_value = result_value; - for (parent_single_op_env, folder, sub_folder_prev_value) in - single_op_envs.into_iter().rev() - { - parent_single_op_env - .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - .await - .expect( - format!( - "update folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value - ) - .as_str(), - ); - sub_folder_value = parent_single_op_env.commit().await.expect( + state_op_env + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .await + .expect( format!( - "commit folder {} value from {:?} to {:?} failed", - folder, sub_folder_prev_value, sub_folder_value + "set_with_path {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value ) .as_str(), ); - } - sub_folder_value + state_op_env.commit().await.expect( + format!( + "commit {:?} from {:?} to {} failed", + EXAMPLE_VALUE_PATH.as_str(), + pre_value, + result_value + ) + .as_str(), + ) + // let mut sub_folder_value = result_value; + // for (parent_single_op_env, folder, sub_folder_prev_value) in + // single_op_envs.into_iter().rev() + // { + // parent_single_op_env + // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) + // .await + // .expect( + // format!( + // "update folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // sub_folder_value = parent_single_op_env.commit().await.expect( + // format!( + // "commit folder {} value from {:?} to {:?} failed", + // folder, sub_folder_prev_value, sub_folder_value + // ) + // .as_str(), + // ); + // } + // sub_folder_value }; let receipt = { @@ -784,13 +824,26 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = Self::get_value_from_state_tree_with_single_op_envs( - pre_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let pre_value = match pre_state_id { + Some(pre_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&pre_state_id) + .await + .expect(format!("load {} failed", pre_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |pre_state_id| { let buf = pre_state_id.data(); let mut pre_value = [0u8; 8]; @@ -798,13 +851,26 @@ mod GroupDecService { u64::from_be_bytes(pre_value) }); - let result_value = Self::get_value_from_state_tree_with_single_op_envs( - execute_result.result_state_id, - object_map_processor, - ) - .await - .unwrap() - .0 + let result_value = match execute_result.result_state_id { + Some(result_state_id) => { + let state_op_env = object_map_processor + .create_sub_tree_op_env() + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + state_op_env + .load(&result_state_id) + .await + .expect(format!("load {} failed", result_state_id).as_str()); + state_op_env + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .expect( + format!("get_by_path {:?} failed", EXAMPLE_VALUE_PATH.as_str()) + .as_str(), + ) + } + None => None, + } .map_or(0, |result_id| { let buf = result_id.data(); let mut result_value = [0u8; 8]; From b4bffb5f423b5f31b762f5dedaec95f7bb1ad50a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:00 +0800 Subject: [PATCH 497/553] Accept the invalid block with vote it. --- src/component/cyfs-group/Cargo.toml | 1 + .../src/consensus/hotstuff/hotstuff.rs | 138 +++++++++++++----- .../cyfs-group/src/storage/group_storage.rs | 102 +------------ 3 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index aaab4ed76..4a7aae6c2 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = '1.4' sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' +itertools = "0.10.3" cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d9773bd88..511b0b32e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -13,6 +13,7 @@ use cyfs_core::{ }; use cyfs_lib::NONObjectInfo; use futures::FutureExt; +use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, @@ -365,7 +366,7 @@ impl HotstuffRunner { } } - let (prev_block, proposals) = match self.check_block_linked(&block, remote).await { + let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, Err(err) => return err }; @@ -391,9 +392,6 @@ impl HotstuffRunner { self, block.block_id()); - self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await?; - self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -402,7 +400,7 @@ impl HotstuffRunner { self.advance_round(tc.round).await; } - self.process_block(block, remote, &proposals).await + self.process_block(block, remote, &HashMap::new()).await } fn check_block_result_state(block: &GroupConsensusBlock) -> BuckyResult<()> { @@ -574,7 +572,7 @@ impl HotstuffRunner { } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result<(Option, HashMap), BuckyResult<()>> { + async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { match self.store.block_linked(block).await .map_err(|err| Err(err))? { @@ -585,16 +583,6 @@ impl HotstuffRunner { ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } - crate::storage::BlockLinkState::DuplicateProposal => { - log::warn!( - "[hotstuff] local: {:?}, receive block with duplicate proposal.", - self - ); - Err (Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicate proposal", - ))) - } crate::storage::BlockLinkState::Duplicate => { log::warn!( "[hotstuff] local: {:?}, receive duplicate block.", @@ -605,7 +593,7 @@ impl HotstuffRunner { "duplicate block", ))) } - crate::storage::BlockLinkState::Link(prev_block, proposals) => { + crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( "[hotstuff] local: {:?}, receive in-order block, height: {}.", self, @@ -614,7 +602,7 @@ impl HotstuffRunner { // 顺序连接状态 Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; - Ok((prev_block, proposals)) + Ok(prev_block) } crate::storage::BlockLinkState::Pending => { log::warn!( @@ -942,20 +930,6 @@ impl HotstuffRunner { return None; } - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 - let mut proposal_temp: HashMap = HashMap::new(); - if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { - Ok(_) => proposals = &proposal_temp, - Err(_) => return None - } - } else { - assert_eq!(proposals.len(), block.proposals().len()); - } - if !Self::check_timestamp_precision(block, proposals) { - return None; - } - // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -982,6 +956,22 @@ impl HotstuffRunner { return None; } + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block.clone()), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None + }, + }, + None => None + }; + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -993,6 +983,77 @@ impl HotstuffRunner { } } + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + let mut proposal_temp: HashMap = HashMap::new(); + if proposals.len() == 0 && block.proposals().len() > 0 { + match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + Ok(_) => proposals = &proposal_temp, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + return None + } + } + } else { + assert_eq!(proposals.len(), block.proposals().len()); + } + + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + return None; + } + + if proposals.len() != block.proposals().len() { + let mut dup_proposals = block.proposals().clone(); + dup_proposals.sort_unstable_by_key(|p| p.proposal); + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + ); + return None; + } + + let check_proposal_results = + futures::future::join_all(block.proposals().iter().map(|proposal_result| async { + match block.prev_block_id() { + Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) + .await.map(|is_finished| (is_finished, &proposal_result.proposal)), + None => Ok((false, &proposal_result.proposal)) + } + })) + .await; + + for check_result in check_proposal_results { + match check_result { + Ok((is_finished, proposal_id)) => { + if is_finished { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + self, + block.block_id(), + proposal_id + ); + return None; + } + }, + Err(err) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", + self, + block.block_id(), + err + ); + return None; + }, + } + } + + if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) + .await.is_err() { + return None; + } + log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1021,12 +1082,23 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, proposals: &HashMap) -> bool { + fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { false } else { + if let Some(prev_block) = prev_block { + let prev_block_time = bucky_time_to_system_time( + prev_block.named_object().desc().create_time(), + ); + if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { + if duration > TIME_PRECISION { + return false + } + } + } + for proposal in block.proposals() { let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 491d029dd..04e4c80fc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,22 +1,19 @@ -use std::{ - collections::{HashMap, HashSet}, - time::SystemTime, -}; +use std::collections::{HashMap, HashSet}; use cyfs_base::{ - bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupQuorumCertificateObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, TIME_PRECISION, + NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ @@ -31,11 +28,10 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, - DuplicateProposal, Duplicate, Link( Option, - HashMap, + // HashMap, ), // Pending, InvalidBranch, @@ -528,18 +524,6 @@ impl GroupStorage { return Ok(BlockLinkState::Duplicate); } - let now = SystemTime::now(); - let block_time = bucky_time_to_system_time(block.named_object().desc().create_time()); - - if let Ok(duration) = block_time.duration_since(now) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } - log::debug!( "[group storage] {} block_linked {} step2", self.local_device_id, @@ -554,17 +538,6 @@ impl GroupStorage { } else if prev_block.round() >= block.round() { return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); } else { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); - if let Ok(duration) = prev_block_time.duration_since(block_time) { - if duration > TIME_PRECISION { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - } Some(prev_block) } } @@ -592,66 +565,7 @@ impl GroupStorage { block.block_id() ); - let mut proposals = HashMap::new(); - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - if let Some(prev_block_id) = block.prev_block_id() { - if self - .is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await? - { - return Ok(BlockLinkState::DuplicateProposal); - } - } - - let proposal = self - .non_driver - .get_proposal(&proposal_result.proposal, Some(block.owner())) - .await?; - - let proposal_time = bucky_time_to_system_time(proposal.desc().create_time()); - if block_time - .duration_since(proposal_time) - .or(proposal_time.duration_since(block_time)) - .unwrap() - > TIME_PRECISION - { - return Err(BuckyError::new( - BuckyErrorCode::ErrorTimestamp, - "error timestamp", - )); - } - - Ok(BlockLinkState::Link( - None, - HashMap::from([(proposal_result.proposal, proposal)]), - )) - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok(result) => match result { - BlockLinkState::Link(_, proposal) => { - let (proposal_id, proposal) = proposal.into_iter().next().unwrap(); - if proposals.get(&proposal_id).is_some() { - return Ok(BlockLinkState::DuplicateProposal); - } - proposals.insert(proposal_id, proposal); - } - _ => return Ok(result), - }, - _ => return check_result, - } - } - - log::debug!( - "[group storage] {} block_linked {} step4", - self.local_device_id, - block.block_id() - ); - - Ok(BlockLinkState::Link(prev_block, proposals)) + Ok(BlockLinkState::Link(prev_block)) } pub fn find_block_in_cache(&self, block_id: &ObjectId) -> BuckyResult { From bee578f62c559da11dbed54f0881c5197e88173a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 24 Feb 2023 21:35:55 +0800 Subject: [PATCH 498/553] Chore unused code --- src/component/cyfs-group/src/storage/group_storage.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 04e4c80fc..122ae72ab 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -29,10 +29,7 @@ const PROPOSAL_MAX_TIMEOUT_AS_MICRO_SEC: u64 = PROPOSAL_MAX_TIMEOUT.as_micros() pub enum BlockLinkState { Expired, Duplicate, - Link( - Option, - // HashMap, - ), // + Link(Option), // Pending, InvalidBranch, } From de6c91285364ffe5841d9b0579db1ac34591bc2f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 12:20:23 +0800 Subject: [PATCH 499/553] get VerifiableState from the admin --- .../src/consensus/hotstuff/hotstuff.rs | 260 +++++++++++------- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 2 +- src/component/cyfs-group/src/constant.rs | 2 +- .../src/dec_state/dec_state_requestor.rs | 5 + .../cyfs-group/src/dec_state/state_pusher.rs | 2 +- .../src/objects/group_rpath_status.rs | 21 +- .../cyfs-group/src/objects/protocol.rs | 11 +- .../cyfs-group/src/storage/dec_storage.rs | 6 + .../cyfs-group/src/storage/group_storage.rs | 27 +- src/tests/group-example/Cargo.toml | 3 +- src/tests/group-example/src/main.rs | 79 +++++- 11 files changed, 302 insertions(+), 116 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 511b0b32e..10c5d9635 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -4,7 +4,7 @@ use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, + RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ @@ -19,11 +19,13 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, }; /** * TODO: generate empty block when the 'Node' is synchronizing + * + * synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -212,6 +214,7 @@ struct HotstuffRunner { round: u64, // 当前轮次 high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, + max_quorum_round: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -311,6 +314,7 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, + max_quorum_round: round - 1, state_pusher, tx_block_gen, rx_block_gen, @@ -366,15 +370,6 @@ impl HotstuffRunner { } } - let prev_block = match self.check_block_linked(&block, remote).await { - Ok(link) => link, - Err(err) => return err - }; - - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", - self, - block.block_id()); - self.committee .verify_block(block, remote) .await @@ -388,6 +383,18 @@ impl HotstuffRunner { err })?; + let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); + self.update_max_quorum_round(quorum_round); + + log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + self, + block.block_id()); + + let prev_block = match self.check_block_linked(&block, remote).await { + Ok(link) => link, + Err(err) => return err + }; + log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", self, block.block_id()); @@ -452,10 +459,19 @@ impl HotstuffRunner { block: &GroupConsensusBlock, proposals: &HashMap, prev_block: &Option, + remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = prev_block - .as_ref() - .map_or(None, |block| block.result_state_id().clone()); + let mut prev_state_id = match prev_block + .as_ref() { + Some(prev_block) => { + let result_state_id = block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; + } + result_state_id.clone() + }, + None => None + }; for proposal_exe_info in block.proposals() { // 去重 @@ -672,7 +688,7 @@ impl HotstuffRunner { err })?; - if let Some(header_block) = new_header_block.map(|b| b.0.clone()) { + if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed", self, header_block.block_id() @@ -696,29 +712,18 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(header_block.clone(), qc_block).await; + self.notify_block_committed(&header_block, &old_header_block, qc_block).await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", self, block.block_id() ); - let leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get leader in round {} failed {:?}", - self, self.round, err - ); - - err - }); - // notify by leader - if let Ok(leader) = leader { - if self.local_device_id == leader { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } + if &self.local_id == header_block.owner() { + self.state_pusher + .notify_block_commit(header_block, qc_block.clone()) + .await; } log::debug!( @@ -733,7 +738,7 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, the qc of block {:?} has received before", self, block.block_id() ); - return self.process_block_qc(qc, block, remote).await; + return self.process_block_qc(qc, block).await; }, VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( @@ -762,7 +767,7 @@ impl HotstuffRunner { return Ok(()); } - if let Some(vote) = self.make_vote(block, proposals).await { + if let Some(vote) = self.make_vote(block, proposals, &remote).await { log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", self, block.block_id(), block.round()); @@ -791,22 +796,12 @@ impl HotstuffRunner { Ok(()) } - async fn notify_block_committed(&self, new_header: GroupConsensusBlock, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - let mut pre_state_id = match new_header.prev_block_id() { - Some(block_id) => self - .non_driver - .get_block(block_id, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get prev-block {:?} before commit-notify failed {:?}", - self, block_id, err - ); - err - })? - .result_state_id() - .clone(), - None => None, - }; + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { + assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); + + let mut pre_state_id = old_header_block + .as_ref() + .map_or(None, |b| b.result_state_id().clone()); for proposal in new_header.proposals() { let proposal_obj = self @@ -900,6 +895,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_round(&mut self, quorum_round: u64) { + if quorum_round > self.max_quorum_round { + self.max_quorum_round = quorum_round; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -922,7 +923,7 @@ impl HotstuffRunner { .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap) -> Option { + async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -930,6 +931,13 @@ impl HotstuffRunner { return None; } + if self.max_quorum_round >= self.round { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } + // round只能逐个递增 let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); let is_valid_round = if block.round() == qc_round + 1 { @@ -1002,6 +1010,10 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + self, + block.block_id(), + ); return None; } @@ -1016,44 +1028,15 @@ impl HotstuffRunner { return None; } - let check_proposal_results = - futures::future::join_all(block.proposals().iter().map(|proposal_result| async { - match block.prev_block_id() { - Some(prev_block_id) => self.store.is_proposal_finished(&proposal_result.proposal, prev_block_id) - .await.map(|is_finished| (is_finished, &proposal_result.proposal)), - None => Ok((false, &proposal_result.proposal)) - } - })) - .await; - - for check_result in check_proposal_results { - match check_result { - Ok((is_finished, proposal_id)) => { - if is_finished { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", - self, - block.block_id(), - proposal_id - ); - return None; - } - }, - Err(err) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore check duplicate failed {:?}", - self, - block.block_id(), - err - ); - return None; - }, - } + if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err + ); + return None; } - if self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block) - .await.is_err() { - return None; - } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, block.block_id(), block.round()); @@ -1075,7 +1058,12 @@ impl HotstuffRunner { } }; - if self.store.set_last_vote_round(block.round()).await.is_err() { + if let Err(err) = self.store.set_last_vote_round(block.round()).await { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for update last-vote-round failed {:?}", + self, + block.block_id(), + err + ); return None; } @@ -1086,23 +1074,39 @@ impl HotstuffRunner { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + block.block_id(), + block_timestamp, + now + ); + false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time( - prev_block.named_object().desc().create_time(), - ); + let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + block.block_id(), + block_timestamp, + prev_block_time + ); return false } } } for proposal in block.proposals() { - let proposal = proposals.get(&proposal.proposal).expect("should load all proposals"); + let proposal_id = proposal.proposal; + let proposal = proposals.get(&proposal_id).expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { + log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + block.block_id(), + block_timestamp, + proposal_id, + proposal_timestamp + ); return false } } @@ -1174,7 +1178,7 @@ impl HotstuffRunner { if is_prev_none {"None"} else {"Some"} ); - self.process_block_qc(qc, &block, remote).await?; + self.process_block_qc(qc, &block).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1185,7 +1189,6 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, - remote: ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1334,7 +1337,10 @@ impl HotstuffRunner { .collect::>(), max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); - + + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1453,6 +1459,9 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); + let quorum_round = tc.round; + self.update_max_quorum_round(quorum_round); + self.store.save_tc(&tc).await?; self.advance_round(tc.round).await; @@ -1501,8 +1510,7 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ) - .await.map_err(|err| { + ).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", self, err @@ -1541,7 +1549,13 @@ impl HotstuffRunner { proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); let prev_block = match self.high_qc.as_ref() { - Some(qc) => Some(self.store.find_block_in_cache(&qc.block_id)?), + Some(qc) => { + let prev_block = self.store.find_block_in_cache(&qc.block_id)?; + if let Some(result_state_id) = prev_block.result_state_id() { + self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + } + Some(prev_block) + }, None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1940,6 +1954,58 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } + async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 + let obj_map_processor = self.store.get_object_map_processor(); + + #[async_recursion::async_recursion] + async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if non_driver.get_object(&root_id, None).await.is_ok() { + // TODO: 可能有下级分支子树因为异常不齐全 + return Ok(()); + } + let obj = non_driver.get_object(root_id, Some(remote)).await?; + match obj.object.as_ref() { + Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { + let single_op_env = obj_map_processor.create_single_op_env().await?; + single_op_env.load(root_id).await?; + loop { + let branchs = single_op_env.next(16).await?; + for branch in branchs.list.iter() { + let branch_id = match branch { + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Map(map) => &map.1, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + }, + cyfs_base::ObjectMapContentItem::Set(set) => set, + }; + make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + } + + if branchs.list.len() < 16 { + return Ok(()) + } + } + }, + _ => return Ok(()) + } + } + + let mut result = Ok(()); + for remote in remotes { + result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + if result.is_ok() { + return result; + } + } + result + } + async fn recover(&mut self) { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 82f4017a0..f44260a04 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, Signature, + BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 1170176b2..77a652a7e 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -17,7 +17,7 @@ pub const TIME_PRECISION: Duration = Duration::from_millis(60000); pub const PROPOSAL_MAX_TIMEOUT: Duration = Duration::from_secs(3600); pub const SYNCHRONIZER_TIMEOUT: u64 = 500; pub const SYNCHRONIZER_TRY_TIMES: usize = 3; -pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(1000); +pub const CLIENT_POLL_TIMEOUT: Duration = Duration::from_millis(5000); pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 0a3544c09..790429c6c 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -154,6 +154,11 @@ impl DecStateRequestorRunner { .await .map(|r| r.cloned()); + log::debug!( + "handle_verifiable_state sub_path: {}, result: {:?}", + sub_path, + result + ); self.query_state_notifier.reply(&sub_path, result).await } Err(e) => self.query_state_notifier.reply(&sub_path, Err(e)).await, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index cc0b4aff2..b1506a192 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -13,7 +13,7 @@ use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), - BlockCommit(GroupConsensusBlock, GroupConsensusBlock), + BlockCommit(GroupConsensusBlock, GroupConsensusBlock), // LastStateRequest(ObjectId), DelayBroadcast, } diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group/src/objects/group_rpath_status.rs index 858c37fff..bfc9bc5d2 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group/src/objects/group_rpath_status.rs @@ -69,8 +69,25 @@ impl<'de> RawDecode<'de> for GroupRPathStatus { assert_eq!(remain.len(), 0); let mut status_map = HashMap::new(); for obj_buf in proto.status_list.iter() { - let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; - assert_eq!(remain.len(), 0); + log::debug!("will decode len: {}", obj_buf.len()); + // size + object_id + let status = if obj_buf.len() > OBJECT_ID_LEN + 1 { + let (status, remain) = NONObjectInfo::raw_decode(obj_buf.as_slice())?; + assert_eq!(remain.len(), 0); + status + } else if obj_buf.len() == OBJECT_ID_LEN + 1 { + NONObjectInfo::new( + ObjectId::clone_from_slice(&obj_buf.as_slice()[1..])?, + obj_buf.clone(), + None, + ) + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidData, + "expect NONObjectInfo", + )); + }; + status_map.insert(status.object_id, status); } diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/objects/protocol.rs index 6c9f89e96..932e5cd46 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/objects/protocol.rs @@ -7,6 +7,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_lib::NONObjectInfo; +use itertools::Itertools; use sha2::Digest; use crate::GroupRPathStatus; @@ -185,12 +186,13 @@ impl std::fmt::Debug for HotstuffMessage { result.as_ref().map(|status| { let desc = status.block_desc.content(); format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ) }) ) @@ -315,12 +317,13 @@ impl std::fmt::Debug for HotstuffPackage { |status| { let desc = status.block_desc.content(); let ok = format!( - "({:?}/{:?}, {}/{}/{})", + "({:?}/{:?}, {}/{}/{}) sub-count: {:?}", desc.result_state_id(), status.block_desc.object_id(), desc.height(), desc.round(), - status.certificate.round + status.certificate.round, + status.status_map.iter().map(|(key, _)| key).collect_vec() ); Ok(ok) } diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index de5a0fd4a..60a45724f 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -69,6 +69,10 @@ impl DecStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } + let parent_state = match verifiable_status.status_map.get(&parent_state_id) { Some(state) => state, None => return Ok(None), @@ -98,6 +102,8 @@ impl DecStorage { assert_eq!(remain.len(), 0); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 122ae72ab..966fa518a 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, - ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, + ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, @@ -223,7 +223,13 @@ impl GroupStorage { pub async fn push_block( &mut self, block: GroupConsensusBlock, - ) -> BuckyResult)>> { + ) -> BuckyResult< + Option<( + &GroupConsensusBlock, + Option, + Vec, + )>, + > { let header_height = self.header_height(); assert!(block.height() > header_height && block.height() <= header_height + 3); @@ -399,9 +405,10 @@ impl GroupStorage { } } - self.cache.header_block = Some(new_header); + let old_header_block = self.cache.header_block.replace(new_header); return Ok(Some(( self.cache.header_block.as_ref().unwrap(), + old_header_block, removed_blocks, ))); } @@ -736,6 +743,7 @@ impl GroupStorage { } pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult { + // TODO: 需要一套通用的同步ObjectMap树的实现 let (header_block, qc) = match self.cache.header_block.as_ref() { Some(block) => { let (_, qc_block) = self @@ -778,6 +786,9 @@ impl GroupStorage { let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone()); for folder in sub_path.split(STATE_PATH_SEPARATOR) { + if folder.len() == 0 { + continue; + } let parent_state = self.non_driver.get_object(&parent_state_id, None).await?; if ObjectTypeCode::ObjectMap != parent_state.object().obj_type_code() { @@ -806,6 +817,8 @@ impl GroupStorage { status_map.insert(parent_state_id, parent_state); let sub_map_id = parent.get_by_key(&cache, folder).await?; + log::debug!("get sub-folder {} result: {:?}", folder, sub_map_id); + match sub_map_id { Some(sub_map_id) => { // for next folder @@ -821,7 +834,11 @@ impl GroupStorage { } } - let leaf_state = self.non_driver.get_object(&parent_state_id, None).await?; + let leaf_state = if parent_state_id.is_data() { + NONObjectInfo::new(parent_state_id, parent_state_id.to_vec()?, None) + } else { + self.non_driver.get_object(&parent_state_id, None).await? + }; status_map.insert(parent_state_id, leaf_state); return Ok(GroupRPathStatus { diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 0053ccd5f..01094f12a 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -27,4 +27,5 @@ cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } -cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } \ No newline at end of file +cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 394b15acb..618336df4 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -14,7 +14,7 @@ use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME}; +use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; mod Common { use std::{fmt::format, io::ErrorKind, sync::Arc}; @@ -505,8 +505,15 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + use cyfs_group::{ + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, + }; + use cyfs_lib::{ + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, + }; use cyfs_stack::CyfsStack; + use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -522,10 +529,42 @@ mod GroupDecService { Box::new(GroupRPathDelegateFactory { local_name }), ) .await - .unwrap() + .unwrap(); + + // let source = RequestSourceInfo { + // protocol: todo!(), + // zone: todo!(), + // dec: todo!(), + // verified: todo!(), + // }; + + // cyfs_stack + // .router_handlers() + // .handlers(&RouterHandlerChain::PostRouter) + // .post_object() + // .add_handler(RouterHandler::new()); } } + // pub struct PostProposalRoutine { + // controller: RPathControl, + // } + + // #[async_trait::async_trait] + // impl EventListenerAsyncRoutine + // for PostProposalRoutine + // { + // async fn call( + // &self, + // param: &NONPostObjectInputRequest, + // ) -> BuckyResult { + // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; + // assert_eq!(remain.len(), 0); + // self.controller.push_proposal(proposal).await?; + // Ok(NONPostObjectInputResponse { object: None }) + // } + // } + pub struct GroupRPathDelegateFactory { local_name: String, } @@ -778,6 +817,16 @@ mod GroupDecService { .execute(proposal, pre_state_id, object_map_processor) .await?; + log::info!( + "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + execute_result.result_state_id, + execute_result.context.is_none(), + execute_result.receipt.is_none(), + result.result_state_id, + result.context.is_none(), + result.receipt.is_none() + ); + let is_ok = execute_result.result_state_id == result.result_state_id && execute_result.context.is_none() && execute_result.receipt.is_none(); @@ -1007,7 +1056,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 1000usize; + let PROPOSAL_COUNT = 5usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1085,6 +1134,28 @@ async fn main_run() { log::info!("will push new proposals, i: {}", i); } } + + let client = admin_stacks + .get(0) + .unwrap() + .group_mgr() + .rpath_client( + &group.desc().object_id(), + dec_app_id.object_id(), + &EXAMPLE_RPATH, + ) + .await + .unwrap(); + + let value_obj = client + .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + .await + .unwrap(); + let buf = value_obj.as_ref().unwrap().object_id.data(); + let mut value = [0u8; 8]; + value.copy_from_slice(&buf[..8]); + + log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From 70e84256bec025e932eec199ed2f4474979cb0b1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 27 Feb 2023 15:46:00 +0800 Subject: [PATCH 500/553] Fix: result-state verify failed --- .../src/consensus/hotstuff/hotstuff.rs | 29 +++++++++++++++---- src/tests/group-example/src/main.rs | 3 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 10c5d9635..e142d4069 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -464,7 +464,7 @@ impl HotstuffRunner { let mut prev_state_id = match prev_block .as_ref() { Some(prev_block) => { - let result_state_id = block.result_state_id(); + let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; } @@ -520,14 +520,24 @@ impl HotstuffRunner { err })? { + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); + prev_state_id = proposal_exe_info.result_state; } else { log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}, expect-result: {:?}", + "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", self, proposal_exe_info.proposal, - prev_state_id, - proposal_exe_info.result_state + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() ); return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); @@ -966,7 +976,7 @@ impl HotstuffRunner { let prev_block = match block.prev_block_id() { Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block.clone()), + Ok(block) => Some(block), Err(_) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", self, @@ -1960,11 +1970,18 @@ impl HotstuffRunner { #[async_recursion::async_recursion] async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + if root_id.is_data() { + return Ok(()); + } + if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await?; + let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { + log::warn!("get branch {} failed {:?}", root_id, err); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { let single_op_env = obj_map_processor.create_single_op_env().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 618336df4..4daa0d4f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -818,7 +818,8 @@ mod GroupDecService { .await?; log::info!( - "verify expect: {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + pre_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), From 22868769d9489075bae6bc09fa6b41a1c801b78b Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 28 Feb 2023 20:27:49 +0800 Subject: [PATCH 501/553] Redefine the Group object for Permission --- .../protos/standard_objects-permission.proto | 203 ++++++++++++++++++ src/tests/group-example/src/main.rs | 8 +- 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto new file mode 100644 index 000000000..b2ec61f60 --- /dev/null +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -0,0 +1,203 @@ +syntax="proto3"; + +// contract +message ContractBodyContent { + bytes data = 1; +} + +// device +message DeviceBodyContent { + repeated bytes endpoints = 1; + repeated bytes sn_list = 2; + repeated bytes passive_pn_list = 3; + optional string name = 4; + optional uint32 bdt_version = 5; +} + +// dir +message DirBodyContent { + enum Type { + Chunk = 0; + ObjList = 1; + } + Type type = 1; + optional bytes chunk_id = 2; + + // 使用list编码hash_map + message ObjItem { + bytes obj_id = 1; + bytes value = 2; + } + repeated ObjItem obj_list = 3; +} + +// file +message ChunkList { + enum Type { + ChunkInList = 0; + ChunkInFile = 1; + ChunkInBundle = 2; + } + enum HashMethod { + Serial = 0; + } + + Type type = 1; + repeated bytes chunk_id_list = 2; + bytes file_id = 3; + optional HashMethod hash_method = 4; +} + +message FileBodyContent { + ChunkList chunk_list = 1; +} + +// people +message PeopleBodyContent { + repeated bytes ood_list = 1; + optional string name = 2; + optional bytes icon = 3; + optional string ood_work_mode = 4; +} + +message GroupRPathPermissionWeight { + string rpath = 1; + GroupFunctionPermissionWeight weight = 2; +} + +message GroupDecPermissionWeight { + bytes dec_id = 1; + optional GroupRPathPermissionWeight default_dec_weight = 2; + repeated GroupRPathPermissionWeight rpath_weight = 3; +} + +message GroupMember { + bytes id = 1; + string title = 2; + // uint64 shares = 3; delay + optional GroupGlobalPermissionWeight global_weight = 4; + optional GroupDecPermissionWeight weight = 5; +} + +/** +admin 修改管理员列表 +member 修改成员列表 +display-${scope} 修改展示信息 + ${scope}=g: 修改group信息 + ${scope}=s: 修改自身信息 + ${scope}=m: 修改任意member信息 + ${scope}=a: 修改任意admin信息 +property 修改资产信息 +conclusion 修改决议类别列表 +conclusion-${category} 修改决议类别配置 +it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) +c-${any} 其他自定义(custom)权限 +*/ + +message GroupGlobalPermissionWeight { + optional uint32 admin = 1; + optional uint32 member = 2; + optional uint32 display_group = 3; + optional uint32 display_self = 4; + optional uint32 display_member = 5; + optional uint32 display_admin = 6; + optional uint32 property = 7; +} + +message GroupCommonPermissionWeight { + string category = 1; + uint32 weight = 2; +} + +message GroupFunctionPermissionWeight { + optional uint32 it = 1; + optional uint32 conclusion = 2; + repeated GroupCommonPermissionWeight conclusion_category = 3; + repeated GroupCommonPermissionWeight custom = 4; +} + +message GroupITConfig { + repeated bytes ood_list = 8; + optional uint64 history_block_max = 9; + optional uint64 history_block_lifespan = 10; + optional uint64 consensus_interval = 11; // ms +} + +message GroupConclusionConfig { + string category = 1; + uint64 lifespan = 2; // ms +} + +message GroupConfigItem { + optional GroupITConfig it = 1; + repeated GroupConclusionConfig conclusions = 2; + optional GroupFunctionPermissionWeight weight_threshold = 3; +} + +message GroupRPathConfig { + string rpath = 1; + GroupConfigItem config = 2; +} + +message GroupDecConfig { + bytes dec_id = 1; + optional GroupConfigItem default_dec_config = 2; + repeated GroupRPathConfig rpath_configs = 3; +} + +message CommonGroupBodyContent { + string name = 1; + optional bytes icon = 2; + string description = 3; + + repeated GroupMember members = 4; + + // uint64 total_equity = 5; // delay + + repeated bytes revoked_conclusions = 6; + + GroupConfigItem default_config = 7; + repeated GroupDecConfig dec_configs = 8; + + GroupGlobalPermissionWeight global_weight_threshold = 9; + GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + + uint64 version = 11; +} + +// simple_group +message SimpleGroupDescContent { + bytes unique_id = 1; + bytes founder_id = 2; + repeated GroupMember admins = 3; +} + +message SimpleGroupBodyContent { + CommonGroupBodyContent common = 1; +} + +// org +message OrgDescContent { + bytes unique_id = 1; + bytes founder_id = 2; +} + +message OrgBodyContent { + repeated GroupMember admins = 1; + optional bytes token_contract = 2; + CommonGroupBodyContent common = 3; +} + +// tx +message TxBodyContent { + bytes data = 1; +} + +// proof_of_service +message ProofData { + bytes data = 1; +} + +message ProofOfServiceBodyContent { + ProofData data = 1; +} \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 4daa0d4f1..ef2366de0 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1051,13 +1051,13 @@ async fn main_run() { .unwrap(); } - async_std::task::sleep(Duration::from_millis(30000)).await; + async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 5usize; + let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; @@ -1130,12 +1130,14 @@ async fn main_run() { control.push_proposal(proposal).await.unwrap(); }); - if i % 1 == 0 { + if i % 10 == 0 { async_std::task::sleep(Duration::from_millis(1000)).await; log::info!("will push new proposals, i: {}", i); } } + async_std::task::sleep(Duration::from_millis(10000)).await; + let client = admin_stacks .get(0) .unwrap() From 02d7727d05fc480a0beaf645b3ea6f45073b384d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 14:41:55 +0800 Subject: [PATCH 502/553] Simplify group definition --- .../protos/standard_objects-permission.proto | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto index b2ec61f60..09f9e3684 100644 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ b/src/component/cyfs-base/protos/standard_objects-permission.proto @@ -60,89 +60,9 @@ message PeopleBodyContent { optional string ood_work_mode = 4; } -message GroupRPathPermissionWeight { - string rpath = 1; - GroupFunctionPermissionWeight weight = 2; -} - -message GroupDecPermissionWeight { - bytes dec_id = 1; - optional GroupRPathPermissionWeight default_dec_weight = 2; - repeated GroupRPathPermissionWeight rpath_weight = 3; -} - message GroupMember { bytes id = 1; string title = 2; - // uint64 shares = 3; delay - optional GroupGlobalPermissionWeight global_weight = 4; - optional GroupDecPermissionWeight weight = 5; -} - -/** -admin 修改管理员列表 -member 修改成员列表 -display-${scope} 修改展示信息 - ${scope}=g: 修改group信息 - ${scope}=s: 修改自身信息 - ${scope}=m: 修改任意member信息 - ${scope}=a: 修改任意admin信息 -property 修改资产信息 -conclusion 修改决议类别列表 -conclusion-${category} 修改决议类别配置 -it 修改DEC运行配置(ood_list/history_block_max/history_block_lifespan/consensus_interval) -c-${any} 其他自定义(custom)权限 -*/ - -message GroupGlobalPermissionWeight { - optional uint32 admin = 1; - optional uint32 member = 2; - optional uint32 display_group = 3; - optional uint32 display_self = 4; - optional uint32 display_member = 5; - optional uint32 display_admin = 6; - optional uint32 property = 7; -} - -message GroupCommonPermissionWeight { - string category = 1; - uint32 weight = 2; -} - -message GroupFunctionPermissionWeight { - optional uint32 it = 1; - optional uint32 conclusion = 2; - repeated GroupCommonPermissionWeight conclusion_category = 3; - repeated GroupCommonPermissionWeight custom = 4; -} - -message GroupITConfig { - repeated bytes ood_list = 8; - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms -} - -message GroupConclusionConfig { - string category = 1; - uint64 lifespan = 2; // ms -} - -message GroupConfigItem { - optional GroupITConfig it = 1; - repeated GroupConclusionConfig conclusions = 2; - optional GroupFunctionPermissionWeight weight_threshold = 3; -} - -message GroupRPathConfig { - string rpath = 1; - GroupConfigItem config = 2; -} - -message GroupDecConfig { - bytes dec_id = 1; - optional GroupConfigItem default_dec_config = 2; - repeated GroupRPathConfig rpath_configs = 3; } message CommonGroupBodyContent { @@ -152,17 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - // uint64 total_equity = 5; // delay - - repeated bytes revoked_conclusions = 6; - - GroupConfigItem default_config = 7; - repeated GroupDecConfig dec_configs = 8; - - GroupGlobalPermissionWeight global_weight_threshold = 9; - GroupFunctionPermissionWeight default_rpath_weight_threshold = 10; + repeated bytes ood_list = 5; - uint64 version = 11; + optional bytes prev_version = 6; + uint64 version_num = 7; } // simple_group @@ -184,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx From 1e44e7302d92e34d17df1ccaf055079e83532983 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 1 Mar 2023 20:16:27 +0800 Subject: [PATCH 503/553] Move the interface to cyfs-lib --- .../src/consensus/hotstuff/hotstuff.rs | 8 +++--- .../cyfs-group/src/dec/group_manager.rs | 6 ++--- src/component/cyfs-group/src/dec/mod.rs | 6 ++--- .../cyfs-group/src/dec/rpath_control.rs | 3 ++- .../engine/storage_engine_group_state.rs | 6 ++--- .../cyfs-group/src/storage/group_storage.rs | 6 ++--- .../src/group}/delegate_factory.rs | 2 +- .../cyfs-lib/src/group/group_manager.rs | 20 ++++++++++++++ src/component/cyfs-lib/src/group/mod.rs | 7 +++++ .../cyfs-lib/src/group/rpath_client.rs | 27 +++++++++++++++++++ src/component/cyfs-lib/src/lib.rs | 6 +++-- src/tests/group-example/src/main.rs | 8 +++--- 12 files changed, 79 insertions(+), 26 deletions(-) rename src/component/{cyfs-group/src/dec => cyfs-lib/src/group}/delegate_factory.rs (98%) create mode 100644 src/component/cyfs-lib/src/group/group_manager.rs create mode 100644 src/component/cyfs-lib/src/group/mod.rs create mode 100644 src/component/cyfs-lib/src/group/rpath_client.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e142d4069..52dcdd650 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,15 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - ExecuteResult, GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, - PendingProposalConsumer, RPathDelegate, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, GroupObjectMapProcessor, + GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, }; /** diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7b7fbbbe..60ddba1fb 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -6,11 +6,11 @@ use cyfs_base::{ }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; use crate::{ - storage::GroupStorage, DelegateFactory, HotstuffMessage, HotstuffPackage, IsCreateRPath, - NONDriver, NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, + NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index b4e753a27..8a43844b2 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,11 +1,9 @@ // dec framework -mod delegate_factory; +mod group_manager; mod rpath_client; mod rpath_control; -mod group_manager; -pub use delegate_factory::*; +pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; -pub use group_manager::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index 7abff1ec1..c3a25b060 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,10 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathDelegate, + PendingProposalHandler, PendingProposalMgr, }; struct RPathControlRaw { diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 8b8799207..adf11c7e4 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,11 +6,11 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; +use cyfs_lib::GroupObjectMapProcessor; use crate::{ - GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, - GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, - GROUP_STATE_PATH_RESULT_STATE, + GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, + GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 966fa518a..fa6f4930f 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,11 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupObjectMapProcessor, GroupRPathStatus, GroupStatePath, - NONDriverHelper, PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/dec/delegate_factory.rs b/src/component/cyfs-lib/src/group/delegate_factory.rs similarity index 98% rename from src/component/cyfs-group/src/dec/delegate_factory.rs rename to src/component/cyfs-lib/src/group/delegate_factory.rs index f5092dbfc..9e55ff8f4 100644 --- a/src/component/cyfs-group/src/dec/delegate_factory.rs +++ b/src/component/cyfs-lib/src/group/delegate_factory.rs @@ -1,8 +1,8 @@ +use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-lib/src/group/group_manager.rs new file mode 100644 index 000000000..7d836ae49 --- /dev/null +++ b/src/component/cyfs-lib/src/group/group_manager.rs @@ -0,0 +1,20 @@ +use cyfs_base::{BuckyResult, ObjectId}; + +use crate::{DelegateFactory, RPathClient}; + +#[derive(Clone)] +pub struct GroupManager; + +impl GroupManager { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn unregister(&self) { + unimplemented!() + } + + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-lib/src/group/mod.rs new file mode 100644 index 000000000..482d9ea0d --- /dev/null +++ b/src/component/cyfs-lib/src/group/mod.rs @@ -0,0 +1,7 @@ +mod delegate_factory; +mod group_manager; +mod rpath_client; + +pub use delegate_factory::*; +pub use group_manager::*; +pub use rpath_client::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-lib/src/group/rpath_client.rs new file mode 100644 index 000000000..4162abe68 --- /dev/null +++ b/src/component/cyfs-lib/src/group/rpath_client.rs @@ -0,0 +1,27 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, +}; +use cyfs_core::{GroupProposal, GroupRPath}; + +use crate::NONObjectInfo; + +struct RPathClientRaw {} + +#[derive(Clone)] +pub struct RPathClient(Arc); + +impl RPathClient { + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn post_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { + unimplemented!() + } +} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index f74e62985..d2f02315a 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,9 +4,11 @@ mod base; mod crypto; mod default_app; mod events; +mod group; mod ndn; mod non; mod prelude; +mod requestor; mod rmeta; mod root_state; mod router_handler; @@ -17,7 +19,6 @@ mod trans; mod util; mod ws; mod zone; -mod requestor; pub use crate::util::*; pub use acl::*; @@ -26,9 +27,11 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; +pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; +pub use requestor::*; pub use rmeta::*; pub use root_state::*; pub use router_handler::*; @@ -38,7 +41,6 @@ pub use sync::*; pub use trans::*; pub use ws::*; pub use zone::*; -pub use requestor::*; // 重新导出cache相关接口,由于bdt层的依赖关系,只能放在util工程 pub use cyfs_util::cache::*; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index ef2366de0..42544e51c 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,12 +505,10 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, RPathControl, RPathDelegate, - }; + use cyfs_group::RPathControl; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, + DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, + NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, }; use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; From 363e060feda1dd3d746f1ac42ce01b96558e49b1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 12:20:30 +0800 Subject: [PATCH 504/553] Remove the `decide` from proposal, It seems unuseful --- .../cyfs-core/protos/core_objects.proto | 9 +- .../cyfs-core/src/group/group_proposal.rs | 415 +++++++++--------- src/component/cyfs-core/src/group/mod.rs | 10 +- 3 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 487ece4bd..abd299e9d 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -352,7 +352,7 @@ message GroupProposalDescContent { message GroupProposalBodyContent { optional bytes payload = 1; - +/* message Signature { bytes signature = 1; // sign(hash(ProposalId, proponent_id, decide)) bytes proponent_id = 2; @@ -360,8 +360,10 @@ message GroupProposalBodyContent { } repeated Signature decide_signatures = 2; +*/ } +/* message GroupUpdateGroupPropsalParam { repeated bytes target_dec_id = 1; // the proccesor decs optional bytes from_chunk_id = 2; // Chunk(Encode(Group)) @@ -373,6 +375,7 @@ message GroupPropsalDecideParam { bytes proposal_id = 2; bytes decide = 3; } +*/ message HotstuffBlockQc { bytes block_id = 1; @@ -431,6 +434,7 @@ message GroupConsensusBlockBodyContent { optional HotstuffTimeout tc = 3; } +/* message GroupActionDescContent { // target GroupRPath r_path = 1; @@ -441,4 +445,5 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 10aeed798..bf28aafb2 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,4 +1,4 @@ -use crate::{CoreObjectType, GroupPropsalDecideParam, GroupRPath}; +use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; use sha2::Digest; @@ -34,45 +34,44 @@ impl DescContent for GroupProposalDescContent { type PublicKeyType = SubDescNone; } -#[derive(Clone)] -pub struct GroupProposalSignature { - signature: Signature, - proponent_id: ObjectId, - decide: Vec, -} - -impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> - for GroupProposalSignature -{ - fn transform( - value: &crate::codec::protos::group_proposal_body_content::Signature, - ) -> BuckyResult { - Ok(Self { - signature: Signature::raw_decode(value.signature.as_slice())?.0, - proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, - decide: value.decide.clone(), - }) - } -} - -impl ProtobufTransform<&GroupProposalSignature> - for crate::codec::protos::group_proposal_body_content::Signature -{ - fn transform(value: &GroupProposalSignature) -> BuckyResult { - Ok(Self { - signature: value.signature.to_vec()?, - proponent_id: value.proponent_id.to_vec()?, - decide: value.decide.clone(), - }) - } -} +// #[derive(Clone)] +// pub struct GroupProposalSignature { +// signature: Signature, +// proponent_id: ObjectId, +// decide: Vec, +// } + +// impl ProtobufTransform<&crate::codec::protos::group_proposal_body_content::Signature> +// for GroupProposalSignature +// { +// fn transform( +// value: &crate::codec::protos::group_proposal_body_content::Signature, +// ) -> BuckyResult { +// Ok(Self { +// signature: Signature::raw_decode(value.signature.as_slice())?.0, +// proponent_id: ObjectId::raw_decode(value.proponent_id.as_slice())?.0, +// decide: value.decide.clone(), +// }) +// } +// } + +// impl ProtobufTransform<&GroupProposalSignature> +// for crate::codec::protos::group_proposal_body_content::Signature +// { +// fn transform(value: &GroupProposalSignature) -> BuckyResult { +// Ok(Self { +// signature: value.signature.to_vec()?, +// proponent_id: value.proponent_id.to_vec()?, +// decide: value.decide.clone(), +// }) +// } +// } #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Default)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalBodyContent)] pub struct GroupProposalBodyContent { payload: Option>, - - decide_signatures: Vec, + // decide_signatures: Vec, } impl BodyContent for GroupProposalBodyContent { @@ -85,14 +84,14 @@ impl ProtobufTransform for GroupProposalBodyContent { fn transform(value: crate::codec::protos::GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push(GroupProposalSignature::transform(sign)?); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push(GroupProposalSignature::transform(sign)?); + // } Ok(Self { payload: value.payload, - decide_signatures, + // decide_signatures, }) } } @@ -101,16 +100,16 @@ impl ProtobufTransform<&GroupProposalBodyContent> for crate::codec::protos::GroupProposalBodyContent { fn transform(value: &GroupProposalBodyContent) -> BuckyResult { - let mut decide_signatures = vec![]; - for sign in value.decide_signatures.as_slice() { - decide_signatures.push( - crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, - ); - } + // let mut decide_signatures = vec![]; + // for sign in value.decide_signatures.as_slice() { + // decide_signatures.push( + // crate::codec::protos::group_proposal_body_content::Signature::transform(sign)?, + // ); + // } Ok(Self { payload: value.payload.clone(), - decide_signatures, + // decide_signatures, }) } } @@ -143,17 +142,17 @@ impl GroupProposalDescContent { } impl GroupProposalBodyContent { - fn hash_decide_signature( - proposal_id: &ObjectId, - proponent_id: &ObjectId, - decide: &[u8], - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(proposal_id.as_slice()); - sha256.input(proponent_id.as_slice()); - sha256.input(decide); - sha256.result().into() - } + // fn hash_decide_signature( + // proposal_id: &ObjectId, + // proponent_id: &ObjectId, + // decide: &[u8], + // ) -> HashValue { + // let mut sha256 = sha2::Sha256::new(); + // sha256.input(proposal_id.as_slice()); + // sha256.input(proponent_id.as_slice()); + // sha256.input(decide); + // sha256.result().into() + // } } #[async_trait] @@ -182,27 +181,27 @@ pub trait GroupProposalObject { fn payload(&self) -> &Option>; fn set_payload(&mut self, payload: Option>); - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult>; - - fn decided_members_no_verify(&self) -> &Vec; - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult; - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()>; + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult>; + + // fn decided_members_no_verify(&self) -> &Vec; + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult; + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()>; } #[async_trait] @@ -231,7 +230,7 @@ impl GroupProposalObject for GroupProposal { desc, GroupProposalBodyContent { payload, - decide_signatures: vec![], + // decide_signatures: vec![], }, ) .create_time(timestamp.map_or(bucky_time_now(), |t| t)) @@ -252,9 +251,7 @@ impl GroupProposalObject for GroupProposal { fn params_hash(&self) -> BuckyResult> { match &self.desc().content().params { - Some(params) => { - HashValue::try_from(params.as_slice()).map(|h| Some(h)) - } + Some(params) => HashValue::try_from(params.as_slice()).map(|h| Some(h)), None => Ok(None), } } @@ -298,134 +295,130 @@ impl GroupProposalObject for GroupProposal { self.body_mut().as_mut().unwrap().content_mut().payload = payload; } - async fn verify_member_decide( - &self, - member_id: &ObjectId, - public_key: &PublicKey, - ) -> BuckyResult> { - let signs = self - .body() - .as_ref() - .unwrap() - .content() - .decide_signatures - .as_slice(); - - let proposal_id = self.desc().object_id(); - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - - let mut decides = vec![]; - - for sign in signs { - if &sign.proponent_id == member_id { - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &sign.proponent_id, - sign.decide.as_slice(), - ); - - if verifier.verify(hash.as_slice(), &sign.signature).await { - decides.push(sign.decide.as_slice()); - } else { - return Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )); - } - } - } - - Ok(decides) - } - - fn decided_members_no_verify(&self) -> &Vec { - &self.body().as_ref().unwrap().content().decide_signatures - } - - async fn decide( - &self, - member_id: ObjectId, - decide: Vec, - private_key: &PrivateKey, - ) -> BuckyResult { - let signs = &self.body().as_ref().unwrap().content().decide_signatures; - - if signs.iter().find(|s| s.proponent_id == member_id).is_some() { - return Err(BuckyError::new( - BuckyErrorCode::AlreadyExists, - "duplicated decide", - )); - } - - let proposal_id = self.desc().object_id(); - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.as_slice(), - ); - - let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); - let sign = signer - .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) - .await?; - - Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) - } - - async fn verify_and_merge_decide( - &mut self, - decide: &GroupPropsalDecideParam, - member_id: ObjectId, - public_key: &PublicKey, - ) -> BuckyResult<()> { - let proposal_id = self.desc().object_id(); - - if decide.proposal_id() != &proposal_id { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - format!( - "proposal id not match for decide signature: {}/{}", - proposal_id, - decide.proposal_id() - ), - )); - } - - let hash = GroupProposalBodyContent::hash_decide_signature( - &proposal_id, - &member_id, - decide.decide(), - ); - - let verifier = RsaCPUObjectVerifier::new(public_key.clone()); - if verifier.verify(hash.as_slice(), decide.signature()).await { - let signs = &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .decide_signatures; - for exist in signs.iter() { - if &exist.proponent_id == &member_id && exist.decide == decide.decide() { - return Ok(()); - } - } - - signs.push(GroupProposalSignature { - signature: decide.signature().clone(), - proponent_id: member_id, - decide: Vec::from(decide.decide()), - }); - - Ok(()) - } else { - Err(BuckyError::new( - BuckyErrorCode::InvalidSignature, - "invalid signature", - )) - } - } + // async fn verify_member_decide( + // &self, + // member_id: &ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult> { + // let signs = self + // .body() + // .as_ref() + // .unwrap() + // .content() + // .decide_signatures + // .as_slice(); + + // let proposal_id = self.desc().object_id(); + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + + // let mut decides = vec![]; + + // for sign in signs { + // if &sign.proponent_id == member_id { + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &sign.proponent_id, + // sign.decide.as_slice(), + // ); + + // if verifier.verify(hash.as_slice(), &sign.signature).await { + // decides.push(sign.decide.as_slice()); + // } else { + // return Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )); + // } + // } + // } + + // Ok(decides) + // } + + // async fn decide( + // &self, + // member_id: ObjectId, + // decide: Vec, + // private_key: &PrivateKey, + // ) -> BuckyResult { + // let signs = &self.body().as_ref().unwrap().content().decide_signatures; + + // if signs.iter().find(|s| s.proponent_id == member_id).is_some() { + // return Err(BuckyError::new( + // BuckyErrorCode::AlreadyExists, + // "duplicated decide", + // )); + // } + + // let proposal_id = self.desc().object_id(); + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.as_slice(), + // ); + + // let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + // let sign = signer + // .sign(hash.as_slice(), &SignatureSource::RefIndex(0)) + // .await?; + + // Ok(GroupPropsalDecideParam::new(sign, proposal_id, decide)) + // } + + // async fn verify_and_merge_decide( + // &mut self, + // decide: &GroupPropsalDecideParam, + // member_id: ObjectId, + // public_key: &PublicKey, + // ) -> BuckyResult<()> { + // let proposal_id = self.desc().object_id(); + + // if decide.proposal_id() != &proposal_id { + // return Err(BuckyError::new( + // BuckyErrorCode::NotMatch, + // format!( + // "proposal id not match for decide signature: {}/{}", + // proposal_id, + // decide.proposal_id() + // ), + // )); + // } + + // let hash = GroupProposalBodyContent::hash_decide_signature( + // &proposal_id, + // &member_id, + // decide.decide(), + // ); + + // let verifier = RsaCPUObjectVerifier::new(public_key.clone()); + // if verifier.verify(hash.as_slice(), decide.signature()).await { + // let signs = &mut self + // .body_mut() + // .as_mut() + // .unwrap() + // .content_mut() + // .decide_signatures; + // for exist in signs.iter() { + // if &exist.proponent_id == &member_id && exist.decide == decide.decide() { + // return Ok(()); + // } + // } + + // signs.push(GroupProposalSignature { + // signature: decide.signature().clone(), + // proponent_id: member_id, + // decide: Vec::from(decide.decide()), + // }); + + // Ok(()) + // } else { + // Err(BuckyError::new( + // BuckyErrorCode::InvalidSignature, + // "invalid signature", + // )) + // } + // } } #[cfg(test)] diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index b2885d637..4310f48a5 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -1,13 +1,15 @@ mod group_consensus_block; mod group_proposal; -mod group_proposal_decide_param; +// mod group_proposal_decide_param; mod group_quorum_certificate; mod group_rpath; -mod group_update_group_proposal_param; +// mod group_update_group_proposal_param; +mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; -pub use group_proposal_decide_param::*; +// pub use group_proposal_decide_param::*; pub use group_quorum_certificate::*; pub use group_rpath::*; -pub use group_update_group_proposal_param::*; +// pub use group_update_group_proposal_param::*; +pub use group_protocol::*; From a943eab91350a504058f903b6237f559691db42e Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 2 Mar 2023 20:52:45 +0800 Subject: [PATCH 505/553] Prepare for export interface to SDK --- .../cyfs-core/protos/core_objects.proto | 2 +- src/component/cyfs-core/src/coreobj.rs | 1 + src/component/cyfs-core/src/group/mod.rs | 2 - src/component/cyfs-group-lib/Cargo.toml | 34 ++ .../{cyfs-group => cyfs-group-lib}/build.rs | 27 +- .../protos/group_bft_protocol.proto | 63 +++ src/component/cyfs-group-lib/readme.md | 14 + .../src/delegate.rs} | 18 +- .../src}/group_manager.rs | 6 +- .../mod.rs => cyfs-group-lib/src/lib.rs} | 6 +- .../cyfs-group-lib/src/objects/certificate.rs | 190 ++++++++ .../cyfs-group-lib/src/objects/codec/mod.rs | 3 + .../src/objects/group_command.rs | 428 ++++++++++++++++++ .../src/objects/group_decide_proposal.rs | 0 .../src/objects/group_rpath_status.rs | 6 +- .../src/objects/group_update_proposal.rs | 0 .../cyfs-group-lib/src/objects/mod.rs | 12 + .../src}/rpath_client.rs | 3 +- src/component/cyfs-group/Cargo.toml | 3 +- .../protos/group_bft_protocol.proto | 23 - .../src/consensus/hotstuff/hotstuff.rs | 60 +-- .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 7 +- .../cyfs-group/src/dec/group_events.rs | 42 ++ .../cyfs-group/src/dec/group_manager.rs | 94 ++-- src/component/cyfs-group/src/dec/mod.rs | 2 + .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec/rpath_control.rs | 8 +- .../src/dec_state/dec_state_requestor.rs | 6 +- .../src/dec_state/dec_state_synchronizer.rs | 64 +-- .../cyfs-group/src/dec_state/state_pusher.rs | 8 +- src/component/cyfs-group/src/helper/mod.rs | 2 - src/component/cyfs-group/src/helper/verify.rs | 16 - src/component/cyfs-group/src/lib.rs | 4 - src/component/cyfs-group/src/network/mod.rs | 2 + .../src/{objects => network}/protocol.rs | 306 +++---------- src/component/cyfs-group/src/objects/mod.rs | 9 - .../cyfs-group/src/storage/dec_storage.rs | 9 +- .../engine/storage_engine_group_state.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 7 +- src/component/cyfs-group/src/utils.rs | 8 - src/component/cyfs-lib/src/lib.rs | 2 - 42 files changed, 977 insertions(+), 529 deletions(-) create mode 100644 src/component/cyfs-group-lib/Cargo.toml rename src/component/{cyfs-group => cyfs-group-lib}/build.rs (66%) create mode 100644 src/component/cyfs-group-lib/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group-lib/readme.md rename src/component/{cyfs-lib/src/group/delegate_factory.rs => cyfs-group-lib/src/delegate.rs} (81%) rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/group_manager.rs (100%) rename src/component/{cyfs-lib/src/group/mod.rs => cyfs-group-lib/src/lib.rs} (56%) create mode 100644 src/component/cyfs-group-lib/src/objects/certificate.rs create mode 100644 src/component/cyfs-group-lib/src/objects/codec/mod.rs create mode 100644 src/component/cyfs-group-lib/src/objects/group_command.rs rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_decide_proposal.rs (100%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_rpath_status.rs (93%) rename src/component/{cyfs-group => cyfs-group-lib}/src/objects/group_update_proposal.rs (100%) create mode 100644 src/component/cyfs-group-lib/src/objects/mod.rs rename src/component/{cyfs-lib/src/group => cyfs-group-lib/src}/rpath_client.rs (94%) delete mode 100644 src/component/cyfs-group/protos/group_bft_protocol.proto create mode 100644 src/component/cyfs-group/src/dec/group_events.rs delete mode 100644 src/component/cyfs-group/src/helper/verify.rs rename src/component/cyfs-group/src/{objects => network}/protocol.rs (70%) delete mode 100644 src/component/cyfs-group/src/objects/mod.rs delete mode 100644 src/component/cyfs-group/src/utils.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index abd299e9d..742c14904 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -446,4 +446,4 @@ message GroupActionDescContent { optional uint64 value = 4; optional bytes conclusion = 5; } -*/ \ No newline at end of file +*/ diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 3d53a082f..8eb96a930 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -66,6 +66,7 @@ pub enum CoreObjectType { GroupConsensusBlock = 702, GroupAction = 704, GroupQuorumCertificate = 705, + GroupCommand = 706, // IM通用对象 AddFriend = 1001, diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 4310f48a5..d7134a3c0 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,7 +4,6 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_protocol; pub use group_consensus_block::*; pub use group_proposal::*; @@ -12,4 +11,3 @@ pub use group_proposal::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; -pub use group_protocol::*; diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml new file mode 100644 index 000000000..e7cfda851 --- /dev/null +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -0,0 +1,34 @@ + +[package] +name = 'cyfs-group-lib' +version = '0.1.1' +authors = ['zhangzhen '] +edition = '2021' +license = 'BSD-2-Clause' +description = 'Rust cyfs-group package' + +[build-dependencies] +prost-build = { version = '0.9.0' } +protoc-rust = '2' +chrono = '0.4' +protoc-bin-vendored = '3' + +[dependencies] +async-trait = "0.1.53" +async-std = '1.11' +log = '0.4' +serde_json = '1.0' +futures = '0.3.25' +serde = { version = '1.0', features = ['derive'] } +prost = { version = '0.11.5' } +protobuf = { version = '2', features = ['with-bytes'] } +lazy_static = '1.4' +sha2 = { version = '0.8' } +async-recursion = '1.0' +rand = '0.8.5' +itertools = "0.10.3" +cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } +cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } +cyfs-debug = { path = "../../component/cyfs-debug" } +cyfs-lib = { path = '../../component/cyfs-lib' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/build.rs b/src/component/cyfs-group-lib/build.rs similarity index 66% rename from src/component/cyfs-group/build.rs rename to src/component/cyfs-group-lib/build.rs index 8d4efe9c9..206d6bc6f 100644 --- a/src/component/cyfs-group/build.rs +++ b/src/component/cyfs-group-lib/build.rs @@ -37,28 +37,13 @@ fn gen_protos() { } fn main() { - println!("cargo:rerun-if-env-changed=VERSION"); - println!("cargo:rerun-if-env-changed=CHANNEL"); - println!("cargo:rerun-if-env-changed=TARGET"); - println!( - "cargo:rustc-env=VERSION={}", - std::env::var("VERSION").unwrap_or("0".to_owned()) - ); - println!( - "cargo:rustc-env=CHANNEL={}", - std::env::var("CHANNEL").unwrap_or("nightly".to_owned()) - ); - println!( - "cargo:rustc-env=TARGET={}", - std::env::var("TARGET").unwrap() - ); - + println!("cargo:rerun-if-changed=protos"); println!( - "cargo:rustc-env=BUILDDATE={}", - chrono::Local::today().format("%y-%m-%d") + "cargo:warning={}", + format!( + "cyfs-core run build script, OUT_DIR={}", + std::env::var("OUT_DIR").unwrap() + ) ); - - println!("cargo:rerun-if-changed=protos"); - gen_protos(); } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto new file mode 100644 index 000000000..2bfdd8d21 --- /dev/null +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -0,0 +1,63 @@ + +syntax = "proto3"; + +message HotstuffBlockQCVote { + bytes block_id = 1; + optional bytes prev_block_id = 2; + uint64 round = 3; + bytes voter = 4; + bytes signature = 5; +} + +message HotstuffTimeoutVote { + optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) + uint64 round = 2; + bytes voter = 3; + bytes signature = 4; +} + +message GroupRPathStatus { + bytes block_desc = 1; // GroupConsensusBlockDescContent + bytes certificate = 2; // HotstuffBlockQC for block + repeated bytes status_list = 4; // Array> +} + +// GroupCommand + +message GroupCommandDescContent { + +} + +message GroupCommandNewRPath { + bytes group_id = 1; + string rpath = 2; + optional bytes with_block = 3; // Block.to_vec() +} + +message GroupCommandExecute { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId +} + +message GroupCommandExecuteResult { + optional bytes result_state_id = 1; // ObjectId + optional bytes receipt = 2; // NONObjectInfo.to_vec() + optional bytes context = 3; // Vec +} + +message GroupCommandVerify { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec +} + +message GroupCommandCommited { + bytes proposal = 1; // Proposal.to_vec() + optional bytes prev_state_id = 2; // ObjectId + optional bytes result_state_id = 3; // ObjectId + optional bytes receipt = 4; // NONObjectInfo.to_vec() + optional bytes context = 5; // Vec + bytes block = 6; // Block.to_vec() +} diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md new file mode 100644 index 000000000..fd211a02c --- /dev/null +++ b/src/component/cyfs-group-lib/readme.md @@ -0,0 +1,14 @@ +# 模块说明 + +支持群组产权数据相关需求 + +# 方案简介 + +1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) +2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 +3. 共识协议目前采用 BFT(HotStuff?) +4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 +5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) +6. 支持 cyfs://r/${groupid}/${decid}/${r-path} +7. 提供对 GroupState 的访问权限控制 ACL +8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-lib/src/group/delegate_factory.rs b/src/component/cyfs-group-lib/src/delegate.rs similarity index 81% rename from src/component/cyfs-lib/src/group/delegate_factory.rs rename to src/component/cyfs-group-lib/src/delegate.rs index 9e55ff8f4..21b1e6346 100644 --- a/src/component/cyfs-lib/src/group/delegate_factory.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,25 +1,17 @@ -use crate::NONObjectInfo; use cyfs_base::{ BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult>; - - async fn on_state_changed( &self, group_id: &ObjectId, rpath: &str, - state_id: Option, - pre_state_id: Option, - ); + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()>; } pub struct ExecuteResult { @@ -30,8 +22,6 @@ pub struct ExecuteResult { #[async_trait::async_trait] pub trait RPathDelegate: Sync + Send { - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult; - async fn on_execute( &self, proposal: &GroupProposal, @@ -45,7 +35,7 @@ pub trait RPathDelegate: Sync + Send { pre_state_id: Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult; + ) -> BuckyResult<()>; async fn on_commited( &self, diff --git a/src/component/cyfs-lib/src/group/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs similarity index 100% rename from src/component/cyfs-lib/src/group/group_manager.rs rename to src/component/cyfs-group-lib/src/group_manager.rs index 7d836ae49..8c82bc9e1 100644 --- a/src/component/cyfs-lib/src/group/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -6,15 +6,15 @@ use crate::{DelegateFactory, RPathClient}; pub struct GroupManager; impl GroupManager { - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { unimplemented!() } - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn unregister(&self) { unimplemented!() } } diff --git a/src/component/cyfs-lib/src/group/mod.rs b/src/component/cyfs-group-lib/src/lib.rs similarity index 56% rename from src/component/cyfs-lib/src/group/mod.rs rename to src/component/cyfs-group-lib/src/lib.rs index 482d9ea0d..199307bcc 100644 --- a/src/component/cyfs-lib/src/group/mod.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,7 +1,9 @@ -mod delegate_factory; +mod delegate; mod group_manager; +mod objects; mod rpath_client; -pub use delegate_factory::*; +pub use delegate::*; pub use group_manager::*; +pub use objects::*; pub use rpath_client::*; diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs new file mode 100644 index 000000000..32b1b53c8 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -0,0 +1,190 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, HashValue, ObjectId, ObjectLink, ProtobufDecode, + ProtobufEncode, ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, + RawEncodePurpose, RsaCPUObjectSigner, Signature, SignatureSource, Signer, +}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC}; +use sha2::Digest; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffBlockQcVote)] +pub struct HotstuffBlockQCVote { + pub block_id: ObjectId, + pub prev_block_id: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffBlockQCVote { + pub async fn new( + block: &GroupConsensusBlock, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let block_id = block.block_id().object_id(); + let round = block.round(); + + log::debug!( + "[block vote] local: {:?}, vote hash {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let hash = Self::hash_content(block_id, block.prev_block_id(), round); + + log::debug!( + "[block vote] local: {:?}, vote sign {}, round: {}", + local_device_id, + block.block_id(), + block.round() + ); + + let signature = signer + .sign( + hash.as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + block_id: block_id.clone(), + round, + voter: local_device_id, + signature, + prev_block_id: block.prev_block_id().map(|id| id.clone()), + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) + } + + fn hash_content( + block_id: &ObjectId, + prev_block_id: Option<&ObjectId>, + round: u64, + ) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(block_id.as_slice()); + sha256.input(round.to_le_bytes()); + if let Some(prev_block_id) = prev_block_id { + sha256.input(prev_block_id.as_slice()); + } + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffBlockQCVote { + fn transform(value: super::codec::protos::HotstuffBlockQcVote) -> BuckyResult { + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, + round: value.round, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), + None => None, + }, + }) + } +} + +impl ProtobufTransform<&HotstuffBlockQCVote> for super::codec::protos::HotstuffBlockQcVote { + fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffBlockQcVote { + block_id: value.block_id.to_vec()?, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + prev_block_id: match value.prev_block_id.as_ref() { + Some(id) => Some(id.to_vec()?), + None => None, + }, + }; + + Ok(ret) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::HotstuffTimeoutVote)] +pub struct HotstuffTimeoutVote { + pub high_qc: Option, + pub round: u64, + pub voter: ObjectId, + pub signature: Signature, +} + +impl HotstuffTimeoutVote { + pub async fn new( + high_qc: Option, + round: u64, + local_device_id: ObjectId, + signer: &RsaCPUObjectSigner, + ) -> BuckyResult { + let signature = signer + .sign( + Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + &SignatureSource::Object(ObjectLink { + obj_id: local_device_id, + obj_owner: None, + }), + ) + .await?; + + Ok(Self { + high_qc, + round, + voter: local_device_id, + signature, + }) + } + + pub fn hash(&self) -> HashValue { + Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + } + + pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + let mut sha256 = sha2::Sha256::new(); + sha256.input(high_qc_round.to_le_bytes()); + sha256.input(round.to_le_bytes()); + sha256.result().into() + } +} + +impl ProtobufTransform for HotstuffTimeoutVote { + fn transform(value: super::codec::protos::HotstuffTimeoutVote) -> BuckyResult { + let high_qc = if value.high_qc().len() == 0 { + None + } else { + Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) + }; + Ok(Self { + voter: ObjectId::raw_decode(value.voter.as_slice())?.0, + signature: Signature::raw_decode(value.signature.as_slice())?.0, + round: value.round, + high_qc, + }) + } +} + +impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffTimeoutVote { + fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { + let ret = super::codec::protos::HotstuffTimeoutVote { + high_qc: match value.high_qc.as_ref() { + Some(qc) => Some(qc.to_vec()?), + None => None, + }, + round: value.round, + voter: value.voter.to_vec()?, + signature: value.signature.to_vec()?, + }; + + Ok(ret) + } +} diff --git a/src/component/cyfs-group-lib/src/objects/codec/mod.rs b/src/component/cyfs-group-lib/src/objects/codec/mod.rs new file mode 100644 index 000000000..66df9053f --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/codec/mod.rs @@ -0,0 +1,3 @@ +pub mod protos { + include!(concat!(env!("OUT_DIR"), "/mod.rs")); +} diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs new file mode 100644 index 000000000..912ced438 --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -0,0 +1,428 @@ +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, NamedObjType, NamedObject, + NamedObjectBase, NamedObjectBuilder, NamedObjectId, ObjectId, ProtobufDecode, ProtobufEncode, + ProtobufTransform, ProtobufTransformType, RawConvertTo, RawDecode, RawEncode, RawEncodePurpose, + SubDescNone, OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, +}; + +use cyfs_core::{CoreObjectType, GroupConsensusBlock, GroupProposal}; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandDescContent)] +pub struct GroupCommandDescContent {} + +impl DescContent for GroupCommandDescContent { + fn obj_type() -> u16 { + CoreObjectType::GroupCommand as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + fn debug_info() -> String { + String::from("GroupCommandDescContent") + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Debug)] +pub enum GroupCommandType { + NewRPath, + Execute, + ExecuteResult, + Verify, + Commited, +} + +#[derive(Clone, RawEncode, RawDecode)] +pub enum GroupCommandBodyContent { + NewRPath(GroupCommandNewRPath), + Execute(GroupCommandExecute), + ExecuteResult(GroupCommandExecuteResult), + Verify(GroupCommandVerify), + Commited(GroupCommandCommited), +} + +pub type GroupCommandObjectType = NamedObjType; +pub type GroupCommandBuilder = NamedObjectBuilder; + +pub type GroupCommandId = NamedObjectId; +pub type GroupCommand = NamedObjectBase; + +impl GroupCommandBodyContent { + pub fn cmd_type(&self) -> GroupCommandType { + match self { + GroupCommandBodyContent::NewRPath(_) => GroupCommandType::NewRPath, + GroupCommandBodyContent::Execute(_) => GroupCommandType::Execute, + GroupCommandBodyContent::ExecuteResult(_) => GroupCommandType::ExecuteResult, + GroupCommandBodyContent::Verify(_) => GroupCommandType::Verify, + GroupCommandBodyContent::Commited(_) => GroupCommandType::Commited, + } + } +} + +pub trait GroupCommandObject { + fn cmd_type(&self) -> GroupCommandType; + fn into_cmd(self) -> GroupCommandBodyContent; +} + +impl GroupCommandObject for GroupCommand { + fn cmd_type(&self) -> GroupCommandType { + self.body().as_ref().unwrap().content().cmd_type() + } + + fn into_cmd(self) -> GroupCommandBodyContent { + self.into_body().unwrap().into_content() + } +} + +impl BodyContent for GroupCommandBodyContent { + fn version(&self) -> u8 { + 0 + } + + fn format(&self) -> u8 { + cyfs_base::OBJECT_CONTENT_CODEC_FORMAT_RAW + } + + fn debug_info() -> String { + String::from("GroupCommandBodyContent") + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandNewRPath)] +pub struct GroupCommandNewRPath { + pub group_id: ObjectId, + pub rpath: String, + pub with_block: Option, +} + +impl ProtobufTransform for GroupCommandNewRPath { + fn transform(value: super::codec::protos::GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: ObjectId::raw_decode(value.group_id.as_slice())?.0, + with_block: match value.with_block.as_ref() { + Some(buf) => Some(GroupConsensusBlock::raw_decode(buf.as_slice())?.0), + None => None, + }, + rpath: value.rpath, + }) + } +} + +impl ProtobufTransform<&GroupCommandNewRPath> for super::codec::protos::GroupCommandNewRPath { + fn transform(value: &GroupCommandNewRPath) -> BuckyResult { + Ok(Self { + group_id: value.group_id.to_vec()?, + rpath: value.rpath.clone(), + with_block: match value.with_block.as_ref() { + Some(block) => Some(block.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecute)] +pub struct GroupCommandExecute { + pub proposal: GroupProposal, + pub prev_state_id: Option, +} + +impl ProtobufTransform for GroupCommandExecute { + fn transform(value: super::codec::protos::GroupCommandExecute) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecute> for super::codec::protos::GroupCommandExecute { + fn transform(value: &GroupCommandExecute) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandExecuteResult)] +pub struct GroupCommandExecuteResult { + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform + for GroupCommandExecuteResult +{ + fn transform(value: super::codec::protos::GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandExecuteResult> + for super::codec::protos::GroupCommandExecuteResult +{ + fn transform(value: &GroupCommandExecuteResult) -> BuckyResult { + Ok(Self { + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandVerify)] +pub struct GroupCommandVerify { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, +} + +impl ProtobufTransform for GroupCommandVerify { + fn transform(value: super::codec::protos::GroupCommandVerify) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id { + Some(buf) => Some(ObjectId::raw_decode(buf.as_slice())?.0), + None => None, + }, + receipt: match value.receipt { + Some(buf) => Some(NONObjectInfo::raw_decode(buf.as_slice())?.0), + None => None, + }, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupCommandVerify { + fn transform(value: &GroupCommandVerify) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + }) + } +} + +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] +#[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] +pub struct GroupCommandCommited { + pub proposal: GroupProposal, + pub prev_state_id: Option, + pub result_state_id: Option, + pub receipt: Option, + pub context: Option>, + pub block: GroupConsensusBlock, +} + +impl ProtobufTransform for GroupCommandCommited { + fn transform(value: super::codec::protos::GroupCommandCommited) -> BuckyResult { + Ok(Self { + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), + None => None, + }, + proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), + None => None, + }, + block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, + context: value.context, + }) + } +} + +impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { + fn transform(value: &GroupCommandCommited) -> BuckyResult { + Ok(Self { + proposal: value.proposal.to_vec()?, + prev_state_id: match value.prev_state_id.as_ref() { + Some(prev_state_id) => Some(prev_state_id.to_vec()?), + None => None, + }, + result_state_id: match value.result_state_id.as_ref() { + Some(result_state_id) => Some(result_state_id.to_vec()?), + None => None, + }, + receipt: match value.receipt.as_ref() { + Some(receipt) => Some(receipt.to_vec()?), + None => None, + }, + context: value.context.clone(), + block: value.block.to_vec()?, + }) + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandNewRPath) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::NewRPath(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecute) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Execute(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandExecuteResult) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::ExecuteResult(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandVerify) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Verify(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl From for GroupCommand { + fn from(cmd: GroupCommandCommited) -> Self { + let desc = GroupCommandDescContent {}; + let body = GroupCommandBodyContent::Commited(cmd); + GroupCommandBuilder::new(desc, body).build() + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::NewRPath(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect NewRPath", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Execute(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Execute", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::ExecuteResult(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect ExecuteResult", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Verify(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Verify", cmd_type), + )), + } + } +} + +impl TryInto for GroupCommand { + type Error = BuckyError; + + fn try_into(self) -> Result { + let cmd_type = self.cmd_type(); + match self.into_cmd() { + GroupCommandBodyContent::Commited(cmd) => Ok(cmd), + _ => Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("is {:?}, expect Commited", cmd_type), + )), + } + } +} diff --git a/src/component/cyfs-group/src/objects/group_decide_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_decide_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_decide_proposal.rs diff --git a/src/component/cyfs-group/src/objects/group_rpath_status.rs b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs similarity index 93% rename from src/component/cyfs-group/src/objects/group_rpath_status.rs rename to src/component/cyfs-group-lib/src/objects/group_rpath_status.rs index bfc9bc5d2..ae656b5ad 100644 --- a/src/component/cyfs-group/src/objects/group_rpath_status.rs +++ b/src/component/cyfs-group-lib/src/objects/group_rpath_status.rs @@ -21,7 +21,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -42,7 +42,7 @@ impl RawEncode for GroupRPathStatus { status_list.push(obj.to_vec()?); } - let proto = crate::protos::GroupRPathStatus { + let proto = super::codec::protos::GroupRPathStatus { block_desc, certificate, status_list, @@ -56,7 +56,7 @@ impl RawEncode for GroupRPathStatus { impl<'de> RawDecode<'de> for GroupRPathStatus { fn raw_decode(mut buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let proto = crate::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { + let proto = super::codec::protos::GroupRPathStatus::decode(&mut buf).map_err(|err| { let msg = format!("decode proto-buf for GroupRPathStatus failed {:?}", err); log::error!("{}", msg); BuckyError::new(BuckyErrorCode::Failed, msg) diff --git a/src/component/cyfs-group/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs similarity index 100% rename from src/component/cyfs-group/src/objects/group_update_proposal.rs rename to src/component/cyfs-group-lib/src/objects/group_update_proposal.rs diff --git a/src/component/cyfs-group-lib/src/objects/mod.rs b/src/component/cyfs-group-lib/src/objects/mod.rs new file mode 100644 index 000000000..668afe8cf --- /dev/null +++ b/src/component/cyfs-group-lib/src/objects/mod.rs @@ -0,0 +1,12 @@ +mod group_command; +// mod group_decide_proposal; +mod group_rpath_status; +// mod group_update_proposal; +mod certificate; +mod codec; + +pub use group_command::*; +// pub use group_decide_proposal::*; +pub use group_rpath_status::*; +// pub use group_update_proposal::*; +pub use certificate::*; diff --git a/src/component/cyfs-lib/src/group/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs similarity index 94% rename from src/component/cyfs-lib/src/group/rpath_client.rs rename to src/component/cyfs-group-lib/src/rpath_client.rs index 4162abe68..2fea6dcf7 100644 --- a/src/component/cyfs-lib/src/group/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -5,8 +5,7 @@ use cyfs_base::{ RawConvertTo, }; use cyfs_core::{GroupProposal, GroupRPath}; - -use crate::NONObjectInfo; +use cyfs_lib::NONObjectInfo; struct RPathClientRaw {} diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 4a7aae6c2..1caf5b9a4 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,5 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/protos/group_bft_protocol.proto b/src/component/cyfs-group/protos/group_bft_protocol.proto deleted file mode 100644 index 621186522..000000000 --- a/src/component/cyfs-group/protos/group_bft_protocol.proto +++ /dev/null @@ -1,23 +0,0 @@ - -syntax = "proto3"; - -message HotstuffBlockQCVote { - bytes block_id = 1; - optional bytes prev_block_id = 2; - uint64 round = 3; - bytes voter = 4; - bytes signature = 5; -} - -message HotstuffTimeoutVote { - optional bytes high_qc = 1; // encode(core:HotstuffBlockQc) - uint64 round = 2; - bytes voter = 3; - bytes signature = 4; -} - -message GroupRPathStatus { - bytes block_desc = 1; // GroupConsensusBlockDescContent - bytes certificate = 2; // HotstuffBlockQC for block - repeated bytes status_list = 4; // Array> -} \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52dcdd650..cc555298b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,15 +11,16 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{NONObjectInfo, GroupObjectMapProcessor, RPathDelegate, ExecuteResult}; +use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, - GroupStorage, HotstuffBlockQCVote, HotstuffMessage, HotstuffTimeoutVote, + GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, }; /** @@ -51,7 +52,7 @@ impl Hotstuff { network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -81,7 +82,7 @@ impl Hotstuff { rx_message, proposal_consumer, state_pusher_runner, - delegate, + event_notifier, rpath2, ) .run() @@ -224,7 +225,7 @@ struct HotstuffRunner { tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, - delegate: Arc>, + event_notifier: RPathEventNotifier, synchronizer: Synchronizer, rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, @@ -251,7 +252,7 @@ impl HotstuffRunner { rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, state_pusher: StatePusher, - delegate: Arc>, + event_notifier: RPathEventNotifier, rpath: GroupRPath, ) -> Self { let max_round_block = store.block_with_max_round(); @@ -307,7 +308,7 @@ impl HotstuffRunner { network_sender, tx_message, rx_message, - delegate, + event_notifier, synchronizer, non_driver, rpath, @@ -511,37 +512,25 @@ impl HotstuffRunner { context: proposal_exe_info.context.clone(), }; - if self - .delegate - .on_verify(proposal, prev_state_id, self.store.get_object_map_processor(), &exe_result) + self + .event_notifier + .on_verify(proposal, prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); err - })? - { - log::debug!( - "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + })?; - prev_state_id = proposal_exe_info.result_state; - } else { - log::warn!( - "[hotstuff] local: {:?}, block verify failed by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", - self, - proposal_exe_info.proposal, - prev_state_id, prev_block.as_ref().map(|b| b.block_id()), - proposal_exe_info.result_state, - block.block_id() - ); + log::debug!( + "[hotstuff] local: {:?}, block verify ok by app, proposal: {}, prev_state: {:?}/{:?}, expect-result: {:?}/{:?}", + self, + proposal_exe_info.proposal, + prev_state_id, prev_block.as_ref().map(|b| b.block_id()), + proposal_exe_info.result_state, + block.block_id() + ); - return Err(BuckyError::new(BuckyErrorCode::Reject, "verify failed")); - } + prev_state_id = proposal_exe_info.result_state; } assert_eq!( @@ -840,11 +829,10 @@ impl HotstuffRunner { None => None, }; - self.delegate + self.event_notifier .on_commited( &proposal_obj, pre_state_id, - self.store.get_object_map_processor(), &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, @@ -1625,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.delegate.on_execute(&proposal, result_state_id, self.store.get_object_map_processor()).await { + match self.event_notifier.on_execute(&proposal, result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index ad3a21e35..398274723 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -14,9 +14,10 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; -use crate::{network::NONDriverHelper, GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::network::NONDriverHelper; #[derive(Clone)] pub(crate) struct Committee { diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index f44260a04..6a9735a7f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -1,14 +1,13 @@ use std::collections::{HashMap, HashSet}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature, -}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId, Signature}; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffBlockQCSign, HotstuffTimeout, HotstuffTimeoutSign, }; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::{Committee, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use crate::Committee; pub(crate) struct VoteMgr { committee: Committee, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs new file mode 100644 index 000000000..67f79cfdd --- /dev/null +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -0,0 +1,42 @@ +use cyfs_base::{ + BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, +}; +use cyfs_core::{GroupConsensusBlock, GroupProposal}; +use cyfs_group_lib::ExecuteResult; +use cyfs_lib::NONObjectInfo; + +#[derive(Clone)] +pub(crate) struct RPathEventNotifier {} + +impl RPathEventNotifier { + pub fn new() -> Self { + unimplemented!() + } + + pub async fn on_execute( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn on_verify( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + unimplemented!() + } + + pub async fn on_commited( + &self, + proposal: &GroupProposal, + pre_state_id: Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + unimplemented!() + } +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 60ddba1fb..95bdbcd17 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,15 +2,15 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::{DelegateFactory, GlobalStateManagerRawProcessorRef}; +use cyfs_lib::GlobalStateManagerRawProcessorRef; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, IsCreateRPath, NONDriver, - NONDriverHelper, RPathClient, RPathControl, NET_PROTOCOL_VPORT, + storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, + RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, }; type ControlByRPath = HashMap; @@ -22,7 +22,6 @@ type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - delegate_by_dec: HashMap>, control_by_group: ControlByGroup, client_by_group: ClientByGroup, } @@ -33,6 +32,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,12 +54,12 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { control_by_group: ControlByGroup::default(), client_by_group: ClientByGroup::default(), - delegate_by_dec: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -69,29 +69,12 @@ impl GroupManager { Ok(mgr) } - pub async fn register( - &self, - dec_id: DecAppId, - delegate_factory: Box, - ) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec - .insert(dec_id.object_id().clone(), delegate_factory); - Ok(()) - } - - pub async fn unregister(&self, dec_id: &DecAppId) -> BuckyResult<()> { - let mut raw = self.write().await; - raw.delegate_by_dec.remove(dec_id.object_id()); - Ok(()) - } - pub async fn find_rpath_control( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, ) -> BuckyResult { self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await @@ -204,7 +187,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, Some(&block), Some(&remote), ) @@ -220,7 +203,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -236,7 +219,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -252,7 +235,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -268,7 +251,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -284,7 +267,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::Yes, + false, None, Some(&remote), ) @@ -331,7 +314,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.r_path(), - IsCreateRPath::No, + false, None, Some(&remote), ) @@ -378,7 +361,7 @@ impl GroupManager { group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, - is_auto_create: IsCreateRPath, + is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, ) -> BuckyResult { @@ -398,7 +381,6 @@ impl GroupManager { { // write - let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); @@ -411,6 +393,7 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -424,40 +407,25 @@ impl GroupManager { let store = match store { Ok(store) => Some(store), Err(e) => { - if let IsCreateRPath::No = is_auto_create { - return Err(e); - } if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - None + + self.on_new_rpath_request(group_id, dec_id, rpath, block) + .await?; + + if !is_auto_create { + return Err(e); + } else { + None + } } else { return Err(e); } } }; - // TODO: query group - let group = non_driver - .get_group(group_id, block.map(|b| b.group_chunk_id()), remote) - .await?; - let mut raw = self.write().await; - let delegate = { - let delegate_factory = raw.delegate_by_dec.get(dec_id); - if delegate_factory.is_none() { - return Err(BuckyError::new( - BuckyErrorCode::DecNotRunning, - "dec not running for the rpath-control", - )); - } - let delegate_factory = delegate_factory.unwrap(); - - delegate_factory - .create_rpath_delegate(&group, rpath, block) - .await? - }; - let store = match store { Some(store) => store, None => { @@ -489,7 +457,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - Arc::new(delegate), + event_notifier, network_sender, non_driver, store, @@ -501,4 +469,14 @@ impl GroupManager { } } } + + async fn on_new_rpath_request( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: Option<&GroupConsensusBlock>, + ) -> BuckyResult<()> { + unimplemented!() + } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 8a43844b2..2ad717514 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -1,9 +1,11 @@ // dec framework +mod group_events; mod group_manager; mod rpath_client; mod rpath_control; +pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; pub use rpath_control::*; diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 8a1dd34a7..08be0f5a0 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -224,10 +224,10 @@ impl RPathClient { HotstuffMessage::Timeout(tc) => unreachable!(), HotstuffMessage::SyncRequest(min_bound, max_bound) => unreachable!(), HotstuffMessage::LastStateRequest => unreachable!(), - HotstuffMessage::StateChangeNotify(header_block, qc_block) => { + HotstuffMessage::StateChangeNotify(header_block, qc) => { self.0 .state_sync - .on_state_change(header_block, qc_block, remote) + .on_state_change(header_block, qc, remote) .await } HotstuffMessage::ProposalResult(proposal_id, result) => { diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_control.rs index c3a25b060..593d82db4 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_control.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::RPathDelegate; +use cyfs_group_lib::RPathDelegate; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, + PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; struct RPathControlRaw { @@ -26,7 +26,7 @@ impl RPathControl { local_device_id: ObjectId, rpath: GroupRPath, signer: Arc, - delegate: Arc>, + event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, store: GroupStorage, @@ -46,7 +46,7 @@ impl RPathControl { network_sender.clone(), non_driver, pending_proposal_consumer, - delegate, + event_notifier, rpath.clone(), ); diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 790429c6c..8fd67496b 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -4,13 +4,11 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{ - helper::verify_rpath_value, storage::DecStorage, Committee, GroupRPathStatus, HotstuffMessage, - CHANNEL_CAPACITY, -}; +use crate::{storage::DecStorage, Committee, HotstuffMessage, CHANNEL_CAPACITY}; use super::{CallReplyNotifier, CallReplyWaiter}; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 7272b3882..e019db892 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -2,15 +2,12 @@ use std::{collections::HashSet, sync::Arc}; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, -}; -use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; use cyfs_lib::NONObjectInfo; use futures::FutureExt; use crate::{ - helper::Timer, network::NONDriverHelper, storage::{DecStorage, DecStorageCache}, Committee, CHANNEL_CAPACITY, @@ -21,13 +18,9 @@ use super::{CallReplyNotifier, CallReplyWaiter}; enum DecStateSynchronizerMessage { ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, ), - StateChange(GroupConsensusBlock, GroupConsensusBlock), + StateChange(GroupConsensusBlock, HotstuffBlockQC), DelaySync(Option<(ObjectId, Option)>), // (proposal-id, Ok(result)) } @@ -81,11 +74,7 @@ impl DecStateSynchronizer { pub async fn on_proposal_complete( &self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { self.0 @@ -100,13 +89,13 @@ impl DecStateSynchronizer { pub async fn on_state_change( &self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { self.0 .tx_dec_state_sync_message .send(( - DecStateSynchronizerMessage::StateChange(header_block, qc_block), + DecStateSynchronizerMessage::StateChange(header_block, qc), remote, )) .await; @@ -121,7 +110,7 @@ struct DecStateSynchronizerCache { struct UpdateNotifyInfo { header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remotes: HashSet, group_chunk_id: ObjectId, group: Group, @@ -178,15 +167,11 @@ impl DecStateSynchronizerRunner { async fn handle_proposal_complete( &mut self, proposal_id: ObjectId, - result: BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, + result: BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, remote: ObjectId, ) { match result { - Ok((result, header_block, qc_block)) => { + Ok((result, header_block, qc)) => { if header_block .proposals() .iter() @@ -200,7 +185,7 @@ impl DecStateSynchronizerRunner { } if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_err() { @@ -226,11 +211,11 @@ impl DecStateSynchronizerRunner { async fn handle_state_change( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) { if self - .push_update_notify(header_block, qc_block, remote) + .push_update_notify(header_block, qc, remote) .await .is_ok() { @@ -251,11 +236,7 @@ impl DecStateSynchronizerRunner { for remote in notify_info.remotes.iter() { match self .store - .sync( - ¬ify_info.header_block, - ¬ify_info.qc_block, - remote.clone(), - ) + .sync(¬ify_info.header_block, ¬ify_info.qc, remote.clone()) .await { Ok(_) => { @@ -264,7 +245,7 @@ impl DecStateSynchronizerRunner { state_cache: DecStorageCache { state: notify_info.header_block.result_state_id().clone(), header_block: notify_info.header_block.clone(), - qc_block: notify_info.qc_block.clone(), + qc: notify_info.qc.clone(), }, group_chunk_id: notify_info.group_chunk_id, group: notify_info.group.clone(), @@ -316,14 +297,9 @@ impl DecStateSynchronizerRunner { async fn push_update_notify( &mut self, header_block: GroupConsensusBlock, - qc_block: GroupConsensusBlock, + qc: HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { - if qc_block.qc().is_none() { - log::warn!("the qc is none for qc-block({})", qc_block.block_id()); - return Err(BuckyError::new(BuckyErrorCode::Unknown, "qc lost")); - } - if let Some(notify) = self.update_notifies.as_mut() { match notify.header_block.height().cmp(&header_block.height()) { std::cmp::Ordering::Less => {} @@ -338,11 +314,7 @@ impl DecStateSynchronizerRunner { if header_block.check() && self .committee - .verify_block_desc_with_qc( - header_block.named_object().desc(), - qc_block.qc().as_ref().unwrap(), - remote, - ) + .verify_block_desc_with_qc(header_block.named_object().desc(), &qc, remote) .await .is_ok() { @@ -354,7 +326,7 @@ impl DecStateSynchronizerRunner { self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, - qc_block: qc_block, + qc: qc, remotes: HashSet::from([remote]), group_chunk_id, group, diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index b1506a192..571c1ca13 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -194,7 +194,11 @@ impl StateChanggeRunner { .post_message( HotstuffMessage::ProposalResult( exe_info.proposal, - Ok((receipt, block.clone(), qc_block.clone())), + Ok(( + receipt, + block.clone(), + qc_block.qc().as_ref().unwrap().clone(), + )), ), rpath.clone(), &proposer, @@ -320,7 +324,7 @@ impl StateChanggeRunner { let msg = HotstuffMessage::StateChangeNotify( progress.header_block.clone(), - progress.qc_block.clone(), + progress.qc_block.qc().as_ref().unwrap().clone(), ); if notify_targets.len() > 0 { diff --git a/src/component/cyfs-group/src/helper/mod.rs b/src/component/cyfs-group/src/helper/mod.rs index ce36043a3..4d3f1b1c6 100644 --- a/src/component/cyfs-group/src/helper/mod.rs +++ b/src/component/cyfs-group/src/helper/mod.rs @@ -1,5 +1,3 @@ mod timer; -mod verify; pub use timer::*; -pub use verify::*; diff --git a/src/component/cyfs-group/src/helper/verify.rs b/src/component/cyfs-group/src/helper/verify.rs deleted file mode 100644 index ef3e34495..000000000 --- a/src/component/cyfs-group/src/helper/verify.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cyfs_base::{BuckyResult, Group, NamedObject, ObjectDesc}; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockObject, HotstuffBlockQC, -}; - -use crate::GroupRPathStatus; - -pub async fn verify_rpath_value( - value: &GroupRPathStatus, - sub_path: &str, - block_desc: &GroupConsensusBlockDesc, - qc: &HotstuffBlockQC, - group: &Group, -) -> BuckyResult { - unimplemented!() -} diff --git a/src/component/cyfs-group/src/lib.rs b/src/component/cyfs-group/src/lib.rs index ba8e83569..c493f13c5 100644 --- a/src/component/cyfs-group/src/lib.rs +++ b/src/component/cyfs-group/src/lib.rs @@ -4,10 +4,8 @@ mod dec; mod dec_state; mod helper; mod network; -mod objects; mod statepath; mod storage; -mod utils; pub use consensus::*; pub use constant::*; @@ -15,7 +13,5 @@ pub use dec::*; pub(crate) use dec_state::*; pub(crate) use helper::*; pub use network::*; -pub use objects::*; pub use statepath::*; pub(crate) use storage::*; -pub use utils::*; diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index f79e67dd4..096bd0950 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,7 +1,9 @@ mod listener; mod non_driver; +mod protocol; mod sender; pub(crate) use listener::*; pub use non_driver::*; +pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/objects/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs similarity index 70% rename from src/component/cyfs-group/src/objects/protocol.rs rename to src/component/cyfs-group/src/network/protocol.rs index 932e5cd46..7e32fdc4d 100644 --- a/src/component/cyfs-group/src/objects/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -1,16 +1,8 @@ -pub mod protos { - include!(concat!(env!("OUT_DIR"), "/mod.rs")); -} - use cyfs_base::*; -use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, -}; +use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath, HotstuffBlockQC}; +use cyfs_group_lib::{GroupRPathStatus, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; use itertools::Itertools; -use sha2::Digest; - -use crate::GroupRPathStatus; #[derive(RawEncode, RawDecode, PartialEq, Eq, Ord, Clone, Debug)] pub enum SyncBound { @@ -96,15 +88,11 @@ pub(crate) enum HotstuffMessage { SyncRequest(SyncBound, SyncBound), // [min, max] LastStateRequest, - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) ProposalResult( ObjectId, - BuckyResult<( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - )>, - ), // (proposal-id, (ExecuteResult, block, qc-block)) + BuckyResult<(Option, GroupConsensusBlock, HotstuffBlockQC)>, + ), // (proposal-id, (ExecuteResult, block, qc)) QueryState(String), VerifiableState(String, BuckyResult), } @@ -151,8 +139,8 @@ impl std::fmt::Debug for HotstuffMessage { "HotstuffMessage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest => { @@ -169,8 +157,8 @@ impl std::fmt::Debug for HotstuffMessage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) }) ) @@ -214,16 +202,12 @@ pub(crate) enum HotstuffPackage { SyncRequest(ProtocolAddress, SyncBound, SyncBound), - StateChangeNotify(GroupConsensusBlock, GroupConsensusBlock), // (block, qc-block) + StateChangeNotify(GroupConsensusBlock, HotstuffBlockQC), // (block, qc) LastStateRequest(ProtocolAddress), ProposalResult( ObjectId, Result< - ( - Option, - GroupConsensusBlock, - GroupConsensusBlock, - ), + (Option, GroupConsensusBlock, HotstuffBlockQC), (BuckyError, ProtocolAddress), >, ), // (proposal-id, ExecuteResult) @@ -276,8 +260,8 @@ impl std::fmt::Debug for HotstuffPackage { "HotstuffPackage::StateChangeNotify({}/{}, {}/{})", block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ) } Self::LastStateRequest(_) => { @@ -296,8 +280,8 @@ impl std::fmt::Debug for HotstuffPackage { obj.as_ref().map(|o| o.object_id), block.block_id(), block.round(), - qc.block_id(), - qc.round() + qc.block_id, + qc.round ); Ok(ok) } @@ -394,23 +378,25 @@ fn decode_with_length<'de, O: RawDecode<'de>>( impl RawEncode for HotstuffPackage { fn raw_measure(&self, purpose: &Option) -> BuckyResult { let len = match self { - HotstuffPackage::Block(b) => b.raw_measure(purpose)?, + HotstuffPackage::Block(b) => 3 + b.raw_measure(purpose)?, HotstuffPackage::BlockVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::TimeoutVote(addr, vote) => { - 2 + addr.raw_measure(purpose)? + vote.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + vote.raw_measure(purpose)? } HotstuffPackage::Timeout(addr, tc) => { - 2 + addr.raw_measure(purpose)? + tc.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + 3 + tc.raw_measure(purpose)? } HotstuffPackage::SyncRequest(addr, min, max) => { - addr.raw_measure(purpose)? + min.raw_measure(purpose)? + max.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + + min.raw_measure(purpose)? + + max.raw_measure(purpose)? } HotstuffPackage::StateChangeNotify(block, qc) => { - 3 + block.raw_measure(purpose)? + qc.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + 3 + qc.raw_measure(purpose)? } - HotstuffPackage::LastStateRequest(addr) => addr.raw_measure(purpose)?, + HotstuffPackage::LastStateRequest(addr) => 2 + addr.raw_measure(purpose)?, HotstuffPackage::ProposalResult(id, result) => { id.raw_measure(purpose)? + match result { @@ -418,22 +404,23 @@ impl RawEncode for HotstuffPackage { non.raw_measure(purpose)? + 3 + block.raw_measure(purpose)? + + 3 + block_qc.raw_measure(purpose)? } Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } HotstuffPackage::QueryState(addr, sub_path) => { - addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? + sub_path.raw_measure(purpose)? } HotstuffPackage::VerifiableState(sub_path, result) => { sub_path.raw_measure(purpose)? + match result { - Ok(status) => status.raw_measure(purpose)?, + Ok(status) => 3 + status.raw_measure(purpose)?, Err((err, addr)) => { - err.raw_measure(purpose)? + addr.raw_measure(purpose)? + err.raw_measure(purpose)? + 2 + addr.raw_measure(purpose)? } } } @@ -451,43 +438,43 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::Block(b) => { buf[0] = 0; let buf = &mut buf[1..]; - b.raw_encode(buf, purpose) + encode_with_length(buf, b, purpose, 3) } HotstuffPackage::BlockVote(addr, vote) => { buf[0] = 1; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::TimeoutVote(addr, vote) => { buf[0] = 2; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - vote.raw_encode(buf, purpose) + encode_with_length(buf, vote, purpose, 3) } HotstuffPackage::Timeout(addr, tc) => { buf[0] = 3; let buf = &mut buf[1..]; let buf = encode_with_length(buf, addr, purpose, 2)?; - tc.raw_encode(buf, purpose) + encode_with_length(buf, tc, purpose, 3) } HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; + encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; - let buf = max.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + max.raw_encode(buf, purpose) } HotstuffPackage::StateChangeNotify(block, qc) => { buf[0] = 5; let buf = &mut buf[1..]; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } HotstuffPackage::LastStateRequest(addr) => { buf[0] = 6; let buf = &mut buf[1..]; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } HotstuffPackage::ProposalResult(id, result) => { buf[0] = 7; @@ -501,19 +488,19 @@ impl RawEncode for HotstuffPackage { Ok((non, block, qc)) => { let buf = non.raw_encode(buf, purpose)?; let buf = encode_with_length(buf, block, purpose, 3)?; - qc.raw_encode(buf, purpose) + encode_with_length(buf, qc, purpose, 3) } Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } HotstuffPackage::QueryState(addr, sub_path) => { buf[0] = 8; let buf = &mut buf[1..]; - let buf = sub_path.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2)?; + sub_path.raw_encode(buf, purpose) } HotstuffPackage::VerifiableState(sub_path, result) => { buf[0] = 9; @@ -523,10 +510,10 @@ impl RawEncode for HotstuffPackage { let buf = &mut buf[1..]; let buf = sub_path.raw_encode(buf, purpose)?; match result { - Ok(status) => status.raw_encode(buf, purpose), + Ok(status) => encode_with_length(buf, status, purpose, 3), Err((err, addr)) => { let buf = err.raw_encode(buf, purpose)?; - addr.raw_encode(buf, purpose) + encode_with_length(buf, addr, purpose, 2) } } } @@ -542,49 +529,49 @@ impl<'de> RawDecode<'de> for HotstuffPackage { match pkg_type { 0 => { let buf = &buf[1..]; - let (b, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (b, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Block(b), buf)) } 1 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffBlockQCVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::BlockVote(addr, vote), buf)) } 2 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeoutVote::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::TimeoutVote(addr, vote), buf)) } 3 => { let buf = &buf[1..]; let (addr, buf) = decode_with_length(buf, 2)?; - let (vote, buf) = HotstuffTimeout::raw_decode(buf)?; + let (vote, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::Timeout(addr, vote), buf)) } 4 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (min, buf) = SyncBound::raw_decode(buf)?; let (max, buf) = SyncBound::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::SyncRequest(addr, min, max), buf)) } 5 => { let buf = &buf[1..]; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::StateChangeNotify(block, qc), buf)) } 6 => { let buf = &buf[1..]; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::LastStateRequest(addr), buf)) } @@ -596,7 +583,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { true => { let (non, buf) = Option::::raw_decode(buf)?; let (block, buf) = decode_with_length(buf, 3)?; - let (qc, buf) = GroupConsensusBlock::raw_decode(buf)?; + let (qc, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::ProposalResult(id, Ok((non, block, qc))), @@ -605,7 +592,7 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::ProposalResult(id, Err((err, addr))), buf)) } @@ -613,8 +600,8 @@ impl<'de> RawDecode<'de> for HotstuffPackage { } 8 => { let buf = &buf[1..]; + let (addr, buf) = decode_with_length(buf, 2)?; let (sub_path, buf) = String::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::QueryState(addr, sub_path), buf)) } @@ -624,13 +611,13 @@ impl<'de> RawDecode<'de> for HotstuffPackage { let (sub_path, buf) = String::raw_decode(buf)?; match is_ok { true => { - let (status, buf) = GroupRPathStatus::raw_decode(buf)?; + let (status, buf) = decode_with_length(buf, 3)?; assert_eq!(buf.len(), 0); Ok((HotstuffPackage::VerifiableState(sub_path, Ok(status)), buf)) } false => { let (err, buf) = BuckyError::raw_decode(buf)?; - let (addr, buf) = ProtocolAddress::raw_decode(buf)?; + let (addr, buf) = decode_with_length(buf, 2)?; assert_eq!(buf.len(), 0); Ok(( HotstuffPackage::VerifiableState(sub_path, Err((err, addr))), @@ -698,188 +685,5 @@ impl ProtocolAddress { } } -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffBlockQcVote)] -pub(crate) struct HotstuffBlockQCVote { - pub block_id: ObjectId, - pub prev_block_id: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffBlockQCVote { - pub async fn new( - block: &GroupConsensusBlock, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let block_id = block.block_id().object_id(); - let round = block.round(); - - log::debug!( - "[block vote] local: {:?}, vote hash {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let hash = Self::hash_content(block_id, block.prev_block_id(), round); - - log::debug!( - "[block vote] local: {:?}, vote sign {}, round: {}", - local_device_id, - block.block_id(), - block.round() - ); - - let signature = signer - .sign( - hash.as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - block_id: block_id.clone(), - round, - voter: local_device_id, - signature, - prev_block_id: block.prev_block_id().map(|id| id.clone()), - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(&self.block_id, self.prev_block_id.as_ref(), self.round) - } - - fn hash_content( - block_id: &ObjectId, - prev_block_id: Option<&ObjectId>, - round: u64, - ) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(block_id.as_slice()); - sha256.input(round.to_le_bytes()); - if let Some(prev_block_id) = prev_block_id { - sha256.input(prev_block_id.as_slice()); - } - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffBlockQCVote { - fn transform(value: crate::protos::HotstuffBlockQcVote) -> BuckyResult { - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - block_id: ObjectId::raw_decode(value.block_id.as_slice())?.0, - round: value.round, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(ObjectId::raw_decode(id.as_slice())?.0), - None => None, - }, - }) - } -} - -impl ProtobufTransform<&HotstuffBlockQCVote> for crate::protos::HotstuffBlockQcVote { - fn transform(value: &HotstuffBlockQCVote) -> BuckyResult { - let ret = crate::protos::HotstuffBlockQcVote { - block_id: value.block_id.to_vec()?, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - prev_block_id: match value.prev_block_id.as_ref() { - Some(id) => Some(id.to_vec()?), - None => None, - }, - }; - - Ok(ret) - } -} - -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] -#[cyfs_protobuf_type(crate::protos::HotstuffTimeoutVote)] -pub(crate) struct HotstuffTimeoutVote { - pub high_qc: Option, - pub round: u64, - pub voter: ObjectId, - pub signature: Signature, -} - -impl HotstuffTimeoutVote { - pub async fn new( - high_qc: Option, - round: u64, - local_device_id: ObjectId, - signer: &RsaCPUObjectSigner, - ) -> BuckyResult { - let signature = signer - .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), - &SignatureSource::Object(ObjectLink { - obj_id: local_device_id, - obj_owner: None, - }), - ) - .await?; - - Ok(Self { - high_qc, - round, - voter: local_device_id, - signature, - }) - } - - pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) - } - - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { - let mut sha256 = sha2::Sha256::new(); - sha256.input(high_qc_round.to_le_bytes()); - sha256.input(round.to_le_bytes()); - sha256.result().into() - } -} - -impl ProtobufTransform for HotstuffTimeoutVote { - fn transform(value: crate::protos::HotstuffTimeoutVote) -> BuckyResult { - let high_qc = if value.high_qc().len() == 0 { - None - } else { - Some(HotstuffBlockQC::raw_decode(value.high_qc())?.0) - }; - Ok(Self { - voter: ObjectId::raw_decode(value.voter.as_slice())?.0, - signature: Signature::raw_decode(value.signature.as_slice())?.0, - round: value.round, - high_qc, - }) - } -} - -impl ProtobufTransform<&HotstuffTimeoutVote> for crate::protos::HotstuffTimeoutVote { - fn transform(value: &HotstuffTimeoutVote) -> BuckyResult { - let ret = crate::protos::HotstuffTimeoutVote { - high_qc: match value.high_qc.as_ref() { - Some(qc) => Some(qc.to_vec()?), - None => None, - }, - round: value.round, - voter: value.voter.to_vec()?, - signature: value.signature.to_vec()?, - }; - - Ok(ret) - } -} - #[cfg(test)] mod test {} diff --git a/src/component/cyfs-group/src/objects/mod.rs b/src/component/cyfs-group/src/objects/mod.rs deleted file mode 100644 index 5d1a8b13f..000000000 --- a/src/component/cyfs-group/src/objects/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod group_decide_proposal; -mod group_rpath_status; -mod group_update_proposal; -mod protocol; - -pub use group_decide_proposal::*; -pub use group_rpath_status::*; -pub use group_update_proposal::*; -pub use protocol::*; diff --git a/src/component/cyfs-group/src/storage/dec_storage.rs b/src/component/cyfs-group/src/storage/dec_storage.rs index 60a45724f..0d937487c 100644 --- a/src/component/cyfs-group/src/storage/dec_storage.rs +++ b/src/component/cyfs-group/src/storage/dec_storage.rs @@ -5,16 +5,17 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawDecode, }; -use cyfs_core::GroupConsensusBlock; +use cyfs_core::{GroupConsensusBlock, HotstuffBlockQC}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateRawProcessorRef, NONObjectInfo}; -use crate::{GroupRPathStatus, STATE_PATH_SEPARATOR}; +use crate::STATE_PATH_SEPARATOR; #[derive(Clone)] pub struct DecStorageCache { pub state: Option, pub header_block: GroupConsensusBlock, - pub qc_block: GroupConsensusBlock, + pub qc: HotstuffBlockQC, } #[derive(Clone)] @@ -42,7 +43,7 @@ impl DecStorage { pub async fn sync( &self, header_block: &GroupConsensusBlock, - qc_block: &GroupConsensusBlock, + qc: &HotstuffBlockQC, remote: ObjectId, ) -> BuckyResult<()> { unimplemented!() diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index adf11c7e4..63158a865 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_lib::GroupObjectMapProcessor; +use cyfs_group_lib::GroupObjectMapProcessor; use crate::{ GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index fa6f4930f..a1a681259 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,11 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_lib::{GlobalStateManagerRawProcessorRef, GroupObjectMapProcessor, NONObjectInfo}; +use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupRPathStatus, GroupStatePath, NONDriverHelper, - PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, + STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-group/src/utils.rs b/src/component/cyfs-group/src/utils.rs deleted file mode 100644 index 5d005a726..000000000 --- a/src/component/cyfs-group/src/utils.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cyfs_base::ObjectId; - -pub type Round = u64; - -pub enum IsCreateRPath { - No, - Yes, -} diff --git a/src/component/cyfs-lib/src/lib.rs b/src/component/cyfs-lib/src/lib.rs index d2f02315a..9a4d1f079 100644 --- a/src/component/cyfs-lib/src/lib.rs +++ b/src/component/cyfs-lib/src/lib.rs @@ -4,7 +4,6 @@ mod base; mod crypto; mod default_app; mod events; -mod group; mod ndn; mod non; mod prelude; @@ -27,7 +26,6 @@ pub use base::*; pub use crypto::*; pub use default_app::*; pub use events::*; -pub use group::*; pub use ndn::*; pub use non::*; pub use prelude::*; From d334a09e2aee78e419c67e064d9dd04dc7153ac1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 12:15:59 +0800 Subject: [PATCH 506/553] Implement the events with post_object --- .../src/consensus/hotstuff/hotstuff.rs | 8 +- .../cyfs-group/src/dec/group_events.rs | 120 +++++++++++++++--- .../cyfs-group/src/dec/group_manager.rs | 50 ++++++-- .../cyfs-group/src/dec/rpath_client.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 19 ++- .../cyfs-stack/src/stack/group_non_driver.rs | 8 +- 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index cc555298b..eaaaed06e 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -514,7 +514,7 @@ impl HotstuffRunner { self .event_notifier - .on_verify(proposal, prev_state_id, &exe_result) + .on_verify(proposal.clone(), prev_state_id, &exe_result) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} verify by app failed {:?}." , self, proposal_exe_info.proposal, block.block_id(), err); @@ -831,14 +831,14 @@ impl HotstuffRunner { self.event_notifier .on_commited( - &proposal_obj, + proposal_obj, pre_state_id, &ExecuteResult { result_state_id: proposal.result_state.clone(), receipt, context: proposal.context.clone(), }, - &new_header, + new_header.clone(), ) .await; @@ -1613,7 +1613,7 @@ impl HotstuffRunner { continue; } - match self.event_notifier.on_execute(&proposal, result_state_id).await { + match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 67f79cfdd..fc3d12c63 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,42 +1,132 @@ use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_group_lib::ExecuteResult; +use cyfs_group_lib::{ + ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandVerify, +}; use cyfs_lib::NONObjectInfo; +use crate::NONDriverHelper; + #[derive(Clone)] -pub(crate) struct RPathEventNotifier {} +pub(crate) struct RPathEventNotifier { + non_driver: NONDriverHelper, +} impl RPathEventNotifier { - pub fn new() -> Self { - unimplemented!() + pub fn new(driver: NONDriverHelper) -> Self { + Self { non_driver: driver } } pub async fn on_execute( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, ) -> BuckyResult { - unimplemented!() + let cmd = GroupCommandExecute { + proposal, + prev_state_id, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_some()); + match result.as_ref() { + Some(result) => { + let (cmd, _remain) = GroupCommand::raw_decode(result.object_raw.as_slice())?; + assert_eq!(_remain.len(), 0); + let mut cmd = TryInto::::try_into(cmd)?; + Ok(ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }) + } + None => Err(BuckyError::new( + BuckyErrorCode::Unknown, + "expect some result from dec-app", + )), + } } pub async fn on_verify( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandVerify { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } pub async fn on_commited( &self, - proposal: &GroupProposal, - pre_state_id: Option, + proposal: GroupProposal, + prev_state_id: Option, execute_result: &ExecuteResult, - block: &GroupConsensusBlock, + block: GroupConsensusBlock, ) { - unimplemented!() + let cmd = GroupCommandCommited { + proposal, + prev_state_id, + result_state_id: execute_result.result_state_id.clone(), + receipt: execute_result.receipt.clone(), + context: execute_result.context.clone(), + block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .non_driver + .post_object( + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec().expect( + format!("on_commited {} failed for encode", self.non_driver.dec_id()) + .as_str(), + ), + object: None, + }, + None, + ) + .await + .map_err(|err| log::warn!("on_commited {} failed {:?}", self.non_driver.dec_id(), err)); + + assert!(result.is_err() || result.unwrap().is_none()); } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 95bdbcd17..346e75d02 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -2,11 +2,13 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyErrorCode, BuckyResult, GroupId, ObjectId, OwnerObjectDesc, RsaCPUObjectSigner, + BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RsaCPUObjectSigner, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; -use cyfs_lib::GlobalStateManagerRawProcessorRef; +use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -32,7 +34,6 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, - event_notifier: RPathEventNotifier, } #[derive(Clone)] @@ -54,7 +55,6 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, - event_notifier: RPathEventNotifier::new(), }; let raw = GroupRPathMgrRaw { @@ -393,7 +393,6 @@ impl GroupManager { local_device_id.object_id().clone(), ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let event_notifier = local_info.event_notifier.clone(); let store = GroupStorage::load( group_id, @@ -410,8 +409,13 @@ impl GroupManager { if let BuckyErrorCode::NotFound = e.code() { log::warn!("{}/{}/{} not found in storage", group_id, dec_id, rpath); - self.on_new_rpath_request(group_id, dec_id, rpath, block) - .await?; + self.on_new_rpath_request( + group_id.clone(), + dec_id, + rpath.to_string(), + block.cloned(), + ) + .await?; if !is_auto_create { return Err(e); @@ -457,7 +461,7 @@ impl GroupManager { local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), signer, - event_notifier, + RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, store, @@ -472,11 +476,33 @@ impl GroupManager { async fn on_new_rpath_request( &self, - group_id: &ObjectId, + group_id: ObjectId, dec_id: &ObjectId, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, + rpath: String, + with_block: Option, ) -> BuckyResult<()> { - unimplemented!() + let cmd = GroupCommandNewRPath { + group_id, + rpath, + with_block, + }; + + let cmd = GroupCommand::from(cmd); + let result = self + .local_info() + .non_driver + .post_object( + dec_id, + NONObjectInfo { + object_id: cmd.desc().object_id(), + object_raw: cmd.to_vec()?, + object: None, + }, + None, + ) + .await?; + + assert!(result.is_none()); + Ok(()) } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 08be0f5a0..41db0c25c 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -100,7 +100,7 @@ impl RPathClient { match self .0 .non_driver - .post_object(non_proposal.clone(), ood) + .post_object(non_proposal.clone(), Some(ood)) .await { Ok(r) => post_result = Some(Ok(())), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 979451b79..c7f9e7d93 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -6,7 +6,7 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, }; @@ -29,8 +29,8 @@ pub trait NONDriver: Send + Sync { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()>; + to: Option<&ObjectId>, + ) -> BuckyResult>; } #[derive(Clone)] @@ -49,6 +49,10 @@ impl NONDriverHelper { } } + pub fn dec_id(&self) -> &ObjectId { + &self.dec_id + } + pub async fn get_object( &self, object_id: &ObjectId, @@ -74,12 +78,17 @@ impl NONDriverHelper { self.driver.put_object(&self.dec_id, obj).await } - pub async fn post_object(&self, obj: NONObjectInfo, to: &ObjectId) -> BuckyResult<()> { + pub async fn post_object( + &self, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { self.driver.post_object(&self.dec_id, obj, to).await } pub async fn broadcast(&self, obj: NONObjectInfo, to: &[ObjectId]) { - futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), to))).await; + futures::future::join_all(to.iter().map(|to| self.post_object(obj.clone(), Some(to)))) + .await; } pub async fn get_block( diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fcb0dd6da..f7f305a83 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -88,8 +88,8 @@ impl cyfs_group::NONDriver for GroupNONDriver { &self, dec_id: &ObjectId, obj: NONObjectInfo, - to: &ObjectId, - ) -> BuckyResult<()> { + to: Option<&ObjectId>, + ) -> BuckyResult> { self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { @@ -107,12 +107,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { level: NONAPILevel::Router, - target: Some(to.clone()), + target: to.cloned(), flags: 0, }, object: obj, }) .await - .map(|_| ()) + .map(|resp| resp.object) } } From 521bf5e01a10bfe3e9eea4933b11dea9a64af02f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 14:56:29 +0800 Subject: [PATCH 507/553] Rename `control` into `Service` --- .../cyfs-group/src/dec/group_manager.rs | 80 +++++++++---------- src/component/cyfs-group/src/dec/mod.rs | 4 +- .../{rpath_control.rs => rpath_service.rs} | 8 +- src/tests/group-example/src/main.rs | 20 ++--- 4 files changed, 56 insertions(+), 56 deletions(-) rename src/component/cyfs-group/src/dec/{rpath_control.rs => rpath_service.rs} (96%) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 346e75d02..23202fddf 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,19 +12,19 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathControl, RPathEventNotifier, NET_PROTOCOL_VPORT, + RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, }; -type ControlByRPath = HashMap; -type ControlByDec = HashMap; -type ControlByGroup = HashMap; +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; type ClientByRPath = HashMap; type ClientByDec = HashMap; type ClientByGroup = HashMap; struct GroupRPathMgrRaw { - control_by_group: ControlByGroup, + service_by_group: ServiceByGroup, client_by_group: ClientByGroup, } @@ -58,7 +58,7 @@ impl GroupManager { }; let raw = GroupRPathMgrRaw { - control_by_group: ControlByGroup::default(), + service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), }; @@ -69,14 +69,14 @@ impl GroupManager { Ok(mgr) } - pub async fn find_rpath_control( + pub async fn find_rpath_service( &self, group_id: &ObjectId, dec_id: &ObjectId, rpath: &str, is_auto_create: bool, - ) -> BuckyResult { - self.find_rpath_control_inner(group_id, dec_id, rpath, is_auto_create, None, None) + ) -> BuckyResult { + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -155,7 +155,7 @@ impl GroupManager { } // return - pub async fn enum_rpath_control( + pub async fn enum_rpath_service( &self, group_id: &ObjectId, ) -> BuckyResult> { @@ -182,8 +182,8 @@ impl GroupManager { match msg { HotstuffPackage::Block(block) => { let rpath = block.r_path(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -192,14 +192,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Block(block), remote) .await; } HotstuffPackage::BlockVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -208,14 +208,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; } HotstuffPackage::TimeoutVote(target, vote) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -224,14 +224,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; } HotstuffPackage::Timeout(target, tc) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -240,14 +240,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::Timeout(tc), remote) .await; } HotstuffPackage::SyncRequest(target, min_bound, max_bound) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -256,14 +256,14 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; } HotstuffPackage::LastStateRequest(target) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -272,7 +272,7 @@ impl GroupManager { Some(&remote), ) .await?; - control + service .on_message(HotstuffMessage::LastStateRequest, remote) .await; } @@ -309,8 +309,8 @@ impl GroupManager { } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); - let control = self - .find_rpath_control_inner( + let service = self + .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), rpath.r_path(), @@ -320,9 +320,9 @@ impl GroupManager { ) .await; - match control { - Ok(control) => { - control + match service { + Ok(service) => { + service .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } @@ -356,7 +356,7 @@ impl GroupManager { Ok(()) } - async fn find_rpath_control_inner( + async fn find_rpath_service_inner( &self, group_id: &ObjectId, dec_id: &ObjectId, @@ -364,12 +364,12 @@ impl GroupManager { is_auto_create: bool, block: Option<&GroupConsensusBlock>, remote: Option<&ObjectId>, - ) -> BuckyResult { + ) -> BuckyResult { { // read let raw = self.read().await; let found = raw - .control_by_group + .service_by_group .get(group_id) .map_or(None, |by_dec| by_dec.get(dec_id)) .map_or(None, |by_rpath| by_rpath.get(rpath)); @@ -446,7 +446,7 @@ impl GroupManager { }; let found = raw - .control_by_group + .service_by_group .entry(group_id.clone()) .or_insert_with(HashMap::new) .entry(dec_id.clone()) @@ -456,7 +456,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let control = RPathControl::load( + let service = RPathService::load( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -467,8 +467,8 @@ impl GroupManager { store, ) .await?; - entry.insert(control.clone()); - Ok(control) + entry.insert(service.clone()); + Ok(service) } } } diff --git a/src/component/cyfs-group/src/dec/mod.rs b/src/component/cyfs-group/src/dec/mod.rs index 2ad717514..f881db19c 100644 --- a/src/component/cyfs-group/src/dec/mod.rs +++ b/src/component/cyfs-group/src/dec/mod.rs @@ -3,9 +3,9 @@ mod group_events; mod group_manager; mod rpath_client; -mod rpath_control; +mod rpath_service; pub use group_events::*; pub use group_manager::*; pub use rpath_client::*; -pub use rpath_control::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group/src/dec/rpath_control.rs b/src/component/cyfs-group/src/dec/rpath_service.rs similarity index 96% rename from src/component/cyfs-group/src/dec/rpath_control.rs rename to src/component/cyfs-group/src/dec/rpath_service.rs index 593d82db4..b4b90972f 100644 --- a/src/component/cyfs-group/src/dec/rpath_control.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -9,7 +9,7 @@ use crate::{ PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, }; -struct RPathControlRaw { +struct RPathServiceRaw { local_id: ObjectId, rpath: GroupRPath, network_sender: crate::network::Sender, @@ -18,9 +18,9 @@ struct RPathControlRaw { } #[derive(Clone)] -pub struct RPathControl(Arc); +pub struct RPathService(Arc); -impl RPathControl { +impl RPathService { pub(crate) async fn load( local_id: ObjectId, local_device_id: ObjectId, @@ -50,7 +50,7 @@ impl RPathControl { rpath.clone(), ); - let raw = RPathControlRaw { + let raw = RPathServiceRaw { network_sender, pending_proposal_handle, local_id, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 42544e51c..88450ac1b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -505,7 +505,7 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathControl; + use cyfs_group::RPathService; use cyfs_lib::{ DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, @@ -545,7 +545,7 @@ mod GroupDecService { } // pub struct PostProposalRoutine { - // controller: RPathControl, + // service: RPathService, // } // #[async_trait::async_trait] @@ -558,7 +558,7 @@ mod GroupDecService { // ) -> BuckyResult { // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // self.controller.push_proposal(proposal).await?; + // self.service.push_proposal(proposal).await?; // Ok(NONPostObjectInputResponse { object: None }) // } // } @@ -1037,9 +1037,9 @@ async fn main_run() { ) .await; - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group.desc().object_id(), dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1066,9 +1066,9 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1113,9 +1113,9 @@ async fn main_run() { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let control = stack + let service = stack .group_mgr() - .find_rpath_control( + .find_rpath_service( &group_id, dec_app_id.object_id(), &EXAMPLE_RPATH, @@ -1125,7 +1125,7 @@ async fn main_run() { .unwrap(); async_std::task::spawn(async move { - control.push_proposal(proposal).await.unwrap(); + service.push_proposal(proposal).await.unwrap(); }); if i % 10 == 0 { From 3eaf5b90e8c1c482b5b5ba3a9ab7ba4b04e110c5 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 15:34:34 +0800 Subject: [PATCH 508/553] Interface in client for DecAPP --- src/component/cyfs-group-lib/src/delegate.rs | 6 +-- .../cyfs-group-lib/src/group_manager.rs | 37 ++++++++++++++++--- src/component/cyfs-group-lib/src/lib.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 23 ++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/rpath_service.rs diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 21b1e6346..645cd0656 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,4 @@ -use cyfs_base::{ - BuckyResult, Group, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, -}; +use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_lib::NONObjectInfo; @@ -11,7 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()>; + ) -> BuckyResult>; } pub struct ExecuteResult { diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 8c82bc9e1..103807446 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,20 +1,47 @@ -use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_core::DecAppId; +use cyfs_lib::SharedCyfsStack; -use crate::{DelegateFactory, RPathClient}; +use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; #[derive(Clone)] pub struct GroupManager; impl GroupManager { - pub async fn rpath_client(&self, group_id: &ObjectId, rpath: &str) -> BuckyResult { + pub async fn open( + stack: SharedCyfsStack, + delegate_factory: Box, + ) -> BuckyResult { unimplemented!() } - pub async fn register(&self, delegate_factory: Box) -> BuckyResult<()> { + pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { unimplemented!() } - pub async fn unregister(&self) { + pub async fn start_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + delegate: Box, + ) -> BuckyResult { + Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + } + + pub async fn find_rpath_service( + &self, + group_id: ObjectId, + rpath: String, + ) -> BuckyResult { + unimplemented!() + } + + pub async fn rpath_client( + &self, + group_id: ObjectId, + dec_id: DecAppId, + rpath: String, + ) -> BuckyResult { unimplemented!() } } diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 199307bcc..34473bf07 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -2,8 +2,10 @@ mod delegate; mod group_manager; mod objects; mod rpath_client; +mod rpath_service; pub use delegate::*; pub use group_manager::*; pub use objects::*; pub use rpath_client::*; +pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs new file mode 100644 index 000000000..81225ed72 --- /dev/null +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use cyfs_base::BuckyResult; +use cyfs_core::{GroupProposal, GroupRPath}; + +struct RPathServiceRaw {} + +#[derive(Clone)] +pub struct RPathService(Arc); + +impl RPathService { + pub(crate) async fn load() -> BuckyResult { + unimplemented!() + } + + pub fn rpath(&self) -> &GroupRPath { + unimplemented!() + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + unimplemented!() + } +} From 422b2bbd325bcc83a6ec8bca9fd0b7d77c5f3748 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 3 Mar 2023 21:21:44 +0800 Subject: [PATCH 509/553] Interface in client for DecAPP events --- .../cyfs-base/protos/standard_objects.proto | 4 +- src/component/cyfs-base/src/objects/group.rs | 20 +- .../cyfs-core/protos/core_objects.proto | 8 +- .../src/group/group_consensus_block.rs | 16 +- .../cyfs-core/src/group/group_proposal.rs | 18 +- .../cyfs-core/src/group/group_rpath.rs | 14 +- src/component/cyfs-group-lib/Cargo.toml | 3 +- src/component/cyfs-group-lib/src/delegate.rs | 24 +- .../cyfs-group-lib/src/group_manager.rs | 442 +++++++++++++++++- .../cyfs-group-lib/src/rpath_client.rs | 45 +- .../cyfs-group-lib/src/rpath_service.rs | 122 ++++- .../src/consensus/hotstuff/hotstuff.rs | 4 +- .../cyfs-group/src/dec/group_events.rs | 10 +- .../cyfs-group/src/dec/group_manager.rs | 28 +- .../cyfs-group/src/dec/rpath_client.rs | 4 +- .../cyfs-group/src/dec_state/state_pusher.rs | 4 +- .../cyfs-group/src/network/protocol.rs | 6 +- .../engine/storage_engine_group_state.rs | 8 +- .../cyfs-group/src/storage/group_storage.rs | 6 +- src/component/cyfs-lib/src/stack/stack.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 6 +- 21 files changed, 689 insertions(+), 115 deletions(-) diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index cfb722c62..4a9714958 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -72,7 +72,7 @@ message GroupMethodACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; double min_support_percent = 4; string permissions = 5; // ACL-String @@ -83,7 +83,7 @@ message GroupRoleACL { // target optional bytes target_dec_id = 2; - optional string r_path = 3; + optional string rpath = 3; string method = 4; double right_percent = 5; diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index ed7686157..5c8cda714 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -436,7 +436,7 @@ impl TryFrom<&GroupMember> for protos::GroupMember { pub struct GroupMethodACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub min_support_percent: f64, pub permissions: String, // ACL-String } @@ -452,8 +452,8 @@ impl TryFrom for GroupMethodACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -475,8 +475,8 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.min_support_percent = value.min_support_percent; ret.permissions = value.permissions.clone(); @@ -489,7 +489,7 @@ impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { pub struct GroupRoleACL { pub name: String, pub target_dec_id: Option, - pub r_path: Option, + pub rpath: Option, pub method: String, pub right_percent: f64, @@ -508,8 +508,8 @@ impl TryFrom for GroupRoleACL { } else { None }, - r_path: if value.has_r_path() { - Some(value.take_r_path()) + rpath: if value.has_rpath() { + Some(value.take_rpath()) } else { None }, @@ -533,8 +533,8 @@ impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { if let Some(dec_id) = &value.target_dec_id { ret.set_target_dec_id(dec_id.to_vec()?); } - if let Some(r_path) = &value.r_path { - ret.set_r_path(r_path.clone()); + if let Some(rpath) = &value.rpath { + ret.set_rpath(rpath.clone()); } ret.method = value.method.clone(); ret.right_percent = value.right_percent; diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 742c14904..8048b3951 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -333,12 +333,12 @@ message SyncResponseObjectMetaInfo { message GroupRPath { bytes group_id = 1; bytes dec_id = 2; - string r_path = 3; + string rpath = 3; } message GroupProposalDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; @@ -404,7 +404,7 @@ message HotstuffTimeout { message GroupConsensusBlockDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // input bytes body_hash = 2; // hash(Encode(proposals, proposal_result_states, proposal_receiptes)) @@ -437,7 +437,7 @@ message GroupConsensusBlockBodyContent { /* message GroupActionDescContent { // target - GroupRPath r_path = 1; + GroupRPath rpath = 1; // for app string method = 2; diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 35c418552..7d447ad15 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -10,7 +10,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupConsensusBlockDescContent)] pub struct GroupConsensusBlockDescContent { - r_path: GroupRPath, + rpath: GroupRPath, body_hash: HashValue, result_state_id: Option, height: u64, @@ -40,7 +40,7 @@ impl DescContent for GroupConsensusBlockDescContent { impl GroupConsensusBlockDescContent { pub fn rpath(&self) -> &GroupRPath { - &self.r_path + &self.rpath } pub fn result_state_id(&self) -> &Option { @@ -236,7 +236,7 @@ impl GroupConsensusBlockBodyContent { pub trait GroupConsensusBlockObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -248,7 +248,7 @@ pub trait GroupConsensusBlockObject { owner: ObjectId, ) -> Self; fn check(&self) -> bool; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn proposals(&self) -> &Vec; fn result_state_id(&self) -> &Option; fn height(&self) -> u64; @@ -266,7 +266,7 @@ pub trait GroupConsensusBlockObject { impl GroupConsensusBlockObject for GroupConsensusBlock { fn create( - r_path: GroupRPath, + rpath: GroupRPath, proposals: Vec, result_state_id: Option, height: u64, @@ -280,7 +280,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { - r_path, + rpath, result_state_id, height, @@ -319,9 +319,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { } } - fn r_path(&self) -> &GroupRPath { + fn rpath(&self) -> &GroupRPath { let desc = self.0.desc().content(); - &desc.r_path + &desc.rpath } fn proposals(&self) -> &Vec { diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index bf28aafb2..508418f7b 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -6,7 +6,7 @@ use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] pub struct GroupProposalDescContent { - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, @@ -123,7 +123,7 @@ pub type GroupProposal = NamedObjectBase; impl GroupProposalDescContent { pub fn new( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, meta_block_id: Option, @@ -131,7 +131,7 @@ impl GroupProposalDescContent { effective_ending: Option, ) -> GroupProposalDescContent { Self { - r_path, + rpath, method, params, meta_block_id, @@ -158,7 +158,7 @@ impl GroupProposalBodyContent { #[async_trait] pub trait GroupProposalObject { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -169,7 +169,7 @@ pub trait GroupProposalObject { effective_ending: Option, ) -> GroupProposalBuilder; - fn r_path(&self) -> &GroupRPath; + fn rpath(&self) -> &GroupRPath; fn method(&self) -> &str; fn params(&self) -> &Option>; fn params_hash(&self) -> BuckyResult>; @@ -207,7 +207,7 @@ pub trait GroupProposalObject { #[async_trait] impl GroupProposalObject for GroupProposal { fn create( - r_path: GroupRPath, + rpath: GroupRPath, method: String, params: Option>, payload: Option>, @@ -218,7 +218,7 @@ impl GroupProposalObject for GroupProposal { effective_ending: Option, ) -> GroupProposalBuilder { let desc = GroupProposalDescContent { - r_path, + rpath, method, params, meta_block_id, @@ -237,8 +237,8 @@ impl GroupProposalObject for GroupProposal { .owner(owner) } - fn r_path(&self) -> &GroupRPath { - &self.desc().content().r_path + fn rpath(&self) -> &GroupRPath { + &self.desc().content().rpath } fn method(&self) -> &str { diff --git a/src/component/cyfs-core/src/group/group_rpath.rs b/src/component/cyfs-core/src/group/group_rpath.rs index 3b86fbc57..f177015bf 100644 --- a/src/component/cyfs-core/src/group/group_rpath.rs +++ b/src/component/cyfs-core/src/group/group_rpath.rs @@ -1,25 +1,25 @@ use cyfs_base::*; -#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq)] +#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, PartialEq, Hash)] #[cyfs_protobuf_type(crate::codec::protos::GroupRPath)] pub struct GroupRPath { group_id: ObjectId, dec_id: ObjectId, - r_path: String, + rpath: String, } impl std::fmt::Debug for GroupRPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.r_path) + write!(f, "{:?}-{:?}-{:?}", self.group_id, self.dec_id, self.rpath) } } impl GroupRPath { - pub fn new(group_id: ObjectId, dec_id: ObjectId, r_path: String) -> Self { + pub fn new(group_id: ObjectId, dec_id: ObjectId, rpath: String) -> Self { Self { group_id, dec_id, - r_path, + rpath, } } @@ -31,7 +31,7 @@ impl GroupRPath { &self.dec_id } - pub fn r_path(&self) -> &str { - self.r_path.as_str() + pub fn rpath(&self) -> &str { + self.rpath.as_str() } } diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index e7cfda851..bad3d3112 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -31,4 +31,5 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } \ No newline at end of file +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 645cd0656..3cc99902b 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -1,6 +1,6 @@ -use cyfs_base::{BuckyResult, ObjectId, ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef}; +use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal}; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SingleOpEnvStub}; #[async_trait::async_trait] pub trait DelegateFactory: Send + Sync { @@ -23,30 +23,36 @@ pub trait RPathDelegate: Sync + Send { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult; async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, + object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult<()>; async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ); } #[async_trait::async_trait] pub trait GroupObjectMapProcessor: Send + Sync { - async fn create_single_op_env(&self) -> BuckyResult; - async fn create_sub_tree_op_env(&self) -> BuckyResult; + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult; + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 103807446..f93be45f0 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -1,37 +1,132 @@ -use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::DecAppId; -use cyfs_lib::SharedCyfsStack; +use std::{collections::HashMap, sync::Arc}; -use crate::{DelegateFactory, RPathClient, RPathDelegate, RPathService}; +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + RawConvertTo, RawDecode, +}; +use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, + SharedCyfsStack, +}; +use cyfs_util::EventListenerAsyncRoutine; + +use crate::{ + DelegateFactory, ExecuteResult, GroupCommand, GroupCommandCommited, GroupCommandExecute, + GroupCommandExecuteResult, GroupCommandNewRPath, GroupCommandObject, GroupCommandType, + GroupCommandVerify, RPathClient, RPathDelegate, RPathService, +}; + +type ServiceByRPath = HashMap; +type ServiceByDec = HashMap; +type ServiceByGroup = HashMap; + +type ClientByRPath = HashMap; +type ClientByDec = HashMap; +type ClientByGroup = HashMap; + +struct GroupManagerRaw { + stack: SharedCyfsStack, + requestor: HttpRequestorRef, + delegate_factory: Option>, + clients: RwLock, + services: RwLock, + local_zone: Option, +} #[derive(Clone)] -pub struct GroupManager; +pub struct GroupManager(Arc); impl GroupManager { pub async fn open( stack: SharedCyfsStack, delegate_factory: Box, + requestor_type: &CyfsStackRequestorType, ) -> BuckyResult { - unimplemented!() + if stack.dec_id().is_none() { + let msg = "the stack should be opened with dec-id"; + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let dec_id = stack.dec_id().unwrap().clone(); + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + let router_handler_manager = stack.router_handlers().clone(); + + let mgr = Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: Some(delegate_factory), + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + })); + + // TODO: other filters? only local zone + let filter = format!( + "obj_type == {} && dec_id == {}", + CoreObjectType::GroupCommand as u16, + dec_id, + ); + + router_handler_manager + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-cmd-{}", dec_id).as_str(), + 0, + Some(filter), + None, + RouterHandlerAction::Pass, + Some(Box::new(mgr.clone())), + ) + .await?; + + Ok(mgr) } - pub async fn open_as_client(stack: SharedCyfsStack) -> BuckyResult { + pub async fn open_as_client( + stack: SharedCyfsStack, + requestor_type: &CyfsStackRequestorType, + ) -> BuckyResult { + let requestor = stack.select_requestor(requestor_type); + let local_zone = stack.local_device().desc().owner().clone(); + + Ok(Self(Arc::new(GroupManagerRaw { + stack, + requestor, + delegate_factory: None, + clients: RwLock::new(HashMap::new()), + services: RwLock::new(HashMap::new()), + local_zone, + }))) + } + + pub async fn stop(&self) { unimplemented!() } + pub fn stack(&self) -> &SharedCyfsStack { + &self.0.stack + } + pub async fn start_rpath_service( &self, group_id: ObjectId, rpath: String, delegate: Box, ) -> BuckyResult { - Err(BuckyError::new(BuckyErrorCode::NotImplement, "")) + unimplemented!() } pub async fn find_rpath_service( &self, - group_id: ObjectId, - rpath: String, + group_id: &ObjectId, + rpath: &str, ) -> BuckyResult { unimplemented!() } @@ -40,8 +135,329 @@ impl GroupManager { &self, group_id: ObjectId, dec_id: DecAppId, - rpath: String, - ) -> BuckyResult { - unimplemented!() + rpath: &str, + ) -> RPathClient { + { + let clients = self.0.clients.read().await; + let found = clients + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id.object_id())) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if let Some(found) = found { + return found.clone(); + } + } + + { + let client = RPathClient::new( + GroupRPath::new(group_id, dec_id.object_id().clone(), rpath.to_string()), + self.0.stack.dec_id().cloned(), + self.0.stack.non_service().clone(), + ); + + let mut clients = self.0.clients.write().await; + let client = clients + .entry(group_id) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert(client); + client.clone() + } + } + + async fn on_command( + &self, + cmd: GroupCommand, + ) -> BuckyResult> { + match cmd.into_cmd() { + crate::GroupCommandBodyContent::NewRPath(cmd) => { + self.on_new_rpath(cmd).await.map(|_| None) + } + crate::GroupCommandBodyContent::Execute(cmd) => { + self.on_execute(cmd).await.map(|r| Some(r)) + } + crate::GroupCommandBodyContent::ExecuteResult(_) => { + let msg = format!( + "should not get the cmd({:?}) in sdk", + GroupCommandType::ExecuteResult + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)) + } + crate::GroupCommandBodyContent::Verify(cmd) => self.on_verify(cmd).await.map(|_| None), + crate::GroupCommandBodyContent::Commited(cmd) => { + self.on_commited(cmd).await.map(|_| None) + } + } + } + + async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let group_id = &cmd.group_id; + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.rpath.as_str(); + + { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + if found.is_some() { + return Ok(()); + } + } + + let delegate = factory + .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) + .await?; + + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(()); + } + }; + + new_service.start().await; + Ok(()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } + } + + async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try execute proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try execute proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let mut result = service + .on_execute(&cmd.proposal, &cmd.prev_state_id) + .await?; + + Ok(GroupCommandExecuteResult { + result_state_id: result.result_state_id.take(), + receipt: result.receipt.take(), + context: result.context.take(), + }) + } + + async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try verify proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try verify proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) + .await + } + + async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + let group_id = cmd.proposal.rpath().group_id(); + let dec_id = self.0.stack.dec_id().unwrap(); + let rpath = cmd.proposal.rpath().rpath(); + + if cmd.proposal.rpath().dec_id() != dec_id { + let msg = format!( + "try commited proposal in different dec {:?}, expected: {:?}", + cmd.proposal.rpath().dec_id(), + dec_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + + let service = { + let services = self.0.services.read().await; + let found = services + .get(group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + match found { + Some(found) => found.clone(), + None => { + let msg = format!("try commited proposal in not exist rpath {}", rpath); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); + } + } + }; + + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } +} + +#[async_trait::async_trait] +impl EventListenerAsyncRoutine + for GroupManager +{ + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + let req_common = ¶m.request.common; + if req_common.level != NONAPILevel::NOC + || req_common.source.zone.zone != self.0.local_zone + || self.0.local_zone.is_none() + || self.0.stack.dec_id().is_none() + { + log::warn!( + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id() + ); + + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let obj = ¶m.request.object; + match obj.object.as_ref() { + None => { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }) + } + Some(any_obj) => { + assert_eq!(any_obj.obj_type(), CoreObjectType::GroupCommand as u16); + if any_obj.obj_type() != CoreObjectType::GroupCommand as u16 { + return Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Reject, + request: None, + response: None, + }); + } + + let (cmd, remain) = GroupCommand::raw_decode(obj.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + let resp_obj = self.on_command(cmd).await; + + let resp_cmd = resp_obj.map_or_else( + |err| Err(err), + |resp_obj| { + resp_obj.map_or(Ok(None), |resp_cmd| { + let resp_cmd = GroupCommand::from(resp_cmd); + resp_cmd.to_vec().map(|buf| { + Some(NONObjectInfo::new(resp_cmd.desc().object_id(), buf, None)) + }) + }) + }, + ); + + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: Some(resp_cmd.map(|cmd| NONPostObjectInputResponse { object: cmd })), + }) + } + } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 2fea6dcf7..ea032715b 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -1,26 +1,55 @@ use std::sync::Arc; -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, GroupMemberScope, NamedObject, ObjectDesc, ObjectId, - RawConvertTo, +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, }; -use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_lib::NONObjectInfo; -struct RPathClientRaw {} +struct RPathClientRaw { + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, +} #[derive(Clone)] pub struct RPathClient(Arc); impl RPathClient { + pub(crate) fn new( + rpath: GroupRPath, + local_dec_id: Option, + requestor: NONRequestor, + ) -> Self { + Self(Arc::new(RPathClientRaw { + requestor, + rpath, + local_dec_id, + })) + } + pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn post_proposal( &self, proposal: &GroupProposal, ) -> BuckyResult> { - unimplemented!() + self.0 + .requestor + .post_object(NONPostObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: self.0.local_dec_id.clone(), + level: NONAPILevel::Router, + target: Some(proposal.rpath().group_id().clone()), + flags: 0, + }, + object: NONObjectInfo::new(proposal.desc().object_id(), proposal.to_vec()?, None), + }) + .await + .map(|resp| resp.object) } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 81225ed72..cebe445dd 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,23 +1,133 @@ use std::sync::Arc; -use cyfs_base::BuckyResult; -use cyfs_core::{GroupProposal, GroupRPath}; +use cyfs_base::{BuckyResult, ObjectId}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, +}; -struct RPathServiceRaw {} +use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; + +struct RPathServiceRaw { + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, +} #[derive(Clone)] pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load() -> BuckyResult { + pub fn rpath(&self) -> &GroupRPath { unimplemented!() } - pub fn rpath(&self) -> &GroupRPath { + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + // post http unimplemented!() } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub(crate) fn new( + rpath: GroupRPath, + requestor: HttpRequestorRef, + delegate: Box, + stack: SharedCyfsStack, + ) -> Self { + Self(Arc::new(RPathServiceRaw { + rpath, + requestor, + delegate, + stack, + })) + } + + pub(crate) async fn start(&self) -> BuckyResult { + // post create command unimplemented!() } + + pub(crate) async fn on_execute( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + ) -> BuckyResult { + self.0 + .delegate + .on_execute( + proposal, + prev_state_id, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_verify( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + ) -> BuckyResult<()> { + self.0 + .delegate + .on_verify( + proposal, + prev_state_id, + execute_result, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } + + pub(crate) async fn on_commited( + &self, + proposal: &GroupProposal, + prev_state_id: &Option, + execute_result: &ExecuteResult, + block: &GroupConsensusBlock, + ) { + self.0 + .delegate + .on_commited( + proposal, + prev_state_id, + execute_result, + block, + &GroupObjectMapProcessorImpl { + stack: self.0.stack.clone(), + }, + ) + .await + } +} + +struct GroupObjectMapProcessorImpl { + stack: SharedCyfsStack, +} + +#[async_trait::async_trait] +impl GroupObjectMapProcessor for GroupObjectMapProcessorImpl { + async fn create_single_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_single_op_env_with_access(access) + .await + } + + async fn create_sub_tree_op_env( + &self, + access: Option, + ) -> BuckyResult { + self.stack + .root_state_stub(None, None) + .create_isolate_path_op_env_with_access(access) + .await + } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index eaaaed06e..d2dbcc517 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,7 +11,7 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; +use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; use cyfs_lib::{NONObjectInfo}; use futures::FutureExt; use itertools::Itertools; @@ -20,7 +20,7 @@ use crate::{ consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, + HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, }; /** diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index fc3d12c63..9bda7e340 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,6 @@ use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - RawDecode, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -130,3 +130,9 @@ impl RPathEventNotifier { assert!(result.is_err() || result.unwrap().is_none()); } } + +#[async_trait::async_trait] +pub trait GroupObjectMapProcessor: Send + Sync { + async fn create_single_op_env(&self) -> BuckyResult; + async fn create_sub_tree_op_env(&self) -> BuckyResult; +} diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 23202fddf..7a9708ccc 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -181,12 +181,12 @@ impl GroupManager { ) -> BuckyResult<()> { match msg { HotstuffPackage::Block(block) => { - let rpath = block.r_path(); + let rpath = block.rpath(); let service = self .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, Some(&block), Some(&remote), @@ -202,7 +202,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -218,7 +218,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -234,7 +234,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -250,7 +250,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -266,7 +266,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -278,9 +278,9 @@ impl GroupManager { } HotstuffPackage::StateChangeNotify(header_block, qc_block) => { // TODO: unimplemented - // let rpath = header_block.r_path(); + // let rpath = header_block.rpath(); // let client = self - // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) // .await?; // client // .on_message( @@ -292,10 +292,10 @@ impl GroupManager { HotstuffPackage::ProposalResult(proposal_id, result) => { let rpath = result.as_ref().map_or_else( |(_, target)| target.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( @@ -313,7 +313,7 @@ impl GroupManager { .find_rpath_service_inner( rpath.group_id(), rpath.dec_id(), - rpath.r_path(), + rpath.rpath(), false, None, Some(&remote), @@ -328,7 +328,7 @@ impl GroupManager { } _ => { let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) @@ -342,7 +342,7 @@ impl GroupManager { |status| status.block_desc.content().rpath(), ); let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.r_path()) + .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) .await?; client .on_message( diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 41db0c25c..43fb8e559 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -78,13 +78,13 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { - assert_eq!(proposal.r_path(), &self.0.rpath); + assert_eq!(proposal.rpath(), &self.0.rpath); // TODO: signature let group = self .0 .non_driver - .get_group(proposal.r_path().group_id(), None, None) + .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); let proposal_id = proposal.desc().object_id(); diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 571c1ca13..99c3fed62 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -222,7 +222,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) @@ -248,7 +248,7 @@ impl StateChanggeRunner { let group = self .non_driver .get_group( - block.r_path().group_id(), + block.rpath().group_id(), Some(block.group_chunk_id()), None, ) diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 7e32fdc4d..1f2a46a73 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -321,16 +321,16 @@ impl std::fmt::Debug for HotstuffPackage { impl HotstuffPackage { pub(crate) fn rpath(&self) -> &GroupRPath { match self { - HotstuffPackage::Block(block) => block.r_path(), + HotstuffPackage::Block(block) => block.rpath(), HotstuffPackage::BlockVote(addr, _) => addr.check_rpath(), HotstuffPackage::TimeoutVote(addr, _) => addr.check_rpath(), HotstuffPackage::Timeout(addr, _) => addr.check_rpath(), HotstuffPackage::SyncRequest(addr, _, _) => addr.check_rpath(), - HotstuffPackage::StateChangeNotify(block, _) => block.r_path(), + HotstuffPackage::StateChangeNotify(block, _) => block.rpath(), HotstuffPackage::LastStateRequest(addr) => addr.check_rpath(), HotstuffPackage::ProposalResult(_, result) => result.as_ref().map_or_else( |(_, addr)| addr.check_rpath(), - |(_, block, _)| block.r_path(), + |(_, block, _)| block.rpath(), ), HotstuffPackage::QueryState(addr, _) => addr.check_rpath(), HotstuffPackage::VerifiableState(_, result) => result.as_ref().map_or_else( diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 63158a865..029b09e78 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -5,12 +5,12 @@ use cyfs_base::{ ObjectMapIsolatePathOpEnvRef, ObjectMapPathOpEnvRef, ObjectMapRootCacheRef, ObjectMapRootManagerRef, ObjectMapSimpleContentType, ObjectMapSingleOpEnvRef, OpEnvPathAccess, }; -use cyfs_core::{GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout}; -use cyfs_group_lib::GroupObjectMapProcessor; +use cyfs_core::GroupConsensusBlockObject; use crate::{ - GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, GROUP_STATE_PATH_DEC_STATE, - GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, GROUP_STATE_PATH_RESULT_STATE, + GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, GROUP_STATE_PATH_BLOCK, + GROUP_STATE_PATH_DEC_STATE, GROUP_STATE_PATH_FLIP_TIME, GROUP_STATE_PATH_RANGE, + GROUP_STATE_PATH_RESULT_STATE, }; use super::{StorageCacheInfo, StorageEngine, StorageWriter}; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index a1a681259..3a762c1b6 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -9,12 +9,12 @@ use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{GroupObjectMapProcessor, GroupRPathStatus}; +use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use crate::{ - storage::StorageWriter, GroupStatePath, NONDriverHelper, PROPOSAL_MAX_TIMEOUT, - STATE_PATH_SEPARATOR, + storage::StorageWriter, GroupObjectMapProcessor, GroupStatePath, NONDriverHelper, + PROPOSAL_MAX_TIMEOUT, STATE_PATH_SEPARATOR, }; use super::{ diff --git a/src/component/cyfs-lib/src/stack/stack.rs b/src/component/cyfs-lib/src/stack/stack.rs index 2f162c331..05cd8dfd7 100644 --- a/src/component/cyfs-lib/src/stack/stack.rs +++ b/src/component/cyfs-lib/src/stack/stack.rs @@ -94,7 +94,7 @@ pub struct SharedCyfsStack { // uni_stack uni_stack: Arc>, - requestor_holder: RequestorHolder, + requestor_holder: Arc>, } #[derive(Debug, Clone)] @@ -493,14 +493,15 @@ impl SharedCyfsStack { device_info: Arc::new(RwLock::new(None)), uni_stack: Arc::new(OnceCell::new()), - requestor_holder, + requestor_holder: Arc::new(RwLock::new(requestor_holder)), }; Ok(ret) } pub async fn stop(&self) { - self.requestor_holder.stop().await; + let requestor_holder = self.requestor_holder.read().unwrap(); + requestor_holder.stop().await; self.router_handlers.stop().await; @@ -744,6 +745,11 @@ impl SharedCyfsStack { pub fn uni_stack(&self) -> &UniCyfsStackRef { self.uni_stack.get_or_init(|| self.create_uni_stack()) } + + pub fn select_requestor(&self, requestor_type: &CyfsStackRequestorType) -> HttpRequestorRef { + let mut requestor_holder = self.requestor_holder.write().unwrap(); + requestor_holder.select_requestor(&self.param, requestor_type) + } } impl UniCyfsStack for SharedCyfsStack { diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index f7f305a83..431915a96 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: None, flags: 0, @@ -105,7 +105,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::Router, + level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, From 18935b9cfbec2ee2fcd9692114daf207cc396032 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 16:49:16 +0800 Subject: [PATCH 510/553] Interface for client --- src/component/cyfs-group-lib/Cargo.toml | 1 + src/component/cyfs-group-lib/src/delegate.rs | 1 + .../cyfs-group-lib/src/group_manager.rs | 255 ++++++++---------- .../cyfs-group-lib/src/input_request.rs | 0 src/component/cyfs-group-lib/src/lib.rs | 12 + .../cyfs-group-lib/src/output_request.rs | 7 + src/component/cyfs-group-lib/src/processor.rs | 6 + src/component/cyfs-group-lib/src/request.rs | 0 .../cyfs-group-lib/src/request_codec.rs | 21 ++ src/component/cyfs-group-lib/src/requestor.rs | 210 +++++++++++++++ .../cyfs-group-lib/src/rpath_client.rs | 2 + .../cyfs-group-lib/src/rpath_service.rs | 14 +- .../cyfs-lib/src/non/output_request.rs | 20 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- 14 files changed, 391 insertions(+), 162 deletions(-) create mode 100644 src/component/cyfs-group-lib/src/input_request.rs create mode 100644 src/component/cyfs-group-lib/src/output_request.rs create mode 100644 src/component/cyfs-group-lib/src/processor.rs create mode 100644 src/component/cyfs-group-lib/src/request.rs create mode 100644 src/component/cyfs-group-lib/src/request_codec.rs create mode 100644 src/component/cyfs-group-lib/src/requestor.rs diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index bad3d3112..740b303cd 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = '0.8' } async-recursion = '1.0' rand = '0.8.5' itertools = "0.10.3" +http-types = '2.12' cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index 3cc99902b..d678438c3 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -9,6 +9,7 @@ pub trait DelegateFactory: Send + Sync { group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult>; } diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f93be45f0..f442d5c55 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,7 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupProposalObject, GroupRPath}; +use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, @@ -195,98 +195,28 @@ impl GroupManager { } async fn on_new_rpath(&self, cmd: GroupCommandNewRPath) -> BuckyResult<()> { - match self.0.delegate_factory.as_ref() { - Some(factory) => { - let group_id = &cmd.group_id; - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.rpath.as_str(); - - { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - if found.is_some() { - return Ok(()); - } - } - - let delegate = factory - .create_rpath_delegate(&cmd.group_id, &cmd.rpath, cmd.with_block.as_ref()) - .await?; - - let new_service = { - let mut is_new = false; - - let mut services = self.0.services.write().await; - let service = services - .entry(group_id.clone()) - .or_insert_with(HashMap::new) - .entry(dec_id.clone()) - .or_insert_with(HashMap::new) - .entry(rpath.to_string()) - .or_insert_with(|| { - is_new = true; - - RPathService::new( - GroupRPath::new( - group_id.clone(), - dec_id.clone(), - rpath.to_string(), - ), - self.0.requestor.clone(), - delegate, - self.0.stack.clone(), - ) - }); - - if is_new { - service.clone() - } else { - return Ok(()); - } - }; - - new_service.start().await; - Ok(()) - } - None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), - } + self.find_or_restart_service( + &cmd.group_id, + self.0.stack.dec_id().unwrap(), + cmd.rpath.as_str(), + &cmd.with_block, + true, + ) + .await + .map(|_| ()) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try execute proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try execute proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) @@ -300,36 +230,16 @@ impl GroupManager { } async fn on_verify(&self, mut cmd: GroupCommandVerify) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); - - if cmd.proposal.rpath().dec_id() != dec_id { - let msg = format!( - "try verify proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - - let service = { - let services = self.0.services.read().await; - let found = services - .get(group_id) - .and_then(|by_dec| by_dec.get(dec_id)) - .and_then(|by_rpath| by_rpath.get(rpath)); - - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try verify proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } - } - }; + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -343,47 +253,102 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let group_id = cmd.proposal.rpath().group_id(); - let dec_id = self.0.stack.dec_id().unwrap(); - let rpath = cmd.proposal.rpath().rpath(); + let rpath = cmd.proposal.rpath(); + let service = self + .find_or_restart_service( + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + &None, + false, + ) + .await?; - if cmd.proposal.rpath().dec_id() != dec_id { + let result = ExecuteResult { + result_state_id: cmd.result_state_id.take(), + receipt: cmd.receipt.take(), + context: cmd.context.take(), + }; + + service + .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) + .await; + Ok(()) + } + + async fn find_or_restart_service( + &self, + group_id: &ObjectId, + dec_id: &ObjectId, + rpath: &str, + with_block: &Option, + is_new: bool, + ) -> BuckyResult { + if dec_id != self.0.stack.dec_id().unwrap() { let msg = format!( - "try commited proposal in different dec {:?}, expected: {:?}", - cmd.proposal.rpath().dec_id(), - dec_id + "try find proposal in different dec {:?}, expected: {:?}", + dec_id, + self.0.stack.dec_id().unwrap() ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - let service = { + { let services = self.0.services.read().await; let found = services .get(group_id) .and_then(|by_dec| by_dec.get(dec_id)) .and_then(|by_rpath| by_rpath.get(rpath)); - match found { - Some(found) => found.clone(), - None => { - let msg = format!("try commited proposal in not exist rpath {}", rpath); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); - } + if let Some(found) = found { + return Ok(found.clone()); } - }; + } - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; + match self.0.delegate_factory.as_ref() { + Some(factory) => { + let delegate = factory + .create_rpath_delegate(group_id, rpath, with_block.as_ref(), is_new) + .await?; - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; - Ok(()) + let new_service = { + let mut is_new = false; + + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.clone()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + is_new = true; + + RPathService::new( + GroupRPath::new( + group_id.clone(), + dec_id.clone(), + rpath.to_string(), + ), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + + if is_new { + service.clone() + } else { + return Ok(service.clone()); + } + }; + + new_service.start().await; + Ok(new_service.clone()) + } + None => Err(BuckyError::new(BuckyErrorCode::Reject, "is not service")), + } } } diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 34473bf07..519a64040 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -1,11 +1,23 @@ mod delegate; mod group_manager; +mod input_request; mod objects; +mod output_request; +mod processor; +mod request; +mod request_codec; +mod requestor; mod rpath_client; mod rpath_service; pub use delegate::*; pub use group_manager::*; +pub use input_request::*; pub use objects::*; +pub use output_request::*; +pub use processor::*; +pub(crate) use request::*; +pub use request_codec::*; +pub use requestor::*; pub use rpath_client::*; pub use rpath_service::*; diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs new file mode 100644 index 000000000..c847668df --- /dev/null +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -0,0 +1,7 @@ +use cyfs_base::ObjectId; + +#[derive(Debug)] +pub struct GroupStartServiceOutputRequest { + pub group_id: ObjectId, + pub rpath: String, +} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs new file mode 100644 index 000000000..925061f3e --- /dev/null +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +#[async_trait::async_trait] +pub trait GroupOutputProcessor: Send + Sync {} + +pub type GroupOutputProcessorRef = Arc; diff --git a/src/component/cyfs-group-lib/src/request.rs b/src/component/cyfs-group-lib/src/request.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs new file mode 100644 index 000000000..c4f330efc --- /dev/null +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -0,0 +1,21 @@ +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use serde_json::{Map, Value}; + +use crate::output_request::GroupStartServiceOutputRequest; + +impl JsonCodec for GroupStartServiceOutputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs new file mode 100644 index 000000000..437a01184 --- /dev/null +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use cyfs_base::{ + BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, + CYFS_API_LEVEL, +}; +use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_lib::{ + HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, +}; +use http_types::{Method, Request, Url}; + +use crate::{ + output_request::GroupStartServiceOutputRequest, + processor::{GroupOutputProcessor, GroupOutputProcessorRef}, +}; + +#[derive(Clone)] +pub struct GroupRequestor { + dec_id: ObjectId, + requestor: HttpRequestorRef, + service_url: Url, +} + +impl GroupRequestor { + pub fn new(dec_id: ObjectId, requestor: HttpRequestorRef) -> Self { + let addr = requestor.remote_addr(); + + let url = format!("http://{}/group/", addr); + let url = Url::parse(&url).unwrap(); + + Self { + dec_id, + requestor, + service_url: url, + } + } + + pub fn clone_processor(&self) -> GroupOutputProcessorRef { + Arc::new(self.clone()) + } + + fn encode_common_headers( + &self, + // action: NONAction, + com_req: &NONOutputRequestCommon, + http_req: &mut Request, + ) { + let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); + http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); + + RequestorHelper::encode_opt_header_with_encoding( + http_req, + cyfs_base::CYFS_REQ_PATH, + com_req.req_path.as_deref(), + ); + + // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + + http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); + + if let Some(target) = &com_req.target { + http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); + } + + if let Some(source) = &com_req.source { + http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); + } + + http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); + } + + fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(dec_id), + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, + } + } + + pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + log::info!("will start group service: {:?}", rpath); + + let url = self.service_url.join("start-service").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + let req = GroupStartServiceOutputRequest { + group_id: rpath.group_id().clone(), + rpath: rpath.rpath().to_string(), + }; + + self.encode_common_headers( + &Self::make_default_common(rpath.dec_id().clone()), + &mut http_req, + ); + let body = req.encode_string(); + http_req.set_body(body); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group start service failed, read body string error! req={:?} {}", + req, e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!("group start service success"); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group start service failed: rpath={:?}, status={}, {}", + rpath, + code, + e + ); + Err(e) + } + } + } + + pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + let proposal_id = proposal.desc().object_id(); + log::info!( + "will push proposal: {:?}, {}", + proposal.rpath(), + proposal_id + ); + + let url = self.service_url.join("push-proposal").unwrap(); + let mut http_req = Request::new(Method::Put, url); + + self.encode_common_headers( + &Self::make_default_common(proposal.rpath().dec_id().clone()), + &mut http_req, + ); + + NONRequestorHelper::encode_object_info( + &mut http_req, + NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + ); + + let mut resp = self.requestor.request(http_req).await?; + + match resp.status() { + code if code.is_success() => { + let body = resp.body_string().await.map_err(|e| { + let msg = format!( + "group push proposal failed, read body string error! req={:?}/{} {}", + proposal.rpath(), + proposal_id, + e + ); + log::error!("{}", msg); + + BuckyError::from(msg) + })?; + + // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // error!( + // "decode group start service resp from body string error: body={} {}", + // body, e, + // ); + // e + // })?; + + log::debug!( + "group push proposal success, req={:?}/{}", + proposal.rpath(), + proposal_id + ); + + Ok(()) + } + code @ _ => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!( + "group push proposal failed: rpath={:?}/{}, status={}, {}", + proposal.rpath(), + proposal_id, + code, + e + ); + Err(e) + } + } + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupRequestor {} diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index ea032715b..7d7c9a613 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -32,6 +32,8 @@ impl RPathClient { &self.0.rpath } + // post proposal to the admins, it's same as calling to non.post_object with default parameters; + // and you can call the non.post_object with more parameters. pub async fn post_proposal( &self, proposal: &GroupProposal, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index cebe445dd..95811e339 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -6,11 +6,11 @@ use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, RPathDelegate}; +use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; struct RPathServiceRaw { rpath: GroupRPath, - requestor: HttpRequestorRef, + requestor: GroupRequestor, delegate: Box, stack: SharedCyfsStack, } @@ -20,12 +20,12 @@ pub struct RPathService(Arc); impl RPathService { pub fn rpath(&self) -> &GroupRPath { - unimplemented!() + &self.0.rpath } pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - unimplemented!() + self.0.requestor.push_proposal(proposal).await } pub(crate) fn new( @@ -35,16 +35,16 @@ impl RPathService { stack: SharedCyfsStack, ) -> Self { Self(Arc::new(RPathServiceRaw { + requestor: GroupRequestor::new(rpath.dec_id().clone(), requestor), rpath, - requestor, delegate, stack, })) } - pub(crate) async fn start(&self) -> BuckyResult { + pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - unimplemented!() + self.0.requestor.start_group_service(self.rpath()).await } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-lib/src/non/output_request.rs b/src/component/cyfs-lib/src/non/output_request.rs index d4950ce33..b6e96dcb3 100644 --- a/src/component/cyfs-lib/src/non/output_request.rs +++ b/src/component/cyfs-lib/src/non/output_request.rs @@ -4,7 +4,7 @@ use cyfs_base::*; use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NONOutputRequestCommon { // 请求路径,可为空 pub req_path: Option, @@ -130,14 +130,22 @@ impl NONUpdateObjectMetaOutputRequest { Self::new(NONAPILevel::NOC, object_id, access) } - pub fn new_non(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_non( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::NON, object_id, access); ret.common.target = target.map(|v| v.into()); ret } - pub fn new_router(target: Option, object_id: ObjectId, access: Option) -> Self { + pub fn new_router( + target: Option, + object_id: ObjectId, + access: Option, + ) -> Self { let mut ret = Self::new(NONAPILevel::Router, object_id, access); ret.common.target = target; @@ -243,7 +251,6 @@ impl NONGetObjectOutputRequest { } } - impl fmt::Display for NONGetObjectOutputRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "common: {}", self.common)?; @@ -338,7 +345,6 @@ impl fmt::Display for NONPostObjectOutputResponse { } } - // select #[derive(Clone)] pub struct NONSelectObjectOutputRequest { @@ -392,7 +398,6 @@ impl fmt::Display for NONSelectObjectOutputRequest { } } - #[derive(Clone)] pub struct NONSelectObjectOutputResponse { pub objects: Vec, @@ -470,7 +475,6 @@ impl fmt::Display for NONDeleteObjectOutputRequest { } } - #[derive(Clone)] pub struct NONDeleteObjectOutputResponse { pub object: Option, @@ -479,7 +483,7 @@ pub struct NONDeleteObjectOutputResponse { impl fmt::Display for NONDeleteObjectOutputResponse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "object: {:?}", self.object)?; - + Ok(()) } } diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 431915a96..9333e7981 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::NOC, target: None, flags: 0, From b5b39af10ff2443daee09238bfb1720013b72976 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 7 Mar 2023 21:35:56 +0800 Subject: [PATCH 511/553] Export to SDK --- .../cyfs-group-lib/src/input_request.rs | 10 + .../cyfs-group-lib/src/output_request.rs | 4 + src/component/cyfs-group-lib/src/processor.rs | 24 ++- .../cyfs-group-lib/src/request_codec.rs | 19 +- src/component/cyfs-group-lib/src/requestor.rs | 54 +++-- .../cyfs-group-lib/src/rpath_service.rs | 21 +- src/component/cyfs-stack/Cargo.toml | 1 + src/component/cyfs-stack/src/group/mod.rs | 5 + .../cyfs-stack/src/group/processor.rs | 25 +++ .../cyfs-stack/src/group/transform.rs | 190 ++++++++++++++++++ .../cyfs-stack/src/group_api/acl/group_acl.rs | 61 ++++++ .../cyfs-stack/src/group_api/acl/mod.rs | 3 + src/component/cyfs-stack/src/group_api/mod.rs | 7 + .../group_api/router/group_service_router.rs | 133 ++++++++++++ .../src/group_api/router/local_service.rs | 113 +++++++++++ .../cyfs-stack/src/group_api/router/mod.rs | 5 + .../src/group_api/service/group_handler.rs | 125 ++++++++++++ .../src/group_api/service/group_listener.rs | 77 +++++++ .../src/group_api/service/group_service.rs | 35 ++++ .../cyfs-stack/src/group_api/service/mod.rs | 7 + .../cyfs-stack/src/interface/http_listener.rs | 11 + .../src/interface/listener_manager.rs | 14 +- src/component/cyfs-stack/src/lib.rs | 2 + .../cyfs-stack/src/stack/cyfs_stack.rs | 12 +- 24 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/component/cyfs-stack/src/group/mod.rs create mode 100644 src/component/cyfs-stack/src/group/processor.rs create mode 100644 src/component/cyfs-stack/src/group/transform.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/group_acl.rs create mode 100644 src/component/cyfs-stack/src/group_api/acl/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/group_service_router.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/local_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/router/mod.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_handler.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_listener.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/group_service.rs create mode 100644 src/component/cyfs-stack/src/group_api/service/mod.rs diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index e69de29bb..0f861ea3c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -0,0 +1,10 @@ +use cyfs_base::ObjectId; + +pub struct GroupStartServiceInputRequest { + pub group_id: ObjectId, + pub rpath: String, +} + +pub struct GroupStartServiceInputResponse {} + +pub struct GroupPushProposalInputResponse {} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index c847668df..f65e02e3e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -5,3 +5,7 @@ pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, pub rpath: String, } + +pub struct GroupStartServiceOutputResponse {} + +pub struct GroupPushProposalOutputResponse {} diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 925061f3e..9aec5a354 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -1,6 +1,26 @@ use std::sync::Arc; +use cyfs_base::BuckyResult; +use cyfs_core::GroupProposal; +use cyfs_lib::NONOutputRequestCommon; + +use crate::{ + GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, +}; + #[async_trait::async_trait] -pub trait GroupOutputProcessor: Send + Sync {} +pub trait GroupOutputProcessor: Send + Sync { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult; + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} -pub type GroupOutputProcessorRef = Arc; +pub type GroupOutputProcessorRef = Arc>; diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index c4f330efc..58404d6b0 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,7 +1,7 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::output_request::GroupStartServiceOutputRequest; +use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { @@ -19,3 +19,20 @@ impl JsonCodec for GroupStartServiceOutputReques }) } } + +impl JsonCodec for GroupStartServiceInputRequest { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); + JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, + rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + }) + } +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 437a01184..462b1df85 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -13,6 +13,7 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, + GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -37,7 +38,7 @@ impl GroupRequestor { } pub fn clone_processor(&self) -> GroupOutputProcessorRef { - Arc::new(self.clone()) + Arc::new(Box::new(self.clone())) } fn encode_common_headers( @@ -70,7 +71,7 @@ impl GroupRequestor { http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { + pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { NONOutputRequestCommon { req_path: None, source: None, @@ -81,21 +82,23 @@ impl GroupRequestor { } } - pub async fn start_group_service(&self, rpath: &GroupRPath) -> BuckyResult<()> { + pub async fn start_service( + &self, + req_common: NONOutputRequestCommon, + group_id: &ObjectId, + rpath: &str, + ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); let url = self.service_url.join("start-service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { - group_id: rpath.group_id().clone(), - rpath: rpath.rpath().to_string(), + group_id: group_id.clone(), + rpath: rpath.to_string(), }; - self.encode_common_headers( - &Self::make_default_common(rpath.dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -123,7 +126,7 @@ impl GroupRequestor { log::debug!("group start service success"); - Ok(()) + Ok(GroupStartServiceOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -138,7 +141,11 @@ impl GroupRequestor { } } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + proposal: &GroupProposal, + ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", @@ -149,10 +156,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers( - &Self::make_default_common(proposal.rpath().dec_id().clone()), - &mut http_req, - ); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, @@ -189,7 +193,7 @@ impl GroupRequestor { proposal_id ); - Ok(()) + Ok(GroupPushProposalOutputResponse {}) } code @ _ => { let e = RequestorHelper::error_from_resp(&mut resp).await; @@ -207,4 +211,20 @@ impl GroupRequestor { } #[async_trait::async_trait] -impl GroupOutputProcessor for GroupRequestor {} +impl GroupOutputProcessor for GroupRequestor { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupRequestor::push_proposal(self, req_common, &req).await + } +} diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 95811e339..66d0d83f4 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupRPath}; +use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, }; @@ -25,7 +25,14 @@ impl RPathService { pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { // post http - self.0.requestor.push_proposal(proposal).await + self.0 + .requestor + .push_proposal( + GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal, + ) + .await + .map(|_| {}) } pub(crate) fn new( @@ -44,7 +51,15 @@ impl RPathService { pub(crate) async fn start(&self) -> BuckyResult<()> { // post create command - self.0.requestor.start_group_service(self.rpath()).await + self.0 + .requestor + .start_service( + GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + self.rpath().group_id(), + self.rpath().rpath(), + ) + .await + .map(|_| {}) } pub(crate) async fn on_execute( diff --git a/src/component/cyfs-stack/Cargo.toml b/src/component/cyfs-stack/Cargo.toml index d005147ec..ca254632f 100644 --- a/src/component/cyfs-stack/Cargo.toml +++ b/src/component/cyfs-stack/Cargo.toml @@ -16,6 +16,7 @@ cyfs-bdt-ext = { path = "../../component/cyfs-bdt-ext" } cyfs-base = { path = "../../component/cyfs-base" } cyfs-core = { path = "../../component/cyfs-core" } cyfs-group = { path = "../../component/cyfs-group" } +cyfs-group-lib = { path = "../../component/cyfs-group-lib" } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = "../../component/cyfs-lib" } cyfs-chunk-lib = { path = "../../component/cyfs-chunk-lib" } diff --git a/src/component/cyfs-stack/src/group/mod.rs b/src/component/cyfs-stack/src/group/mod.rs new file mode 100644 index 000000000..da7603e40 --- /dev/null +++ b/src/component/cyfs-stack/src/group/mod.rs @@ -0,0 +1,5 @@ +mod processor; +mod transform; + +pub(crate) use processor::*; +pub(crate) use transform::*; \ No newline at end of file diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs new file mode 100644 index 000000000..b6fe1544b --- /dev/null +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -0,0 +1,25 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +#[async_trait::async_trait] +pub(crate) trait GroupInputProcessor: Sync + Send { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult; + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult; +} + +pub(crate) type GroupInputProcessorRef = Arc; diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs new file mode 100644 index 000000000..50abe1afb --- /dev/null +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -0,0 +1,190 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, + GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +use super::{GroupInputProcessor, GroupInputProcessorRef}; + +// 实现从input到output的转换 +pub(crate) struct GroupInputTransformer { + processor: GroupOutputProcessorRef, +} + +impl GroupInputTransformer { + pub fn new(processor: GroupOutputProcessorRef) -> GroupInputProcessorRef { + let ret = Self { processor }; + Arc::new(ret) + } + + fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { + NONOutputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 来源DEC + dec_id: common.source.get_opt_dec().cloned(), + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source: common.source.zone.device, + } + } + + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let out_req = GroupStartServiceOutputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let out_resp = self + .processor + .start_service(Self::convert_common(req_common), out_req) + .await?; + + let resp = GroupStartServiceInputResponse {}; + + Ok(resp) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let out_resp = self + .processor + .push_proposal(Self::convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalInputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupInputTransformer { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + GroupInputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupInputTransformer::push_proposal(self, req_common, req).await + } +} + +// 实现从output到input的转换 +pub(crate) struct GroupOutputTransformer { + processor: GroupInputProcessorRef, + source: RequestSourceInfo, +} + +impl GroupOutputTransformer { + fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + let mut source = self.source.clone(); + if let Some(dec_id) = common.dec_id { + source.set_dec(dec_id); + } + + NONInputRequestCommon { + // 请求路径,可为空 + req_path: common.req_path, + + // 默认行为 + level: common.level, + + // 用以处理默认行为 + target: common.target, + + flags: common.flags, + + source, + } + } + + pub fn new( + processor: GroupInputProcessorRef, + source: RequestSourceInfo, + ) -> GroupOutputProcessorRef { + let ret = Self { processor, source }; + Arc::new(Box::new(ret)) + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let in_resp = self + .processor + .push_proposal(self.convert_common(req_common), req) + .await?; + + let resp = GroupPushProposalOutputResponse {}; + + Ok(resp) + } + + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + let in_req = GroupStartServiceInputRequest { + group_id: req.group_id, + rpath: req.rpath, + }; + + let in_resp = self + .processor + .start_service(self.convert_common(req_common), in_req) + .await?; + + let resp = GroupStartServiceOutputResponse {}; + + Ok(resp) + } +} + +#[async_trait::async_trait] +impl GroupOutputProcessor for GroupOutputTransformer { + async fn start_service( + &self, + req_common: NONOutputRequestCommon, + req: GroupStartServiceOutputRequest, + ) -> BuckyResult { + GroupOutputTransformer::start_service(self, req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONOutputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + GroupOutputTransformer::push_proposal(self, req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs new file mode 100644 index 000000000..0e789c023 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -0,0 +1,61 @@ +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::*; + +use std::sync::Arc; + +pub struct GroupAclInnerInputProcessor { + next: GroupInputProcessorRef, +} + +impl GroupAclInnerInputProcessor { + pub(crate) fn new(next: GroupInputProcessorRef) -> GroupInputProcessorRef { + Arc::new(Self { next }) + } + + fn check_local_zone_permit( + &self, + service: &str, + source: &RequestSourceInfo, + ) -> BuckyResult<()> { + // TODO + // if !source.is_current_zone() { + // let msg = format!( + // "{} service valid only in current zone! source={:?}, category={}", + // service, + // source.zone.device, + // source.zone.zone_category.as_str() + // ); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::PermissionDenied, msg)); + // } + + Ok(()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupAclInnerInputProcessor { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.next.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.next.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/acl/mod.rs b/src/component/cyfs-stack/src/group_api/acl/mod.rs new file mode 100644 index 000000000..53dad00b3 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/acl/mod.rs @@ -0,0 +1,3 @@ +mod group_acl; + +pub use group_acl::*; diff --git a/src/component/cyfs-stack/src/group_api/mod.rs b/src/component/cyfs-stack/src/group_api/mod.rs new file mode 100644 index 000000000..29e257330 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/mod.rs @@ -0,0 +1,7 @@ +mod acl; +mod router; +mod service; + +pub(crate) use acl::*; +pub(crate) use router::*; +pub(crate) use service::*; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs new file mode 100644 index 000000000..2c1a2841f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyResult, DeviceId, ObjectId}; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::{ + forward::ForwardProcessorManager, + group::{GroupInputProcessor, GroupInputProcessorRef, GroupInputTransformer}, + group_api::GroupAclInnerInputProcessor, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupServiceRouter { + processor: GroupInputProcessorRef, + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, +} + +impl GroupServiceRouter { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + processor: GroupInputProcessorRef, + ) -> GroupInputProcessorRef { + let processor = GroupAclInnerInputProcessor::new(processor); + let ret = Self { + processor, + zone_manager, + forward, + }; + Arc::new(ret) + } + + async fn get_forward( + &self, + dec_id: ObjectId, + target: DeviceId, + ) -> BuckyResult { + let requestor = self.forward.get(&target).await?; + let group_requestor = GroupRequestor::new(dec_id, requestor); + Ok(GroupInputTransformer::new( + group_requestor.clone_processor(), + )) + } + + // 不同于non/ndn的router,如果target为空,那么表示本地device + async fn get_target(&self, target: Option<&ObjectId>) -> BuckyResult> { + let ret = match target { + Some(object_id) => { + let info = self + .zone_manager + .target_zone_manager() + .resolve_target(Some(object_id)) + .await?; + if info.target_device == *self.zone_manager.get_current_device_id() { + None + } else { + Some(info.target_device) + } + } + None => None, + }; + + Ok(ret) + } + + async fn get_processor( + &self, + dec_id: ObjectId, + target: Option<&ObjectId>, + ) -> BuckyResult { + if let Some(device_id) = self.get_target(target).await? { + debug!("group target resolved: {:?} -> {}", target, device_id); + let processor = self.get_forward(dec_id, device_id).await?; + Ok(processor) + } else { + Ok(self.processor.clone()) + } + } + + pub async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + pub async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for GroupServiceRouter { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.start_service(req_common, req).await + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let processor = self + .get_processor(req_common.source.dec, req_common.target.as_ref()) + .await?; + processor.push_proposal(req_common, req).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs new file mode 100644 index 000000000..e14691b5e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc}; +use cyfs_core::{GroupProposal, GroupProposalObject}; +use cyfs_group::GroupManager; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::NONInputRequestCommon; + +use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; + +#[derive(Clone)] +pub(crate) struct LocalGroupService { + group_manager: GroupManager, +} + +impl LocalGroupService { + pub(crate) fn new(group_manager: GroupManager) -> Self { + Self { group_manager } + } + + pub fn clone_processor(&self) -> GroupInputProcessorRef { + Arc::new(self.clone()) + } +} + +#[async_trait::async_trait] +impl GroupInputProcessor for LocalGroupService { + async fn start_service( + &self, + req_common: NONInputRequestCommon, + req: GroupStartServiceInputRequest, + ) -> BuckyResult { + self.group_manager + .find_rpath_service( + &req.group_id, + &req_common.source.dec, + req.rpath.as_str(), + true, + ) + .await + .map(|_| GroupStartServiceInputResponse {}) + .map_err(|err| { + log::error!( + "group start service {}-{}-{} failed {:?}", + req.group_id, + req_common.source.dec, + req.rpath, + err + ); + err + }) + } + + async fn push_proposal( + &self, + req_common: NONInputRequestCommon, + req: GroupProposal, + ) -> BuckyResult { + let proposal_id = req.desc().object_id(); + let rpath = req.rpath().clone(); + if &req_common.source.dec != rpath.dec_id() { + let msg = format!( + "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + req_common.source.dec + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let service = self + .group_manager + .find_rpath_service( + req.rpath().group_id(), + &req_common.source.dec, + rpath.rpath(), + true, + ) + .await + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed when find the service {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + })?; + + service + .push_proposal(req) + .await + .map(|_| GroupPushProposalInputResponse {}) + .map_err(|err| { + log::error!( + "group push proposal {}-{}-{} {} failed {:?}", + rpath.group_id(), + rpath.dec_id(), + rpath.rpath(), + proposal_id, + err + ); + err + }) + } +} diff --git a/src/component/cyfs-stack/src/group_api/router/mod.rs b/src/component/cyfs-stack/src/group_api/router/mod.rs new file mode 100644 index 000000000..877b4eff6 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/router/mod.rs @@ -0,0 +1,5 @@ +mod group_service_router; +mod local_service; + +pub use group_service_router::*; +pub(crate) use local_service::*; diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs new file mode 100644 index 000000000..f01f2eaa5 --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -0,0 +1,125 @@ +use cyfs_base::*; +use cyfs_core::GroupProposal; +use cyfs_group_lib::{ + GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, +}; +use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; + +use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; + +#[derive(Clone)] +pub(crate) struct GroupRequestHandler { + processor: GroupInputProcessorRef, +} + +impl GroupRequestHandler { + pub fn new(processor: GroupInputProcessorRef) -> Self { + Self { processor } + } + + // 解析通用header字段 + fn decode_common_headers( + req: &NONInputHttpRequest, + ) -> BuckyResult { + // req_path + let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( + &req.request, + cyfs_base::CYFS_REQ_PATH, + )?; + + // 尝试提取flags + let flags: Option = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; + + // 尝试提取default_action字段 + let level = + RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; + + // 尝试提取target字段 + let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; + + let ret = NONInputRequestCommon { + req_path, + source: req.source.clone(), + level: level.unwrap_or_default(), + target, + flags: flags.unwrap_or(0), + }; + + Ok(ret) + } + + // group/start-service + pub async fn process_start_service( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_start_service(req).await { + Ok(_resp) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_start_service( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + let common = Self::decode_common_headers(&req)?; + + // 提取body里面的object对象,如果有的话 + let body = req.request.body_json().await.map_err(|e| { + let msg = format!("group start service failed, read body bytes error! {}", e); + error!("{}", msg); + + BuckyError::new(BuckyErrorCode::InvalidParam, msg) + })?; + + let req = GroupStartServiceInputRequest::decode_json(&body)?; + + self.processor.start_service(common, req).await + } + + pub async fn process_push_proposal( + &self, + req: NONInputHttpRequest, + ) -> tide::Response { + match self.on_push_proposal(req).await { + Ok(_) => { + let http_resp: tide::Response = RequestorHelper::new_ok_response(); + + http_resp + } + Err(e) => RequestorHelper::trans_error(e), + } + } + + async fn on_push_proposal( + &self, + mut req: NONInputHttpRequest, + ) -> BuckyResult { + // 检查action + // let action = Self::decode_action(&req, NONAction::PutObject)?; + // if action != NONAction::PutObject { + // let msg = format!("invalid non put_object action! {:?}", action); + // error!("{}", msg); + + // return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg)); + // } + + let common = Self::decode_common_headers(&req)?; + let object = NONRequestorHelper::decode_object_info(&mut req.request).await?; + let (proposal, remain) = GroupProposal::raw_decode(object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + + // let access: Option = + // RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_ACCESS)?; + // let access = access.map(|v| AccessString::new(v)); + + info!("recv push proposal: {}", object.object_id); + + self.processor.push_proposal(common, proposal).await + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs new file mode 100644 index 000000000..163228d1f --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -0,0 +1,77 @@ +use cyfs_lib::RequestProtocol; +use tide::Response; + +use crate::{non::NONInputHttpRequest, ZoneManagerRef}; + +use super::GroupRequestHandler; + +enum GroupRequestType { + StartService, + PushProposal, +} + +pub(crate) struct GroupRequestHandlerEndpoint { + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, +} + +impl GroupRequestHandlerEndpoint { + fn new( + zone_manager: ZoneManagerRef, + protocol: RequestProtocol, + req_type: GroupRequestType, + handler: GroupRequestHandler, + ) -> Self { + Self { + zone_manager, + protocol, + req_type, + handler, + } + } + + async fn process_request(&self, req: tide::Request) -> Response { + let req = match NONInputHttpRequest::new(&self.zone_manager, &self.protocol, req).await { + Ok(v) => v, + Err(resp) => return resp, + }; + match self.req_type { + GroupRequestType::StartService => self.handler.process_start_service(req).await, + GroupRequestType::PushProposal => self.handler.process_push_proposal(req).await, + } + } + + pub fn register_server( + zone_manager: &ZoneManagerRef, + protocol: &RequestProtocol, + handler: &GroupRequestHandler, + server: &mut tide::Server<()>, + ) { + server.at("/group/start-service").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::StartService, + handler.clone(), + )); + + server.at("group/push-proposal").post(Self::new( + zone_manager.clone(), + protocol.to_owned(), + GroupRequestType::PushProposal, + handler.clone(), + )); + } +} + +#[async_trait::async_trait] +impl tide::Endpoint for GroupRequestHandlerEndpoint +where + State: Clone + Send + Sync + 'static, +{ + async fn call(&self, req: tide::Request) -> tide::Result { + let resp = self.process_request(req).await; + Ok(resp) + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/group_service.rs b/src/component/cyfs-stack/src/group_api/service/group_service.rs new file mode 100644 index 000000000..3a25e282e --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/group_service.rs @@ -0,0 +1,35 @@ +use cyfs_group::GroupManager; + +use crate::{ + forward::ForwardProcessorManager, + group::GroupInputProcessorRef, + group_api::{GroupServiceRouter, LocalGroupService}, + ZoneManagerRef, +}; + +#[derive(Clone)] +pub struct GroupService { + router: GroupInputProcessorRef, + local_service: LocalGroupService, +} + +impl GroupService { + pub(crate) fn new( + forward: ForwardProcessorManager, + zone_manager: ZoneManagerRef, + group_manager: GroupManager, + ) -> Self { + let local_service = LocalGroupService::new(group_manager); + let router = + GroupServiceRouter::new(forward, zone_manager, local_service.clone_processor()); + + Self { + router, + local_service, + } + } + + pub(crate) fn clone_processor(&self) -> GroupInputProcessorRef { + self.router.clone() + } +} diff --git a/src/component/cyfs-stack/src/group_api/service/mod.rs b/src/component/cyfs-stack/src/group_api/service/mod.rs new file mode 100644 index 000000000..1140a741d --- /dev/null +++ b/src/component/cyfs-stack/src/group_api/service/mod.rs @@ -0,0 +1,7 @@ +mod group_service; +mod group_listener; +mod group_handler; + +pub(crate) use group_service::*; +pub(crate) use group_listener::*; +pub(crate) use group_handler::*; diff --git a/src/component/cyfs-stack/src/interface/http_listener.rs b/src/component/cyfs-stack/src/interface/http_listener.rs index 21b6e86e3..e9ef12523 100644 --- a/src/component/cyfs-stack/src/interface/http_listener.rs +++ b/src/component/cyfs-stack/src/interface/http_listener.rs @@ -1,6 +1,7 @@ use crate::acl::AclManagerRef; use crate::crypto_api::*; use crate::front::{FrontProtocolHandler, FrontRequestHandlerEndpoint}; +use crate::group_api::{GroupRequestHandler, GroupRequestHandlerEndpoint, GroupService}; use crate::name::NameResolver; use crate::ndn_api::*; use crate::non_api::*; @@ -75,6 +76,7 @@ impl ObjectHttpListener { global_state_meta: &GlobalStateMetaService, name_resolver: &NameResolver, zone_manager: &ZoneManagerRef, + group_service: &GroupService, ) -> Self { let mut server = new_server(); @@ -225,6 +227,15 @@ impl ObjectHttpListener { &mut server, ); + // group manager + let handler = GroupRequestHandler::new(group_service.clone_processor()); + GroupRequestHandlerEndpoint::register_server( + zone_manager, + &protocol, + &handler, + &mut server, + ); + Self { server } } diff --git a/src/component/cyfs-stack/src/interface/listener_manager.rs b/src/component/cyfs-stack/src/interface/listener_manager.rs index c6b5510be..76d3c4e9d 100644 --- a/src/component/cyfs-stack/src/interface/listener_manager.rs +++ b/src/component/cyfs-stack/src/interface/listener_manager.rs @@ -9,6 +9,7 @@ use crate::acl::AclManagerRef; use crate::app::AuthenticatedAppList; use crate::config::StackGlobalConfig; use crate::events::RouterEventsManager; +use crate::group_api::GroupService; use crate::interface::http_ws_listener::ObjectHttpWSService; use crate::name::NameResolver; use crate::rmeta_api::GlobalStateMetaService; @@ -18,7 +19,7 @@ use crate::stack::ObjectServices; use crate::zone::ZoneRoleManager; use cyfs_base::*; use cyfs_bdt::StackGuard; -use cyfs_lib::{RequestProtocol, BrowserSanboxMode}; +use cyfs_lib::{BrowserSanboxMode, RequestProtocol}; use cyfs_debug::Mutex; use std::net::SocketAddr; @@ -131,6 +132,7 @@ impl ObjectListenerManager { root_state: &GlobalStateService, local_cache: &GlobalStateLocalService, global_state_meta: &GlobalStateMetaService, + group_service: &GroupService, ) { assert!(self.listeners.is_empty()); @@ -151,6 +153,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); @@ -172,18 +175,14 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); let http_server = DefaultHttpServer::new(raw_handler.into(), default_handler.clone()); let http_server = match config.get_stack_params().front.browser_mode { BrowserSanboxMode::None => http_server.into(), - mode @ _ => { - BrowserSanboxHttpServer::new( - http_server.into(), - mode, - ).into() - } + mode @ _ => BrowserSanboxHttpServer::new(http_server.into(), mode).into(), }; self.http_tcp_server = Some(http_server); } @@ -202,6 +201,7 @@ impl ObjectListenerManager { global_state_meta, name_resolver, role_manager.zone_manager(), + group_service, ); let raw_handler = RawHttpServer::new(server.into_server()); diff --git a/src/component/cyfs-stack/src/lib.rs b/src/component/cyfs-stack/src/lib.rs index c180fe861..832029d33 100644 --- a/src/component/cyfs-stack/src/lib.rs +++ b/src/component/cyfs-stack/src/lib.rs @@ -29,6 +29,8 @@ mod config; mod front; mod rmeta_api; mod rmeta; +mod group; +mod group_api; pub use stack::*; pub use storage::*; diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 8cf9bcad0..493f6ace8 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -10,6 +10,7 @@ use crate::crypto_api::{CryptoService, ObjectCrypto, ObjectVerifier}; use crate::events::RouterEventsManager; use crate::forward::ForwardProcessorManager; use crate::front::FrontService; +use crate::group_api::GroupService; use crate::interface::{ ObjectListenerManager, ObjectListenerManagerParams, ObjectListenerManagerRef, }; @@ -105,7 +106,7 @@ pub struct CyfsStackImpl { global_state_meta: GlobalStateMetaService, // group - group_manager: GroupManager, + group_service: GroupService, } impl CyfsStackImpl { @@ -437,6 +438,8 @@ impl CyfsStackImpl { bdt_stack.clone(), global_state_manager.clone_processor(), )?; + let group_service = + GroupService::new(forward_manager.clone(), zone_manager.clone(), group_manager); let mut stack = Self { config, @@ -474,7 +477,7 @@ impl CyfsStackImpl { acl_manager, - group_manager, + group_service, }; // init an system-dec router-handler processor for later use @@ -564,6 +567,7 @@ impl CyfsStackImpl { &stack.root_state, &stack.local_cache, &stack.global_state_meta, + &stack.group_service, ); let interface = Arc::new(interface); @@ -1163,8 +1167,8 @@ impl CyfsStack { &self.stack.root_state } - pub fn group_mgr(&self) -> &GroupManager { - &self.stack.group_manager + pub fn group_service(&self) -> &GroupService { + &self.stack.group_service } // use system dec as default dec From cd3cc3808c32305b1f87b055fd36d15a9a63d37c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 8 Mar 2023 17:39:29 +0800 Subject: [PATCH 512/553] Remove several unused import --- src/component/cyfs-group-lib/src/request_codec.rs | 2 +- src/component/cyfs-group-lib/src/requestor.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 58404d6b0..4c7ddfe88 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,4 +1,4 @@ -use cyfs_base::{BuckyResult, JsonCodec, JsonCodecAutoWithSerde, JsonCodecHelper}; +use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 462b1df85..341bff3e3 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -4,7 +4,7 @@ use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, CYFS_API_LEVEL, }; -use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; +use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, }; @@ -116,7 +116,7 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupStartServiceOutputResponse::decode_string(&body).map_err(|e| { // error!( // "decode group start service resp from body string error: body={} {}", // body, e, @@ -179,9 +179,9 @@ impl GroupRequestor { BuckyError::from(msg) })?; - // let resp = TransCreateTaskOutputResponse::decode_string(&body).map_err(|e| { + // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { // error!( - // "decode group start service resp from body string error: body={} {}", + // "decode group push proposal resp from body string error: body={} {}", // body, e, // ); // e From 3bf51f87472eef9067fb338c892a7eaa323928dd Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 19:19:00 +0800 Subject: [PATCH 513/553] Debug --- src/component/cyfs-group-lib/Cargo.toml | 1 - .../cyfs-group-lib/src/group_manager.rs | 138 +++++- src/component/cyfs-group-lib/src/requestor.rs | 11 +- .../cyfs-group/src/dec/group_events.rs | 43 +- .../cyfs-group/src/dec/group_manager.rs | 10 +- .../cyfs-group/src/dec/rpath_service.rs | 7 +- .../src/group_api/service/group_listener.rs | 4 +- .../cyfs-stack/src/stack/group_non_driver.rs | 21 +- .../cyfs-stack/src/zone/zone_manager.rs | 20 +- src/tests/group-example/Cargo.toml | 4 +- src/tests/group-example/src/main.rs | 436 ++++++++---------- 11 files changed, 407 insertions(+), 288 deletions(-) diff --git a/src/component/cyfs-group-lib/Cargo.toml b/src/component/cyfs-group-lib/Cargo.toml index 740b303cd..68931728c 100644 --- a/src/component/cyfs-group-lib/Cargo.toml +++ b/src/component/cyfs-group-lib/Cargo.toml @@ -32,5 +32,4 @@ cyfs-base = { path = '../../component/cyfs-base', version = '0.6' } cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index f442d5c55..61a11698d 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -7,7 +7,7 @@ use cyfs_base::{ }; use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - CyfsStackRequestorType, HttpRequestorRef, NONAPILevel, NONObjectInfo, + CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -68,11 +68,14 @@ impl GroupManager { // TODO: other filters? only local zone let filter = format!( - "obj_type == {} && dec_id == {}", + "obj_type == {} && source.dec_id == {} && source.zone_category == {}", CoreObjectType::GroupCommand as u16, dec_id, + DeviceZoneCategory::CurrentZone.to_string(), ); + // let filter = "*".to_string(); + router_handler_manager .post_object() .add_handler( @@ -80,7 +83,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - None, + Some("group-inner".to_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) @@ -120,7 +123,38 @@ impl GroupManager { rpath: String, delegate: Box, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap().clone(); + + { + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(&dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath.as_str())); + + if let Some(found) = found { + return Ok(found.clone()); + } + } + + { + let mut services = self.0.services.write().await; + let service = services + .entry(group_id.clone()) + .or_insert_with(HashMap::new) + .entry(dec_id.into()) + .or_insert_with(HashMap::new) + .entry(rpath.to_string()) + .or_insert_with(|| { + RPathService::new( + GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), + self.0.requestor.clone(), + delegate, + self.0.stack.clone(), + ) + }); + Ok(service.clone()) + } } pub async fn find_rpath_service( @@ -128,7 +162,20 @@ impl GroupManager { group_id: &ObjectId, rpath: &str, ) -> BuckyResult { - unimplemented!() + let dec_id = self.0.stack.dec_id().unwrap(); + let services = self.0.services.read().await; + let found = services + .get(&group_id) + .and_then(|by_dec| by_dec.get(dec_id)) + .and_then(|by_rpath| by_rpath.get(rpath)); + + found.map_or( + Err(BuckyError::new( + BuckyErrorCode::NotFound, + "please start the service first", + )), + |service| Ok(service.clone()), + ) } pub async fn rpath_client( @@ -204,6 +251,16 @@ impl GroupManager { ) .await .map(|_| ()) + .map_err(|err| { + log::warn!( + "group on_new_rpath {}-{:?}-{} failed, err: {:?}", + cmd.group_id, + self.0.stack.dec_id(), + cmd.rpath, + err + ); + err + }) } async fn on_execute(&self, cmd: GroupCommandExecute) -> BuckyResult { @@ -216,11 +273,27 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let mut result = service .on_execute(&cmd.proposal, &cmd.prev_state_id) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_execute {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; Ok(GroupCommandExecuteResult { result_state_id: result.result_state_id.take(), @@ -239,7 +312,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_verify find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -250,6 +331,14 @@ impl GroupManager { service .on_verify(&cmd.proposal, &cmd.prev_state_id, &result) .await + .map_err(|err| { + log::warn!( + "group on_verify {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + }) } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { @@ -262,7 +351,15 @@ impl GroupManager { &None, false, ) - .await?; + .await + .map_err(|err| { + log::warn!( + "group on_commited find service {:?} failed, err: {:?}", + cmd.proposal.rpath(), + err + ); + err + })?; let result = ExecuteResult { result_state_id: cmd.result_state_id.take(), @@ -361,27 +458,38 @@ impl EventListenerAsyncRoutine BuckyResult { let req_common = ¶m.request.common; - if req_common.level != NONAPILevel::NOC - || req_common.source.zone.zone != self.0.local_zone + let obj = ¶m.request.object; + + log::debug!( + "group-command handle, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", + req_common.level, + req_common.source.zone, + self.0.local_zone, + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) + ); + + if !req_common.source.zone.is_current_zone() || self.0.local_zone.is_none() + // || req_common.source.zone.zone != self.0.local_zone || self.0.stack.dec_id().is_none() { log::warn!( - "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}", + "there should no group-command from other zone, level = {:?}, zone = {:?}, local-zone = {:?}, dec-id = {:?}, obj_type = {:?}", req_common.level, req_common.source.zone, self.0.local_zone, - self.0.stack.dec_id() + self.0.stack.dec_id(), + obj.object.as_ref().map(|o| o.obj_type()) ); return Ok(RouterHandlerPostObjectResult { - action: RouterHandlerAction::Reject, + action: RouterHandlerAction::Pass, request: None, response: None, }); } - let obj = ¶m.request.object; match obj.object.as_ref() { None => { return Ok(RouterHandlerPostObjectResult { diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 341bff3e3..b77f93dad 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -6,7 +6,8 @@ use cyfs_base::{ }; use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_lib::{ - HttpRequestorRef, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, RequestorHelper, + HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, + RequestorHelper, }; use http_types::{Method, Request, Url}; @@ -43,7 +44,7 @@ impl GroupRequestor { fn encode_common_headers( &self, - // action: NONAction, + action: NONAction, com_req: &NONOutputRequestCommon, http_req: &mut Request, ) { @@ -56,7 +57,7 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - // http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); + http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); @@ -98,7 +99,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -156,7 +157,7 @@ impl GroupRequestor { let url = self.service_url.join("push-proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index 9bda7e340..a25accb19 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -1,6 +1,9 @@ +use std::sync::Arc; + use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, + ObjectMapIsolatePathOpEnvRef, ObjectMapSingleOpEnvRef, RawConvertTo, RawDecode, RawFrom, + TypelessCoreObject, }; use cyfs_core::{GroupConsensusBlock, GroupProposal}; use cyfs_group_lib::{ @@ -32,13 +35,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -78,13 +86,18 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) @@ -111,16 +124,26 @@ impl RPathEventNotifier { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd + .to_vec() + .expect(format!("on_commited {} failed for encode", self.non_driver.dec_id()).as_str()); + let any_obj = cyfs_base::AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(object_raw_buf.as_slice()).expect( + format!( + "on_commited {} failed for convert to any", + self.non_driver.dec_id() + ) + .as_str(), + ), + ); + let result = self .non_driver .post_object( NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec().expect( - format!("on_commited {} failed for encode", self.non_driver.dec_id()) - .as_str(), - ), - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 7a9708ccc..579f63831 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ BuckyErrorCode, BuckyResult, GroupId, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - RawConvertTo, RsaCPUObjectSigner, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; @@ -488,6 +488,10 @@ impl GroupManager { }; let cmd = GroupCommand::from(cmd); + let object_raw_buf = cmd.to_vec()?; + let any_obj = cyfs_base::AnyNamedObject::Core(TypelessCoreObject::clone_from_slice( + object_raw_buf.as_slice(), + )?); let result = self .local_info() .non_driver @@ -495,8 +499,8 @@ impl GroupManager { dec_id, NONObjectInfo { object_id: cmd.desc().object_id(), - object_raw: cmd.to_vec()?, - object: None, + object_raw: object_raw_buf, + object: Some(Arc::new(any_obj)), }, None, ) diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index b4b90972f..1f2e836a1 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -66,6 +66,11 @@ impl RPathService { } pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { + log::info!( + "group({:?}) push proposal {}", + self.rpath(), + proposal.desc().object_id() + ); self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 163228d1f..47be52927 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").post(Self::new( + server.at("/group/start-service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").post(Self::new( + server.at("group/push-proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 9333e7981..fa136b3fa 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -42,7 +42,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // from.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: from.map(|remote| remote.clone()), flags: 0, @@ -72,7 +72,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: NONAPILevel::NOC, + level: NONAPILevel::Router, target: None, flags: 0, @@ -90,10 +90,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { obj: NONObjectInfo, to: Option<&ObjectId>, ) -> BuckyResult> { + let obj_type_code = obj.object_id.obj_type_code(); + let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some("group-inner".to_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -105,7 +108,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { verified: None, }, - level: to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), + level: NONAPILevel::Router, // to.map_or(NONAPILevel::NOC, |_| NONAPILevel::Router), target: to.cloned(), flags: 0, @@ -114,5 +117,15 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) .await .map(|resp| resp.object) + .map_err(|err| { + log::warn!( + "group post object(type={:?}/{:?}) to {:?} failed {:?}", + obj_type_code, + obj_type, + to, + err + ); + err + }) } } diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 6819b991d..61f284bc4 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -652,7 +652,25 @@ impl ZoneManager { owner_id, work_mode, list ); - return Ok((work_mode, list.to_owned())); + if obj_type == ObjectTypeCode::People { + return Ok((work_mode, list.to_owned())); + } else if obj_type == ObjectTypeCode::Group { + let group = owner_object.into_group(); + // TODO: 先简单处理,找最近的OOD,后面可能要依据具体操作向不同身份发起请求; + // 比如:读操作向任意member请求即可 + let list = group + .ood_list_with_distance( + self.get_current_device_id().object_id(), + ) + .into_iter() + .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) + .map(|id| DeviceId::try_from(id).unwrap()) + .collect(); + return Ok((work_mode, list)); + } else { + unreachable!() + } + /* let ood_device_id = list[0].clone(); let obj_type = ood_device_id.object_id().obj_type_code(); diff --git a/src/tests/group-example/Cargo.toml b/src/tests/group-example/Cargo.toml index 01094f12a..2cf31aba9 100644 --- a/src/tests/group-example/Cargo.toml +++ b/src/tests/group-example/Cargo.toml @@ -23,9 +23,9 @@ cyfs-core = { path = '../../component/cyfs-core' } cyfs-bdt = { path = '../../component/cyfs-bdt' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } -cyfs-group = { path = '../../component/cyfs-group' } cyfs-stack = { path = '../../component/cyfs-stack' } +cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } cyfs-meta-lib = { path = '../../component/cyfs-meta-lib' } cyfs-bdt-ext = { path = '../../component/cyfs-bdt-ext' } cyfs-util = { path = '../../component/cyfs-util' } \ No newline at end of file diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 88450ac1b..e74f3c5d6 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -1,36 +1,43 @@ -use std::{clone, sync::Arc, time::Duration}; +use std::{clone, collections::HashSet, sync::Arc, time::Duration}; +use async_std::sync::Mutex; use cyfs_base::{ AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, TypelessCoreObject, }; use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; -use cyfs_group::IsCreateRPath; +use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NamedObjectCachePutObjectRequest, - NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, + DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, + NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, + RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; use GroupDecService::DecService; -use crate::Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}; +use crate::{ + Common::{init_admins, init_group, init_members, EXAMPLE_APP_NAME, EXAMPLE_VALUE_PATH}, + GroupDecService::MyRPathDelegate, +}; mod Common { - use std::{fmt::format, io::ErrorKind, sync::Arc}; + use std::{ + fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, + }; - use async_std::{fs, stream::StreamExt}; + use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, StandardObject, + RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::BdtStackParams; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId, DecAppObj}; - use cyfs_lib::{BrowserSanboxMode, NONObjectInfo}; + use cyfs_core::{DecApp, DecAppId}; + use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ CyfsStack, CyfsStackConfigParams, CyfsStackFrontParams, CyfsStackInterfaceParams, @@ -348,6 +355,8 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, + rpc_port: u16, + ws_port: u16, ) -> Box<(BdtStackParams, CyfsStackParams, CyfsStackKnownObjects)> { log::info!("init_stack_params"); @@ -369,13 +378,19 @@ mod Common { config: CyfsStackConfigParams { isolate: Some(device.desc().object_id().to_string()), sync_service: false, - shared_stack: false, + shared_stack: true, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { bdt_listeners: vec![NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT], - tcp_listeners: vec![], - ws_listener: None, + tcp_listeners: vec![SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + rpc_port, + ))], + ws_listener: Some(SocketAddr::V4(SocketAddrV4::new( + std::net::Ipv4Addr::new(127, 0, 0, 1), + ws_port, + ))), }, meta: CyfsStackMetaParams { target: MetaMinerTarget::Dev, @@ -454,9 +469,20 @@ mod Common { members: Vec<(People, Device)>, group: &Group, dec_app: &DecApp, - ) -> CyfsStack { - let params = - init_stack_params(people, private_key, device, admins, members, group, dec_app); + rpc_port: u16, + ws_port: u16, + ) -> (CyfsStack, SharedCyfsStack) { + let params = init_stack_params( + people, + private_key, + device, + admins, + members, + group, + dec_app, + rpc_port, + ws_port, + ); log::info!("cyfs-stack.open"); @@ -468,14 +494,23 @@ mod Common { }) .unwrap(); - stack + async_std::task::sleep(Duration::from_millis(1000)).await; + + let shared_stack = + SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) + .await + .unwrap(); + + shared_stack.wait_online(None).await.unwrap(); + + (stack, shared_stack) } } mod Client { // use cyfs_base::ObjectId; // use cyfs_core::GroupProposal; - // use cyfs_group::RPathClient; + // use cyfs_group_lib::RPathClient; // pub struct DecClient {} @@ -505,12 +540,14 @@ mod GroupDecService { DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; - use cyfs_group::RPathService; + use cyfs_group_lib::{ + DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, + RPathService, + }; use cyfs_lib::{ - DelegateFactory, ExecuteResult, GroupObjectMapProcessor, NONPostObjectInputRequest, - NONPostObjectInputResponse, RPathDelegate, RequestSourceInfo, RouterHandlerChain, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, + RouterHandlerChain, SharedCyfsStack, }; - use cyfs_stack::CyfsStack; use cyfs_util::EventListenerAsyncRoutine; use crate::Common::{EXAMPLE_VALUE_PATH, STATE_PATH_SEPARATOR}; @@ -518,16 +555,18 @@ mod GroupDecService { pub struct DecService {} impl DecService { - pub async fn run(cyfs_stack: &CyfsStack, local_name: String, dec_app_id: DecAppId) { - let group_mgr = cyfs_stack.group_mgr(); - - group_mgr - .register( - dec_app_id.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), - ) - .await - .unwrap(); + pub async fn run( + cyfs_stack: &SharedCyfsStack, + local_name: String, + dec_app_id: DecAppId, + ) -> GroupManager { + let group_mgr = GroupManager::open( + cyfs_stack.clone(), + Box::new(GroupRPathDelegateFactory { local_name }), + &cyfs_lib::CyfsStackRequestorType::Http, + ) + .await + .unwrap(); // let source = RequestSourceInfo { // protocol: todo!(), @@ -541,6 +580,8 @@ mod GroupDecService { // .handlers(&RouterHandlerChain::PostRouter) // .post_object() // .add_handler(RouterHandler::new()); + + group_mgr } } @@ -570,7 +611,7 @@ mod GroupDecService { impl GroupRPathDelegateFactory { pub fn is_accept( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, ) -> bool { @@ -583,27 +624,18 @@ mod GroupDecService { impl DelegateFactory for GroupRPathDelegateFactory { async fn create_rpath_delegate( &self, - group: &Group, + group_id: &ObjectId, rpath: &str, with_block: Option<&GroupConsensusBlock>, + is_new: bool, ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { + if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } } pub struct MyRPathDelegate { @@ -621,73 +653,19 @@ mod GroupDecService { } impl MyRPathDelegate { - // pub async fn get_value_from_state_tree_with_single_op_envs( - // pre_state_id: Option, - // object_map_processor: &dyn GroupObjectMapProcessor, - // ) -> BuckyResult<( - // Option, - // Vec<(ObjectMapSingleOpEnvRef, &str, Option)>, - // )> { - // let mut single_op_envs = vec![]; - // let mut parent_map_id = pre_state_id; - // for folder in EXAMPLE_VALUE_PATH.split(STATE_PATH_SEPARATOR.as_str()) { - // let single_op_env = object_map_processor.create_single_op_env().await.expect( - // format!( - // "create_single_op_env load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // parent_map_id = match parent_map_id { - // Some(parent_map_id) => { - // single_op_env.load(&parent_map_id).await.expect( - // format!( - // "load folder {} parent with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // single_op_env.get_by_key(folder).await.expect( - // format!( - // "load folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ) - // } - // None => { - // single_op_env - // .create_new(ObjectMapSimpleContentType::Map) - // .await - // .expect( - // format!( - // "create folder {} with obj_id {:?} failed", - // folder, parent_map_id - // ) - // .as_str(), - // ); - // None - // } - // }; - // single_op_envs.push((single_op_env, folder, parent_map_id)); - // } - - // Ok((parent_map_id, single_op_envs)) - // } - pub async fn execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); - let pre_value = match pre_state_id { - Some(pre_state_id) => { - state_op_env.load(&pre_state_id).await?; + let prev_value = match prev_state_id { + Some(prev_state_id) => { + state_op_env.load(prev_state_id.to_owned()).await?; state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -708,13 +686,13 @@ mod GroupDecService { let result_value = { /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 + * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ - let pre_value = pre_value.map_or(0, |pre_value| { - let buf = pre_value.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + let prev_value = prev_value.map_or(0, |prev_value| { + let buf = prev_value.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let delta_buf = proposal.params().as_ref().unwrap().as_slice(); @@ -722,7 +700,7 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let value = pre_value + delta; + let value = prev_value + delta; ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() @@ -731,13 +709,13 @@ mod GroupDecService { let result_state_id = { state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, &pre_value, true) + .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) .await .expect( format!( "set_with_path {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), @@ -746,34 +724,11 @@ mod GroupDecService { format!( "commit {:?} from {:?} to {} failed", EXAMPLE_VALUE_PATH.as_str(), - pre_value, + prev_value, result_value ) .as_str(), ) - // let mut sub_folder_value = result_value; - // for (parent_single_op_env, folder, sub_folder_prev_value) in - // single_op_envs.into_iter().rev() - // { - // parent_single_op_env - // .set_with_key(folder, &sub_folder_value, &sub_folder_prev_value, true) - // .await - // .expect( - // format!( - // "update folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // sub_folder_value = parent_single_op_env.commit().await.expect( - // format!( - // "commit folder {} value from {:?} to {:?} failed", - // folder, sub_folder_prev_value, sub_folder_value - // ) - // .as_str(), - // ); - // } - // sub_folder_value }; let receipt = { @@ -791,11 +746,11 @@ mod GroupDecService { }; /** - * (result_state_id, return_object) = pre_value + proposal + context + * (result_state_id, return_object) = prev_value + proposal + context */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id), + result_state_id: Some(result_state_id.root), receipt, }) } @@ -803,21 +758,21 @@ mod GroupDecService { pub async fn verify( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, execute_result: &ExecuteResult, - ) -> BuckyResult { + ) -> BuckyResult<()> { /** * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context + * == prev_state_id + proposal + execute_result.context */ let result = self - .execute(proposal, pre_state_id, object_map_processor) + .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", - pre_state_id, + prev_state_id, execute_result.result_state_id, execute_result.context.is_none(), execute_result.receipt.is_none(), @@ -830,7 +785,11 @@ mod GroupDecService { && execute_result.context.is_none() && execute_result.receipt.is_none(); - Ok(is_ok) + if is_ok { + Ok(()) + } else { + Err(BuckyError::new(BuckyErrorCode::Reject, "result unmatch")) + } } } @@ -839,31 +798,36 @@ mod GroupDecService { async fn on_execute( &self, proposal: &GroupProposal, - pre_state_id: Option, + prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, pre_state_id, object_map_processor) + self.execute(proposal, prev_state_id, object_map_processor) .await } async fn on_verify( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, object_map_processor, execute_result) - .await + object_map_processor: &dyn GroupObjectMapProcessor, + ) -> BuckyResult<()> { + self.verify( + proposal, + prev_state_id, + object_map_processor, + execute_result, + ) + .await } async fn on_commited( &self, proposal: &GroupProposal, - pre_state_id: Option, - object_map_processor: &dyn GroupObjectMapProcessor, + prev_state_id: &Option, execute_result: &ExecuteResult, block: &GroupConsensusBlock, + object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 @@ -872,16 +836,16 @@ mod GroupDecService { delta.copy_from_slice(delta_buf); let delta = u64::from_be_bytes(delta); - let pre_value = match pre_state_id { - Some(pre_state_id) => { + let prev_value = match prev_state_id { + Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&pre_state_id) + .load(*prev_state_id) .await - .expect(format!("load {} failed", pre_state_id).as_str()); + .expect(format!("load {} failed", prev_state_id).as_str()); state_op_env .get_by_path(EXAMPLE_VALUE_PATH.as_str()) .await @@ -892,21 +856,21 @@ mod GroupDecService { } None => None, } - .map_or(0, |pre_state_id| { - let buf = pre_state_id.data(); - let mut pre_value = [0u8; 8]; - pre_value.copy_from_slice(&buf[..8]); - u64::from_be_bytes(pre_value) + .map_or(0, |prev_state_id| { + let buf = prev_state_id.data(); + let mut prev_value = [0u8; 8]; + prev_value.copy_from_slice(&buf[..8]); + u64::from_be_bytes(prev_value) }); let result_value = match execute_result.result_state_id { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env() + .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(&result_state_id) + .load(result_state_id) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -932,7 +896,7 @@ mod GroupDecService { "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", block.height(), block.round(), delta, - pre_value, + prev_value, result_value, proposal_id, block.block_id(), @@ -942,10 +906,6 @@ mod GroupDecService { let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); assert!(is_new_finished); } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - unimplemented!() - } } } @@ -982,6 +942,7 @@ async fn main_run() { cyfs_debug::PanicBuilder::new(EXAMPLE_APP_NAME.as_str(), EXAMPLE_APP_NAME.as_str()) .exit_on_panic(true) + .dingtalk_bug_report("any value to disable") .build() .start(); @@ -1004,9 +965,12 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec = vec![]; + let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; + let mut group_mgrs: Vec = vec![]; + let mut rpc_port = 32217_u16; + let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { - let cyfs_stack = create_stack( + let (cyfs_stack, shared_stack) = create_stack( admin, private_key, device, @@ -1020,33 +984,34 @@ async fn main_run() { .collect(), &group, &dec_app, + rpc_port, + ws_port, ) .await; - admin_stacks.push(cyfs_stack); + admin_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; } async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { - let stack = admin_stacks.get(i).unwrap(); + let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); - DecService::run( - &stack, - admin.name().unwrap().to_string(), - dec_app_id.clone(), - ) - .await; - - let service = stack - .group_mgr() - .find_rpath_service( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, + let local_name = admin.name().unwrap(); + let group_mgr = + DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; + + let service = group_mgr + .start_rpath_service( + group.desc().object_id(), + EXAMPLE_RPATH.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), ) .await .unwrap(); + + group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1057,7 +1022,8 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); let owner = &admins.get(i % admins.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, @@ -1066,42 +1032,31 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); - let noc = stack.noc_manager().clone(); + let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); let proposal_any = Arc::new(AnyNamedObject::Core( TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), )); - let req = NamedObjectCachePutObjectRequest { - source: RequestSourceInfo { - protocol: RequestProtocol::DatagramBdt, - zone: DeviceZoneInfo { - device: None, - zone: None, - zone_category: DeviceZoneCategory::CurrentDevice, - }, - dec: dec_app_id.object_id().clone(), - verified: None, + let req = NONPutObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: None, + level: cyfs_lib::NONAPILevel::NOC, + target: None, + flags: 0, }, object: NONObjectInfo::new(proposal.desc().object_id(), buf, Some(proposal_any)), - storage_category: NamedObjectStorageCategory::Storage, - context: None, - last_access_rpath: None, - access_string: Some(AccessString::full().value()), + access: Some(AccessString::full()), }; - noc.put_object(&req).await; + noc.put_object(req).await; proposals.push(proposal); } @@ -1112,20 +1067,15 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); + let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let service = stack - .group_mgr() - .find_rpath_service( - &group_id, - dec_app_id.object_id(), - &EXAMPLE_RPATH, - IsCreateRPath::Yes, - ) + let service = group_mgr + .find_rpath_service(&group_id, &EXAMPLE_RPATH) .await .unwrap(); async_std::task::spawn(async move { - service.push_proposal(proposal).await.unwrap(); + service.push_proposal(&proposal).await.unwrap(); }); if i % 10 == 0 { @@ -1136,27 +1086,25 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - let client = admin_stacks - .get(0) - .unwrap() - .group_mgr() - .rpath_client( - &group.desc().object_id(), - dec_app_id.object_id(), - &EXAMPLE_RPATH, - ) - .await - .unwrap(); - - let value_obj = client - .get_by_path(EXAMPLE_VALUE_PATH.as_str()) - .await - .unwrap(); - let buf = value_obj.as_ref().unwrap().object_id.data(); - let mut value = [0u8; 8]; - value.copy_from_slice(&buf[..8]); - - log::info!("value from client is: {}", u64::from_be_bytes(value)); + // let client = group_mgrs + // .get(0) + // .unwrap() + // .rpath_client( + // &group.desc().object_id(), + // dec_app_id.object_id(), + // &EXAMPLE_RPATH, + // ) + // .await; + + // let value_obj = client + // .get_by_path(EXAMPLE_VALUE_PATH.as_str()) + // .await + // .unwrap(); + // let buf = value_obj.as_ref().unwrap().object_id.data(); + // let mut value = [0u8; 8]; + // value.copy_from_slice(&buf[..8]); + + // log::info!("value from client is: {}", u64::from_be_bytes(value)); } fn main() { From 99ada9da94fe8a96129d5d6526110348a5e1c7ac Mon Sep 17 00:00:00 2001 From: liyaxing Date: Wed, 22 Feb 2023 23:01:23 +0800 Subject: [PATCH 514/553] Add service_version and preview relate supports into ood-daemon for better control of services update --- src/service/ood-daemon/src/config/system_config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index ceb3344e9..670ea5832 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -62,6 +62,13 @@ impl SystemConfig { let node = Self::load_as_toml(&config_file)?; + self.parse_config(node).await?; + + info!("system-config: {:?}", self); + + Ok(()) + } + self.parse_config(node).await } @@ -206,4 +213,3 @@ pub async fn reload_system_config() -> BuckyResult { pub fn get_system_config() -> Arc { SYSTEM_CONFIG.lock().unwrap().clone().unwrap() -} \ No newline at end of file From 559efdf8b6891a0fb49621ea17a2850dc4c43e68 Mon Sep 17 00:00:00 2001 From: liyaxing Date: Thu, 23 Feb 2023 18:31:46 +0800 Subject: [PATCH 515/553] Add repeated loading supports to system-config.toml in ood-daemon --- src/service/ood-daemon/src/config/system_config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service/ood-daemon/src/config/system_config.rs b/src/service/ood-daemon/src/config/system_config.rs index 670ea5832..e27890656 100644 --- a/src/service/ood-daemon/src/config/system_config.rs +++ b/src/service/ood-daemon/src/config/system_config.rs @@ -3,6 +3,7 @@ use super::version::{ServiceListVersion, ServiceVersion}; use crate::repo::REPO_MANAGER; use cyfs_base::*; use cyfs_util::TomlHelper; +use super::monitor::SystemConfigMonitor; use std::path::Path; use std::str::FromStr; @@ -64,8 +65,6 @@ impl SystemConfig { self.parse_config(node).await?; - info!("system-config: {:?}", self); - Ok(()) } From 7886b597e994df9ec4b197ac4855686cbada253e Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Fri, 24 Feb 2023 19:05:14 +0800 Subject: [PATCH 516/553] Review cyfs-perf-client, can write stat info to local file. use UniCyfsStack to init cyfs-perf-client, To make it can use in cyfs-stack --- src/Cargo.lock | 3138 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 2742 insertions(+), 396 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 045ce8e2b..8fdd0986b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -141,9 +141,96 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + +[[package]] +name = "app-manager" +version = "0.5.0" +dependencies = [ + "app-manager-lib", + "async-std", + "async-trait", + "bollard", + "chrono", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "flate2", + "fs_extra", + "futures-util", + "log 0.4.17", + "once_cell", + "ood-daemon", + "regex", + "serde", + "serde_json", + "surf", + "tar", + "toml 0.5.11", + "version-compare", + "wait-timeout", + "walkdir", + "which", + "zip-extract", +] + +[[package]] +name = "app-manager-lib" +version = "0.5.0" +dependencies = [ + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", + "serde", + "serde_json", + "toml 0.5.11", +] + +[[package]] +name = "app-tool" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + +[[package]] +name = "app-tool-ex" +version = "0.5.0" +dependencies = [ + "async-std", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] [[package]] name = "arrayref" @@ -196,23 +283,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", @@ -221,6 +308,7 @@ dependencies = [ "blocking", "futures-lite", "once_cell", + "tokio", ] [[package]] @@ -245,27 +333,28 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ + "async-lock", "autocfg 1.1.0", "concurrent-queue", "futures-lite", "libc", "log 0.4.17", - "once_cell", "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -300,9 +389,9 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ "proc-macro2", "quote", @@ -383,6 +472,20 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "async-std-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "pin-utils", + "trust-dns-resolver", +] + [[package]] name = "async-task" version = "4.3.0" @@ -404,9 +507,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.60" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -437,9 +540,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -522,6 +625,31 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +[[package]] +name = "bdt-debuger" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "log 0.4.17", +] + +[[package]] +name = "bdt-debuger-deamon" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", + "md5", +] + [[package]] name = "bincode" version = "1.3.3" @@ -538,6 +666,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f" dependencies = [ "bitcoin_hashes", + "rand 0.6.5", "rand_core 0.4.2", "serde", "unicode-normalization", @@ -620,6 +749,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding 0.2.1", "generic-array 0.14.6", ] @@ -672,14 +802,93 @@ dependencies = [ ] [[package]] -name = "bstr" -version = "0.2.17" +name = "bollard" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92fed694fd5a7468c971538351c61b9c115f1ae6ed411cd2800f0f299403a4b" +dependencies = [ + "base64 0.13.1", + "bollard-stubs", + "bytes 1.4.0", + "chrono", + "dirs-next", + "futures-core", + "futures-util", + "hex", + "http", + "hyper 0.14.24", + "hyperlocal", + "log 0.4.17", + "pin-project", + "serde", + "serde_derive", + "serde_json", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util 0.6.10", + "url 2.3.0", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2f2e73fffe9455141e170fb9c1feb0ac521ec7e7dcd47a7cab72a658490fb8" +dependencies = [ + "chrono", + "serde", + "serde_with", +] + +[[package]] +name = "browser-meta-spv" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "hex", + "log 0.4.17", + "once_cell", + "serde", + "serde_json", + "sqlx", + "tide", + "toml 0.5.11", +] + +[[package]] +name = "bson" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "8746d07211bb12a7c34d995539b4a2acd4e0b0e757de98ce2ab99bcf17443fad" dependencies = [ + "ahash", + "base64 0.13.1", + "chrono", + "hex", + "indexmap", "lazy_static", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "time 0.3.19", + "uuid 1.3.0", +] + +[[package]] +name = "bstr" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +dependencies = [ "memchr", - "regex-automata", "serde", ] @@ -691,15 +900,15 @@ checksum = "2e2c71c44e5bbc64de4ecfac946e05f9bba5cc296ea7bab4d3eda242a3ffa73c" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -707,6 +916,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" + [[package]] name = "byteorder" version = "1.4.3" @@ -725,15 +940,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -770,9 +985,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -795,6 +1010,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "checked_int_cast" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" + [[package]] name = "chrono" version = "0.4.23" @@ -811,6 +1032,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "chunk-manager" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "chrono", + "cyfs-base", + "cyfs-base-meta", + "cyfs-chunk", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "lru_time_cache", + "rand 0.8.5", + "rusqlite", + "serde", + "serde_json", + "tide", + "timer", + "url 2.3.0", +] + [[package]] name = "cipher" version = "0.2.5" @@ -838,7 +1086,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -853,6 +1101,15 @@ dependencies = [ "term", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -863,6 +1120,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colored" version = "2.0.0" @@ -880,15 +1143,21 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "memchr", ] +[[package]] +name = "commandlines" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bae805ce851b49c4bcb88496a42ce817e0865ef7f49800f3656258e774450bf" + [[package]] name = "concurrent-queue" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ "crossbeam-utils", ] @@ -1153,15 +1422,24 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.6", + "subtle 2.4.1", +] + [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -1196,9 +1474,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -1208,9 +1486,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -1223,15 +1501,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -1240,7 +1518,7 @@ dependencies = [ [[package]] name = "cyfs-base" -version = "0.6.8" +version = "0.6.10" dependencies = [ "aes 0.7.5", "async-recursion", @@ -1275,9 +1553,10 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "simple_logger", + "simple_logger 2.3.0", + "sqlx", "url 2.3.0", - "zip", + "zip 0.6.4", ] [[package]] @@ -1310,7 +1589,7 @@ dependencies = [ [[package]] name = "cyfs-bdt" -version = "0.6.8" +version = "0.7.1" dependencies = [ "async-std", "async-trait", @@ -1325,6 +1604,7 @@ dependencies = [ "generic-array 0.12.4", "hex", "libc", + "local-ip-address", "log 0.4.17", "lru_time_cache", "md5", @@ -1336,12 +1616,59 @@ dependencies = [ "serde", "serde_json", "sha2 0.8.2", - "socket2", + "socket2 0.4.7", "winapi", ] [[package]] -name = "cyfs-chunk" +name = "cyfs-bdt-ext" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-cache", + "cyfs-chunk-lib", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-ndc", + "cyfs-tracker-cache", + "cyfs-util", + "futures", + "log 0.4.17", + "lru_time_cache", + "once_cell", + "serde", +] + +[[package]] +name = "cyfs-bench-mark" +version = "0.1.0" +dependencies = [ + "cyfs-debug", +] + +[[package]] +name = "cyfs-check" +version = "0.5.0" +dependencies = [ + "ansi_term", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "dirs 4.0.0", + "log 0.4.17", + "sysinfo 0.26.9", +] + +[[package]] +name = "cyfs-chunk" version = "0.5.0" dependencies = [ "async-std", @@ -1377,12 +1704,30 @@ dependencies = [ "scan_dir", "sha2 0.8.2", "shared_memory", - "sysinfo 0.26.5", + "sysinfo 0.26.9", +] + +[[package]] +name = "cyfs-chunk-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk", + "cyfs-util", + "http-types", + "log 0.4.17", + "serde", + "serde_json", + "time 0.1.45", + "url 2.3.0", ] [[package]] name = "cyfs-chunk-lib" -version = "0.6.3" +version = "0.6.4" dependencies = [ "async-std", "async-trait", @@ -1405,16 +1750,60 @@ dependencies = [ "hmac 0.12.1", "log 0.4.17", "memzero", - "pbkdf2", + "pbkdf2 0.11.0", "rand 0.7.3", "rand_chacha 0.2.2", "rand_core 0.5.1", "sha2 0.10.6", ] +[[package]] +name = "cyfs-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-recursion", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-bdt", + "cyfs-chunk", + "cyfs-chunk-client", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "hex", + "http-types", + "log 0.4.17", + "once_cell", + "rand 0.7.3", + "serde_json", + "url 2.3.0", + "walkdir", +] + +[[package]] +name = "cyfs-container" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "log 0.4.17", +] + [[package]] name = "cyfs-core" -version = "0.6.3" +version = "0.6.6" dependencies = [ "async-std", "async-trait", @@ -1433,6 +1822,7 @@ dependencies = [ "protoc-bin-vendored", "protoc-rust", "rand 0.8.5", + "semver 1.0.16", "serde", "serde_json", "sha2 0.8.2", @@ -1440,7 +1830,7 @@ dependencies = [ [[package]] name = "cyfs-debug" -version = "0.6.2" +version = "0.6.4" dependencies = [ "async-h1", "async-std", @@ -1454,7 +1844,7 @@ dependencies = [ "futures", "hex", "http-types", - "hyper", + "hyper 0.10.16", "lazy_static", "libc", "log 0.4.17", @@ -1468,7 +1858,7 @@ dependencies = [ "surf", "tide", "timer", - "toml", + "toml 0.5.11", "url 2.3.0", "winapi", ] @@ -1498,12 +1888,43 @@ dependencies = [ "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", + "cyfs-group-lib", + "cyfs-lib", + "futures", + "itertools", + "lazy_static", + "log 0.4.17", + "prost 0.11.6", + "prost-build 0.9.0", + "protobuf", + "protoc-bin-vendored", + "protoc-rust", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", +] + +[[package]] +name = "cyfs-group-lib" +version = "0.1.1" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-core", + "cyfs-debug", "cyfs-lib", + "cyfs-util", "futures", + "http-types", + "itertools", "lazy_static", "log 0.4.17", - "prost 0.11.5", - "prost-build 0.11.5", + "prost 0.11.6", + "prost-build 0.9.0", "protobuf", "protoc-bin-vendored", "protoc-rust", @@ -1515,13 +1936,13 @@ dependencies = [ [[package]] name = "cyfs-lib" -version = "0.7.0" +version = "0.8.1" dependencies = [ "async-h1", "async-std", "async-trait", "async-tungstenite", - "bytes 1.3.0", + "bytes 1.4.0", "chrono", "cyfs-base", "cyfs-bdt", @@ -1544,12 +1965,79 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "surf", "tide", ] +[[package]] +name = "cyfs-meta" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "base58", + "base64 0.13.1", + "byteorder", + "chrono", + "cyfs-base", + "cyfs-base-meta", + "cyfs-core", + "cyfs-util", + "evm", + "futures", + "generic-array 0.12.4", + "hex", + "http-types", + "lazy_static", + "libsqlite3-sys", + "log 0.4.17", + "primitive-types", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.8.2", + "sqlx", + "tide", + "timer", +] + +[[package]] +name = "cyfs-meta-client" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-recursion", + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "dirs 4.0.0", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "rand 0.7.3", + "serde_json", + "simple_logger 2.3.0", +] + +[[package]] +name = "cyfs-meta-genesis" +version = "0.5.0" +dependencies = [ + "commandlines", + "cyfs-meta", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + [[package]] name = "cyfs-meta-lib" -version = "0.6.2" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -1557,12 +2045,53 @@ dependencies = [ "hex", "http-types", "log 0.4.17", + "lru_time_cache", "primitive-types", "rand 0.7.3", "serde_json", "surf", ] +[[package]] +name = "cyfs-meta-miner" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-debug", + "cyfs-meta", + "cyfs-meta-lib", + "hex", + "lazy_static", + "log 0.4.17", + "serde", + "serde_json", + "tide", +] + +[[package]] +name = "cyfs-meta-spv" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "base58", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-debug", + "cyfs-meta-lib", + "ethabi", + "hex", + "libsqlite3-sys", + "log 0.4.17", + "serde", + "serde_json", + "sqlx", + "tide", +] + [[package]] name = "cyfs-mobile-stack" version = "0.5.0" @@ -1581,6 +2110,32 @@ dependencies = [ "once_cell", ] +[[package]] +name = "cyfs-monitor" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "futures", + "log 0.4.17", + "once_cell", + "rand 0.7.3", + "serde", + "serde_json", + "surf", + "toml 0.5.11", + "url 2.3.0", +] + [[package]] name = "cyfs-ndc" version = "0.5.0" @@ -1593,7 +2148,6 @@ dependencies = [ "cyfs-util", "log 0.4.17", "rusqlite", - "thread_local", ] [[package]] @@ -1602,6 +2156,7 @@ version = "0.5.0" dependencies = [ "async-std", "async-trait", + "base-x", "cyfs-base", "cyfs-core", "cyfs-debug", @@ -1613,12 +2168,11 @@ dependencies = [ "lru_time_cache", "once_cell", "rusqlite", - "thread_local", ] [[package]] name = "cyfs-perf-base" -version = "0.6.0" +version = "0.6.3" dependencies = [ "async-std", "cyfs-base", @@ -1626,6 +2180,7 @@ dependencies = [ "cyfs-lib", "cyfs-util", "int-enum", + "lazy_static", "log 0.4.17", "protobuf", "protoc-bin-vendored", @@ -1636,11 +2191,12 @@ dependencies = [ [[package]] name = "cyfs-perf-client" -version = "0.6.1" +version = "0.6.2" dependencies = [ "android_logger", "async-std", "async-trait", + "chrono", "cyfs-base", "cyfs-core", "cyfs-debug", @@ -1665,7 +2221,41 @@ dependencies = [ "pyo3", "rand 0.7.3", "serde", - "threadpool", + "threadpool", +] + +[[package]] +name = "cyfs-runtime" +version = "0.5.0" +dependencies = [ + "android_logger", + "async-h1", + "async-std", + "async-trait", + "bytes 1.4.0", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "dirs 4.0.0", + "formdata", + "futures", + "http-types", + "hyper 0.10.16", + "jni", + "log 0.4.17", + "mime-sniffer", + "once_cell", + "ood-control", + "rand 0.7.3", + "serde", + "serde_json", + "tide", + "toml 0.5.11", + "url 2.3.0", ] [[package]] @@ -1675,7 +2265,7 @@ dependencies = [ "block-buffer 0.7.3", "digest 0.8.1", "fake-simd", - "hex-literal", + "hex-literal 0.1.4", "libc", "opaque-debug 0.2.3", "sha2-asm", @@ -1698,10 +2288,12 @@ dependencies = [ "cyfs-core", "cyfs-debug", "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-ndc", "cyfs-noc", + "cyfs-perf-client", "cyfs-task-manager", "cyfs-tracker-cache", "cyfs-util", @@ -1715,8 +2307,8 @@ dependencies = [ "num_cpus", "once_cell", "percent-encoding 2.2.0", - "prost 0.11.5", - "prost-build 0.11.5", + "prost 0.11.6", + "prost-build 0.11.6", "protoc-bin-vendored", "rand 0.8.5", "semver 1.0.16", @@ -1725,8 +2317,31 @@ dependencies = [ "sha2 0.8.2", "sqlx", "tide", - "toml", - "zip", + "toml 0.5.11", + "zip 0.6.4", +] + +[[package]] +name = "cyfs-stack-bench" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "hex", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "serde", + "toml 0.5.11", ] [[package]] @@ -1748,13 +2363,42 @@ dependencies = [ "log 0.4.17", "regex", "serde", - "toml", - "toml_edit", + "toml 0.5.11", + "toml_edit 0.15.0", +] + +[[package]] +name = "cyfs-stack-test" +version = "0.5.0" +dependencies = [ + "async-recursion", + "async-std", + "async-trait", + "chrono", + "cyfs-base", + "cyfs-bdt", + "cyfs-chunk-lib", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-noc", + "cyfs-perf-client", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "log 0.4.17", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "zone-simulator", ] [[package]] name = "cyfs-task-manager" -version = "0.6.1" +version = "0.6.3" dependencies = [ "async-std", "async-trait", @@ -1783,7 +2427,7 @@ dependencies = [ [[package]] name = "cyfs-util" -version = "0.6.4" +version = "0.6.6" dependencies = [ "async-h1", "async-std", @@ -1811,13 +2455,49 @@ dependencies = [ "rusqlite", "serde", "serde_json", - "simple_logger", - "sysinfo", - "toml", + "simple_logger 2.3.0", + "sysinfo 0.27.7", + "thread_local", + "toml 0.5.11", "url 2.3.0", "walkdir", "winapi", - "zip", + "zip 0.6.4", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", ] [[package]] @@ -1830,9 +2510,15 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.7", ] +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + [[package]] name = "deadpool" version = "0.7.0" @@ -1858,6 +2544,44 @@ dependencies = [ "pem-rfc7468", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "desc-tool" +version = "0.5.0" +dependencies = [ + "async-std", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "hex", + "log 0.4.17", + "serde_json", + "simple_logger 2.3.0", +] + [[package]] name = "digest" version = "0.8.1" @@ -1908,6 +2632,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -1919,6 +2653,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users 0.4.3", + "winapi", +] + [[package]] name = "discard" version = "1.0.4" @@ -1933,9 +2678,25 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "email-encoding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34dd14c63662e0206599796cd5e1ad0268ab2b9d19b868d6050d688eba2bbf98" +dependencies = [ + "base64 0.13.1", + "memchr", +] + +[[package]] +name = "email_address" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" [[package]] name = "encoding" @@ -2001,6 +2762,18 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +[[package]] +name = "enum-as-inner" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -2020,12 +2793,133 @@ dependencies = [ "serde", ] +[[package]] +name = "ethabi" +version = "14.0.0" +dependencies = [ + "anyhow", + "cyfs-base", + "ethereum-types", + "evm", + "hex", + "hex-literal 0.3.4", + "itertools", + "paste 1.0.11", + "rustc-hex", + "serde", + "serde_json", + "sha3 0.9.1", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9" +dependencies = [ + "ethereum-types", + "funty", + "hash-db", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "rlp-derive", + "serde", + "sha3 0.9.1", + "triehash", +] + +[[package]] +name = "ethereum-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "evm" +version = "0.26.0" +dependencies = [ + "criterion", + "cyfs-base", + "cyfs-base-meta", + "ethereum", + "evm-core", + "evm-gasometer", + "evm-runtime", + "hex", + "log 0.4.17", + "parity-scale-codec", + "primitive-types", + "rlp", + "rlp-derive", + "serde", + "sha3 0.8.2", +] + +[[package]] +name = "evm-core" +version = "0.26.0" +dependencies = [ + "cyfs-base-meta", + "funty", + "hex", + "parity-scale-codec", + "primitive-types", + "serde", +] + +[[package]] +name = "evm-gasometer" +version = "0.26.0" +dependencies = [ + "cyfs-base", + "evm-core", + "evm-runtime", + "primitive-types", +] + +[[package]] +name = "evm-runtime" +version = "0.26.0" +dependencies = [ + "cyfs-base", + "evm-core", + "primitive-types", + "sha3 0.8.2", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -2046,9 +2940,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -2060,13 +2954,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc04871e5ae3aa2952d552dae6b291b3099723bf779a8054281c1366a54613ef" dependencies = [ "cfg-if 1.0.0", - "js-sys", - "log 0.4.17", - "serde", - "serde_derive", - "serde_json", - "wasm-bindgen", - "web-sys", + "js-sys", + "log 0.4.17", + "serde", + "serde_derive", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "file-manager" +version = "0.5.0" +dependencies = [ + "async-std", + "cyfs-base", + "cyfs-debug", + "cyfs-util", + "lazy_static", + "log 0.4.17", + "rusqlite", + "tide", +] + +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.16", + "windows-sys 0.45.0", ] [[package]] @@ -2123,7 +3043,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.4", + "spin 0.9.5", ] [[package]] @@ -2164,7 +3084,7 @@ checksum = "6b2e172b694029467db935166c398f911adce5373d63bb1149740cd9182a3eee" dependencies = [ "encoding", "httparse", - "hyper", + "hyper 0.10.16", "log 0.4.17", "mime 0.2.6", "mime_multipart", @@ -2181,6 +3101,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -2195,9 +3130,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -2210,9 +3145,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -2220,15 +3155,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -2238,20 +3173,20 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.12.1", + "parking_lot 0.11.2", ] [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -2270,9 +3205,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -2281,21 +3216,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -2309,6 +3244,39 @@ dependencies = [ "slab", ] +[[package]] +name = "gateway" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "bytes 1.4.0", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "lru_time_cache", + "once_cell", + "regex", + "serde", + "serde_json", + "tide", + "toml 0.5.11", + "url 2.3.0", + "wildmatch", + "winapi", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -2374,21 +3342,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -2399,9 +3367,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c4a8d6391675c6b2ee1a6c8d06e8e2d03605c44cec1270675985a4c2a5500b" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", @@ -2418,17 +3386,19 @@ dependencies = [ "async-trait", "cyfs-base", "cyfs-bdt", + "cyfs-bdt-ext", "cyfs-chunk-lib", "cyfs-core", "cyfs-debug", - "cyfs-group", + "cyfs-group-lib", "cyfs-lib", "cyfs-meta-lib", "cyfs-stack", + "cyfs-util", "futures", "lazy_static", "log 0.4.17", - "prost 0.11.5", + "prost 0.11.6", "protobuf", "rand 0.8.5", "serde", @@ -2436,6 +3406,25 @@ dependencies = [ "sha2 0.8.2", ] +[[package]] +name = "h2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +dependencies = [ + "bytes 1.4.0", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util 0.7.7", + "tracing", +] + [[package]] name = "half" version = "1.8.2" @@ -2448,6 +3437,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -2483,9 +3487,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -2524,6 +3528,12 @@ dependencies = [ "proc-macro-hack 0.4.3", ] +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hex-literal-impl" version = "0.1.2" @@ -2583,6 +3593,16 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2603,15 +3623,37 @@ dependencies = [ "hmac 0.7.1", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "fnv", - "itoa 1.0.5", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes 1.4.0", + "http", + "pin-project-lite 0.2.9", ] [[package]] @@ -2667,6 +3709,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + [[package]] name = "hyper" version = "0.10.16" @@ -2686,11 +3734,48 @@ dependencies = [ "url 1.7.2", ] +[[package]] +name = "hyper" +version = "0.14.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +dependencies = [ + "bytes 1.4.0", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite 0.2.9", + "socket2 0.4.7", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyperlocal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +dependencies = [ + "futures-util", + "hex", + "hyper 0.14.24", + "pin-project", + "tokio", +] + [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2710,6 +3795,12 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.1.5" @@ -2732,6 +3823,20 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "impl-codec" version = "0.5.1" @@ -2741,6 +3846,24 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -2791,6 +3914,26 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -2860,6 +4003,24 @@ dependencies = [ "libc", ] +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2 0.3.19", + "widestring 0.4.3", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + [[package]] name = "itertools" version = "0.10.5" @@ -2869,12 +4030,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.5" @@ -2912,13 +4067,42 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2943,6 +4127,28 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lettre" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eabca5e0b4d0e98e7f2243fb5b7520b6af2b65d8f87bcc86f2c75185a6ff243" +dependencies = [ + "base64 0.13.1", + "email-encoding", + "email_address", + "fastrand", + "futures-util", + "hostname", + "httpdate", + "idna 0.2.1", + "mime 0.3.16", + "native-tls", + "nom 7.1.3", + "once_cell", + "quoted_printable", + "socket2 0.4.7", +] + [[package]] name = "lexical-core" version = "0.7.6" @@ -2964,9 +4170,9 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libsecp256k1" @@ -3004,6 +4210,24 @@ dependencies = [ "cc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "local-ip-address" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa9d02443a1741e9f51dafdfcbffb3863b2a89c457d762b40337d6c5153ef81" +dependencies = [ + "libc", + "neli", + "thiserror", + "windows-sys 0.42.0", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -3040,8 +4264,17 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f9dd8546191c1850ecf67d22f5ff00a935b890d0e84713159a55495cc2ac5f" dependencies = [ - "backtrace", - "log 0.4.17", + "backtrace", + "log 0.4.17", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", ] [[package]] @@ -3050,11 +4283,27 @@ version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd" +[[package]] +name = "mac_address" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" +dependencies = [ + "nix 0.23.2", + "winapi", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "maybe-uninit" @@ -3062,6 +4311,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "md5" version = "0.7.0" @@ -3076,9 +4336,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" dependencies = [ "libc", ] @@ -3107,6 +4367,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93c0d11ac30a033511ae414355d80f70d9f29a44a49140face477117a1ee90db" +[[package]] +name = "meta-stat" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-meta", + "log 0.4.17", + "misc-util", + "serde", + "serde_json", + "simple_logger 3.0.0", +] + [[package]] name = "mime" version = "0.2.6" @@ -3122,6 +4399,15 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime-sniffer" +version = "0.1.2" +source = "git+https://github.com/buckyos/rust-mime-sniffer?rev=99c00bba5091810514741bfe0f05d8c9ca244796#99c00bba5091810514741bfe0f05d8c9ca244796" +dependencies = [ + "mime 0.3.16", + "url 1.7.2", +] + [[package]] name = "mime_guess" version = "2.0.4" @@ -3141,7 +4427,7 @@ dependencies = [ "buf-read-ext", "encoding", "httparse", - "hyper", + "hyper 0.10.16", "log 0.4.17", "mime 0.2.6", "tempdir", @@ -3158,12 +4444,80 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "miniz_oxide" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.45.0", +] + +[[package]] +name = "misc-util" +version = "0.1.0" +dependencies = [ + "cyfs-base", + "lettre", + "log 0.4.17", + "serde", +] + +[[package]] +name = "mongodb" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bacb6f8cee6bf010d7bc57550d859f6a4ffe255eb8c9a7014637fe988eaece64" +dependencies = [ + "async-std", + "async-std-resolver", + "async-trait", + "base64 0.13.1", + "bitflags", + "bson", + "chrono", + "derivative", + "futures-core", + "futures-executor", + "futures-io", + "futures-util", + "hex", + "hmac 0.11.0", + "lazy_static", + "md-5", + "os_info", + "pbkdf2 0.8.0", + "percent-encoding 2.2.0", + "rand 0.8.5", + "rustls 0.19.1", + "rustls-pemfile", + "serde", + "serde_with", + "sha-1 0.9.8", + "sha2 0.9.9", + "socket2 0.4.7", + "stringprep", + "strsim 0.10.0", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util 0.6.10", + "trust-dns-proto", + "trust-dns-resolver", + "typed-builder", + "uuid 0.8.2", + "version_check 0.9.4", + "webpki", + "webpki-roots 0.21.1", ] [[package]] @@ -3182,15 +4536,15 @@ dependencies = [ "once_cell", "parking_lot 0.12.1", "thiserror", - "widestring", + "widestring 0.5.1", "winapi", ] [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -3204,6 +4558,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "neli" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9053554eb5dcb7e10d9cdab1206965bde870eed5d0d341532ca035e3ba221508" +dependencies = [ + "byteorder", + "libc", +] + [[package]] name = "nix" version = "0.23.2" @@ -3242,14 +4606,41 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "notify" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.42.0", +] + [[package]] name = "ntapi" version = "0.4.0" @@ -3338,6 +4729,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -3369,18 +4771,107 @@ dependencies = [ [[package]] name = "object" -version = "0.30.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "ood-control" +version = "0.5.1" +dependencies = [ + "android_logger", + "async-h1", + "async-std", + "async-trait", + "cyfs-base", + "cyfs-debug", + "cyfs-lib", + "cyfs-util", + "futures", + "hex", + "http-types", + "jni", + "lazy_static", + "log 0.4.17", + "mac_address", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sysinfo 0.26.9", + "tide", +] + +[[package]] +name = "ood-daemon" +version = "0.5.0" +dependencies = [ + "async-h1", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-meta-lib", + "cyfs-util", + "fs_extra", + "futures", + "futures-util", + "hex", + "http-types", + "lazy_static", + "log 0.4.17", + "notify", + "once_cell", + "ood-control", + "rand 0.7.3", + "semver 1.0.16", + "serde", + "serde_json", + "tide", + "toml 0.5.11", + "zip 0.6.4", +] + +[[package]] +name = "ood-installer" +version = "0.5.0" +dependencies = [ + "app-manager", + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-client", + "cyfs-core", + "cyfs-debug", + "cyfs-meta-lib", + "cyfs-util", + "desc-tool", + "futures-util", + "hex", + "log 0.4.17", + "mac_address", + "ood-control", + "ood-daemon", + "os_type", + "qrcode", + "rust-embed", +] [[package]] name = "oorandom" @@ -3445,6 +4936,38 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_info" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c424bc68d15e0778838ac013b5b3449544d8133633d8016319e7e05a820b8c0" +dependencies = [ + "log 0.4.17", + "winapi", +] + +[[package]] +name = "os_type" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24d44c0eea30167516ed8f6daca4b5e3eebcde1bde1e4e6e08b809fb02c7ba5" +dependencies = [ + "regex", +] + +[[package]] +name = "pack-tools" +version = "0.5.0" +dependencies = [ + "clap", + "cyfs-base", + "log 0.4.17", + "sha2 0.8.2", + "simple_logger 2.3.0", + "walkdir", + "zip 0.6.4", +] + [[package]] name = "parity-scale-codec" version = "2.3.1" @@ -3465,7 +4988,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -3495,7 +5018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.7", ] [[package]] @@ -3514,15 +5037,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec 1.10.0", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -3561,6 +5084,15 @@ dependencies = [ "proc-macro-hack 0.5.20+deprecated", ] +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -3605,11 +5137,32 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "perf-service" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "chrono", + "clap", + "cyfs-base", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-perf-base", + "cyfs-util", + "log 0.4.17", + "mongodb", + "serde", + "serde_json", + "toml 0.7.2", +] + [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -3677,9 +5230,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -3709,6 +5262,25 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pn-miner" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "libc", + "log 0.4.17", + "rusqlite", + "serde", + "serde_json", + "tide", +] + [[package]] name = "polling" version = "2.5.2" @@ -3736,15 +5308,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ "proc-macro2", "syn", @@ -3752,9 +5324,9 @@ dependencies = [ [[package]] name = "primal" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389bfb36ac527b5fe21a57f87bc7956af45cbeb2de7750b90b7ebac6770e715e" +checksum = "4b53cc99c892c461727618e8a63806c94b09ae13c494dc5fc70a7557b3a2f071" dependencies = [ "primal-check", "primal-estimate", @@ -3787,9 +5359,9 @@ checksum = "7374f14c76f23e1271e6be806981ac5dd9e52b59132b0a2f10bcc412495f9159" [[package]] name = "primal-sieve" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fee6031f66b44e8e004ac9bf81fd1c5abcbbb25bd392bc27429daa1759654a" +checksum = "9f2a14766f8c543620824b5b2cec356abf2681b76966a7ac4b4ed2c0011e696a" dependencies = [ "primal-bit", "primal-estimate", @@ -3804,6 +5376,8 @@ checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", "uint", ] @@ -3813,18 +5387,17 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit 0.18.1", ] [[package]] @@ -3850,9 +5423,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -3863,18 +5436,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "prost-derive 0.9.0", ] [[package]] name = "prost" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ - "bytes 1.3.0", - "prost-derive 0.11.5", + "bytes 1.4.0", + "prost-derive 0.11.6", ] [[package]] @@ -3883,7 +5456,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "heck 0.3.3", "itertools", "lazy_static", @@ -3899,20 +5472,20 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ - "bytes 1.3.0", - "heck 0.4.0", + "bytes 1.4.0", + "heck 0.4.1", "itertools", "lazy_static", "log 0.4.17", "multimap", "petgraph", "prettyplease", - "prost 0.11.5", - "prost-types 0.11.5", + "prost 0.11.6", + "prost-types 0.11.6", "regex", "syn", "tempfile", @@ -3934,9 +5507,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -3951,18 +5524,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", "prost 0.9.0", ] [[package]] name = "prost-types" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ - "bytes 1.3.0", - "prost 0.11.5", + "bytes 1.4.0", + "prost 0.11.6", ] [[package]] @@ -3971,7 +5544,7 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" dependencies = [ - "bytes 1.3.0", + "bytes 1.4.0", ] [[package]] @@ -4093,6 +5666,16 @@ dependencies = [ "syn", ] +[[package]] +name = "qrcode" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" +dependencies = [ + "checked_int_cast", + "image", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4110,9 +5693,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f14e071918cbeefc5edc986a7aa92c425dae244e003a35e1cdddb5ca39b5cb" +checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" [[package]] name = "radium" @@ -4133,6 +5716,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -4143,7 +5745,7 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc", + "rand_hc 0.2.0", ] [[package]] @@ -4157,6 +5759,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -4210,6 +5822,15 @@ dependencies = [ "getrandom 0.2.8", ] +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -4219,6 +5840,59 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rayon" version = "1.6.1" @@ -4231,9 +5905,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -4289,26 +5963,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -4319,6 +5987,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.16.20" @@ -4343,6 +6021,27 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes 1.4.0", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "route-recognizer" version = "0.2.0" @@ -4411,6 +6110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a" dependencies = [ "bitflags", + "chrono", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -4431,6 +6131,40 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rust-embed" +version = "6.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" +dependencies = [ + "sha2 0.10.6", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -4478,6 +6212,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "rustversion" version = "1.0.11" @@ -4505,6 +6248,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +dependencies = [ + "cfg-if 1.0.0", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +dependencies = [ + "proc-macro-crate 1.3.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "scan_dir" version = "0.3.3" @@ -4516,12 +6283,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -4548,9 +6314,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.7.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -4561,9 +6327,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -4599,6 +6365,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.2" @@ -4631,11 +6406,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.5", + "indexmap", + "itoa", "ryu", "serde", ] @@ -4651,6 +6427,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4658,11 +6443,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.5", + "itoa", "ryu", "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -4745,6 +6565,31 @@ dependencies = [ "cc", ] +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +dependencies = [ + "block-buffer 0.7.3", + "byte-tools", + "digest 0.8.1", + "keccak", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", +] + [[package]] name = "shared_memory" version = "0.12.4" @@ -4761,9 +6606,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -4771,9 +6616,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -4788,34 +6633,60 @@ dependencies = [ ] [[package]] -name = "simple_asn1" -version = "0.4.1" +name = "simple_asn1" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" +dependencies = [ + "chrono", + "num-bigint 0.2.6", + "num-traits", +] + +[[package]] +name = "simple_logger" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48047e77b528151aaf841a10a9025f9459da80ba820e425ff7eb005708a76dc7" +dependencies = [ + "atty", + "colored", + "log 0.4.17", + "time 0.3.19", + "winapi", +] + +[[package]] +name = "simple_logger" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" +checksum = "cc20708d703a44b96b3b700578a85b6fe887fc63ab20315757026bb8a12faaad" dependencies = [ - "chrono", - "num-bigint 0.2.6", - "num-traits", + "atty", + "colored", + "log 0.4.17", + "time 0.3.19", + "winapi", ] [[package]] name = "simple_logger" -version = "2.3.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48047e77b528151aaf841a10a9025f9459da80ba820e425ff7eb005708a76dc7" +checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" dependencies = [ "atty", "colored", "log 0.4.17", - "time 0.3.16", - "winapi", + "time 0.3.19", + "windows-sys 0.42.0", ] [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg 1.1.0", ] @@ -4835,6 +6706,58 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "sn-miner-rust" +version = "0.5.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-debug", + "cyfs-util", + "log 0.4.17", +] + +[[package]] +name = "sn-online-test" +version = "0.1.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-util", + "log 0.4.17", + "rand 0.7.3", + "simple_logger 4.0.0", +] + +[[package]] +name = "sn-updater" +version = "0.1.0" +dependencies = [ + "async-std", + "clap", + "cyfs-base", + "cyfs-base-meta", + "cyfs-meta-lib", + "cyfs-util", + "log 0.4.17", + "simple_logger 4.0.0", +] + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -4853,9 +6776,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" dependencies = [ "lock_api", ] @@ -4877,7 +6800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom 7.1.1", + "nom 7.1.3", "unicode_categories", ] @@ -4901,7 +6824,8 @@ dependencies = [ "atoi", "bitflags", "byteorder", - "bytes 1.3.0", + "bytes 1.4.0", + "chrono", "crc", "crossbeam-queue", "digest 0.10.6", @@ -4917,7 +6841,7 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.5", + "itoa", "libc", "libsqlite3-sys", "log 0.4.17", @@ -4929,7 +6853,7 @@ dependencies = [ "rand 0.8.5", "rsa 0.6.1", "rustls 0.19.1", - "sha-1", + "sha-1 0.10.1", "sha2 0.10.6", "smallvec 1.10.0", "sqlformat", @@ -4949,7 +6873,7 @@ checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.4.0", + "heck 0.4.1", "once_cell", "proc-macro2", "quote", @@ -5052,6 +6976,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "1.0.0" @@ -5120,9 +7050,24 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.8" +version = "0.26.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" +dependencies = [ + "cfg-if 1.0.0", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + +[[package]] +name = "sysinfo" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6" +checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -5133,12 +7078,29 @@ dependencies = [ "winapi", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -5176,9 +7138,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -5224,10 +7186,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -5291,101 +7254,333 @@ dependencies = [ [[package]] name = "time" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ - "itoa 1.0.5", + "itoa", "libc", "num_threads", "serde", "time-core", - "time-macros 0.2.5", + "time-macros 0.2.7", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack 0.5.20+deprecated", + "time-macros-impl", +] + +[[package]] +name = "time-macros" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" +dependencies = [ + "time-core", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack 0.5.20+deprecated", + "proc-macro2", + "quote", + "standback", + "syn", +] + +[[package]] +name = "timer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" +dependencies = [ + "chrono", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +dependencies = [ + "autocfg 1.1.0", + "bytes 1.4.0", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite 0.2.9", + "socket2 0.4.7", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes 1.4.0", + "futures-core", + "futures-io", + "futures-sink", + "log 0.4.17", + "pin-project-lite 0.2.9", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes 1.4.0", + "futures-core", + "futures-sink", + "pin-project-lite 0.2.9", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "indexmap", + "serde", +] + +[[package]] +name = "toml" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "toml_edit 0.19.4", +] + +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646" +dependencies = [ + "combine", + "indexmap", + "itertools", + "toml_datetime 0.5.1", ] [[package]] -name = "time-core" -version = "0.1.0" +name = "toml_edit" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime 0.5.1", +] [[package]] -name = "time-macros" -version = "0.1.1" +name = "toml_edit" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", - "time-macros-impl", + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "winnow", ] [[package]] -name = "time-macros" -version = "0.2.5" +name = "tower-service" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" -dependencies = [ - "time-core", -] +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] -name = "time-macros-impl" -version = "0.1.2" +name = "tracing" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "proc-macro-hack 0.5.20+deprecated", - "proc-macro2", - "quote", - "standback", - "syn", + "cfg-if 1.0.0", + "pin-project-lite 0.2.9", + "tracing-core", ] [[package]] -name = "timer" -version = "0.2.0" +name = "tracing-core" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "chrono", + "once_cell", ] [[package]] -name = "tinytemplate" -version = "1.2.1" +name = "traitobject" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" dependencies = [ - "serde", - "serde_json", + "hash-db", + "rlp", ] [[package]] -name = "tokio" -version = "1.23.0" +name = "trust-dns-proto" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" dependencies = [ - "autocfg 1.1.0", - "pin-project-lite 0.2.9", - "windows-sys 0.42.0", + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.1", + "ipnet", + "lazy_static", + "log 0.4.17", + "rand 0.8.5", + "smallvec 1.10.0", + "thiserror", + "tinyvec", + "tokio", + "url 2.3.0", ] [[package]] -name = "toml" -version = "0.5.10" +name = "trust-dns-resolver" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" dependencies = [ - "indexmap", - "serde", + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lazy_static", + "log 0.4.17", + "lru-cache", + "parking_lot 0.11.2", + "resolv-conf", + "smallvec 1.10.0", + "thiserror", + "tokio", + "trust-dns-proto", ] [[package]] -name = "traitobject" -version = "0.1.0" +name = "try-lock" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" @@ -5395,12 +7590,12 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.3.0", + "bytes 1.4.0", "http", "httparse", "log 0.4.17", "rand 0.8.5", - "sha-1", + "sha-1 0.10.1", "thiserror", "url 2.3.0", "utf-8", @@ -5412,6 +7607,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +[[package]] +name = "typed-builder" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46ee5bd706ff79131be9c94e7edcb82b703c487766a114434e5790361cf08c5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.16.0" @@ -5450,9 +7656,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" @@ -5471,9 +7677,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -5544,6 +7750,25 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "uuid" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +dependencies = [ + "getrandom 0.2.8", + "serde", +] + [[package]] name = "value-bag" version = "1.0.0-alpha.9" @@ -5570,6 +7795,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + [[package]] name = "version_check" version = "0.1.5" @@ -5582,6 +7813,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.0" @@ -5599,6 +7839,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log 0.4.17", + "try-lock", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -5619,9 +7869,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "serde", @@ -5631,9 +7881,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log 0.4.17", @@ -5646,9 +7896,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5658,9 +7908,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5668,9 +7918,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -5681,15 +7931,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -5734,21 +7984,33 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", "once_cell", ] +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "widestring" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +[[package]] +name = "wildmatch" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" + [[package]] name = "win-sys" version = "0.3.1" @@ -5804,37 +8066,48 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" @@ -5844,15 +8117,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" @@ -5862,15 +8129,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" @@ -5880,15 +8141,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" @@ -5898,21 +8153,15 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" @@ -5922,15 +8171,27 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" +name = "winnow" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] [[package]] name = "wyz" @@ -5938,6 +8199,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] + [[package]] name = "zeroize" version = "1.5.7" @@ -5961,9 +8231,23 @@ dependencies = [ [[package]] name = "zip" -version = "0.6.3" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "flate2", + "thiserror", + "time 0.1.45", +] + +[[package]] +name = "zip" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" dependencies = [ "aes 0.7.5", "byteorder", @@ -5973,12 +8257,73 @@ dependencies = [ "crossbeam-utils", "flate2", "hmac 0.12.1", - "pbkdf2", + "pbkdf2 0.11.0", "sha1 0.10.5", - "time 0.3.16", + "time 0.3.19", "zstd", ] +[[package]] +name = "zip-extract" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c5cc0309f6e81ab96c2b43d5e935025f8732c886690be8f78f68e06bad1d274" +dependencies = [ + "log 0.4.17", + "thiserror", + "zip 0.5.13", +] + +[[package]] +name = "zone-simulator" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "bip39", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "lazy_static", + "log 0.4.17", + "once_cell", + "rand 0.7.3", +] + +[[package]] +name = "zone-stack" +version = "0.5.0" +dependencies = [ + "async-std", + "async-trait", + "bip39", + "clap", + "cyfs-base", + "cyfs-bdt", + "cyfs-cip", + "cyfs-core", + "cyfs-debug", + "cyfs-lib", + "cyfs-stack-loader", + "cyfs-util", + "futures", + "hex", + "log 0.4.17", + "rand 0.8.5", + "serde", + "serde_json", + "toml 0.5.11", + "zone-simulator", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" @@ -6000,10 +8345,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.4+zstd.1.5.2" +version = "2.0.7+zstd.1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" +checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" dependencies = [ "cc", "libc", + "pkg-config", ] From e3510ac9684e9be4ca88edbae2c788385d40e4e4 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 10 Mar 2023 20:09:59 +0800 Subject: [PATCH 517/553] rebase from buckyos/main --- src/Cargo.toml | 1 + src/meta/cyfs-meta/src/executor/view.rs | 52 +++++++++++++------------ src/tests/group-example/src/main.rs | 4 +- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index 28684a8d6..532139459 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -26,6 +26,7 @@ members = [ "./component/cyfs-chunk-lib", "./component/cyfs-mobile-stack", "./component/cyfs-bdt-ext", + "./component/cyfs-group-lib", "./component/cyfs-group", "./service/ood-control", diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 5f245f3a8..7d76e9fcc 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -1,12 +1,13 @@ -use cyfs_base_meta::*; -use crate::state_storage::{StateRef, StateWeakRef}; use super::context; -use crate::archive_storage::*; +use crate::State; use crate::executor::context::AccountMethods; use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; -use evm::executor::{MemoryStackState, StackSubstateMetadata, StackExecutor}; use crate::stat::Stat; +use crate::state_storage::{StateRef, StateWeakRef}; +use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base_meta::*; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; struct ViewExecuteContext {} @@ -20,8 +21,13 @@ pub struct ViewMethodExecutor { evm_config: evm::Config, } -impl ViewMethodExecutor { - pub fn new(block: &BlockDesc, ref_state: &StateRef, stat: Option, method: M) -> ViewMethodExecutor { +impl ViewMethodExecutor { + pub fn new( + block: &BlockDesc, + ref_state: &StateRef, + stat: Option, + method: M, + ) -> ViewMethodExecutor { ViewMethodExecutor { method, ref_state: StateRef::downgrade(ref_state), @@ -86,26 +92,22 @@ impl ViewMethodExecutor { impl ViewMethodExecutor { pub async fn exec(&self) -> BuckyResult<::Result> { let ret = match self.ref_state.to_rc()?.get_obj_desc(&self.method.id).await { - Ok(obj) => { - match obj { - SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), - SavedMetaObject::People(obj) => Ok(obj.to_vec()?), - SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), - SavedMetaObject::File(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Data(obj) => Ok(obj.data), - SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), - SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), - SavedMetaObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + Ok(obj) => match obj { + SavedMetaObject::Device(obj) => Ok(obj.to_vec()?), + SavedMetaObject::People(obj) => Ok(obj.to_vec()?), + SavedMetaObject::UnionAccount(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Group(obj) => Ok(obj.to_vec()?), + SavedMetaObject::File(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Data(obj) => Ok(obj.data), + SavedMetaObject::MinerGroup(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SNService(obj) => Ok(obj.to_vec()?), + SavedMetaObject::Contract(obj) => Ok(obj.to_vec()?), + SavedMetaObject::SimpleGroup => { + panic!("SimpleGroup is deprecated, you can use the Group.") } - } - Err(e) => { - Err(e) - } + SavedMetaObject::Org => panic!("Org is deprecated, you can use the Group."), + }, + Err(e) => Err(e), }; if let Some(stat) = &self.stat { stat.query_desc(&self.method.id, ret.is_ok()); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index e74f3c5d6..361bfd35a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -34,7 +34,7 @@ mod Common { TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; - use cyfs_bdt_ext::BdtStackParams; + use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{DecApp, DecAppId}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; @@ -372,6 +372,7 @@ mod Common { known_device, known_passive_pn: vec![], udp_sn_only: None, + sn_mode: SNMode::Normal, }; let stack_param = CyfsStackParams { @@ -379,6 +380,7 @@ mod Common { isolate: Some(device.desc().object_id().to_string()), sync_service: false, shared_stack: true, + perf_service: false, }, noc: CyfsStackNOCParams {}, interface: CyfsStackInterfaceParams { From 05608642ffe681d664e13eb9af2d9abcfba711e2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 14:48:12 +0800 Subject: [PATCH 518/553] Adapte to the buckyos --- .../engine/storage_engine_group_state.rs | 44 ++++++++++++++++--- .../cyfs-group/src/storage/group_storage.rs | 9 +++- src/meta/cyfs-meta/src/executor/view.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs index 029b09e78..cf04e93ff 100644 --- a/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs +++ b/src/component/cyfs-group/src/storage/engine/storage_engine_group_state.rs @@ -19,6 +19,8 @@ const ACCESS: Option = None; #[derive(Clone)] pub struct StorageEngineGroupState { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, state_path: Arc, } @@ -183,18 +185,28 @@ impl StorageEngineGroupState { Ok(cache) } - pub fn new(state_mgr: ObjectMapRootManagerRef, state_path: GroupStatePath) -> Self { + pub fn new( + state_mgr: ObjectMapRootManagerRef, + state_path: GroupStatePath, + group_id: ObjectId, + dec_id: ObjectId, + ) -> Self { Self { state_mgr, state_path: Arc::new(state_path), + group_id, + dec_id, } } pub async fn create_writer(&self) -> BuckyResult { - Ok( - StorageEngineGroupStateWriter::new(self.state_mgr.clone(), self.state_path.clone()) - .await?, + Ok(StorageEngineGroupStateWriter::new( + self.state_mgr.clone(), + self.state_path.clone(), + self.group_id, + self.dec_id, ) + .await?) } pub fn root_cache(&self) -> &ObjectMapRootCacheRef { @@ -218,6 +230,8 @@ impl StorageEngine for StorageEngineGroupState { #[derive(Clone)] pub struct StorageEngineGroupStateWriter { + group_id: ObjectId, + dec_id: ObjectId, state_mgr: ObjectMapRootManagerRef, op_env: ObjectMapPathOpEnvRef, prepare_op_env: ObjectMapSingleOpEnvRef, @@ -230,6 +244,8 @@ impl StorageEngineGroupStateWriter { async fn new( state_mgr: ObjectMapRootManagerRef, state_path: Arc, + group_id: ObjectId, + dec_id: ObjectId, ) -> BuckyResult { let op_env = state_mgr.create_op_env(ACCESS)?; let prepare_op_env = state_mgr.create_single_op_env(ACCESS)?; @@ -237,7 +253,11 @@ impl StorageEngineGroupStateWriter { if let Err(err) = prepare_op_env.load_by_path(state_path.prepares()).await { if err.code() == BuckyErrorCode::NotFound { prepare_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(group_id), + Some(dec_id), + ) .await?; None } else { @@ -254,6 +274,8 @@ impl StorageEngineGroupStateWriter { state_mgr, prepare_map_id, write_result: Ok(()), + group_id, + dec_id, }) } @@ -264,7 +286,11 @@ impl StorageEngineGroupStateWriter { ) -> BuckyResult { let single_op_env = self.state_mgr.create_single_op_env(ACCESS)?; single_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new( + ObjectMapSimpleContentType::Map, + Some(self.group_id), + Some(self.dec_id), + ) .await?; single_op_env .insert_with_key(GROUP_STATE_PATH_BLOCK, block_id) @@ -463,7 +489,11 @@ impl StorageEngineGroupStateWriter { } add_single_op_env - .create_new(ObjectMapSimpleContentType::Set) + .create_new( + ObjectMapSimpleContentType::Set, + Some(self.group_id), + Some(self.dec_id), + ) .await?; } else { add_single_op_env diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 3a762c1b6..78af14c4b 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -81,6 +81,8 @@ impl GroupStorage { storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), + group_id.clone(), + dec_id.clone(), ), local_device_id, cache: StorageCacheInfo::new(None), @@ -138,7 +140,12 @@ impl GroupStorage { rpath: rpath.to_string(), non_driver, group_chunk_id: group_chunk_id.object_id(), - storage_engine: StorageEngineGroupState::new(dec_group_state, state_path), + storage_engine: StorageEngineGroupState::new( + dec_group_state, + state_path, + group_id.clone(), + dec_id.clone(), + ), local_device_id, cache, object_map_processor, diff --git a/src/meta/cyfs-meta/src/executor/view.rs b/src/meta/cyfs-meta/src/executor/view.rs index 7d76e9fcc..47e3c8a7d 100644 --- a/src/meta/cyfs-meta/src/executor/view.rs +++ b/src/meta/cyfs-meta/src/executor/view.rs @@ -5,7 +5,7 @@ use crate::helper::ArcWeakHelper; use crate::meta_backend::MetaBackend; use crate::stat::Stat; use crate::state_storage::{StateRef, StateWeakRef}; -use cyfs_base::{BuckyResult, RawConvertTo}; +use cyfs_base::{BuckyResult, RawConvertTo, ObjectId}; use cyfs_base_meta::*; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; From ec6ad354425bd26a106a5eb932c3b4b9632eb2e7 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 13 Mar 2023 18:53:20 +0800 Subject: [PATCH 519/553] Adapt interface of RootState, add param(owner) --- src/tests/group-example/src/main.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 361bfd35a..01d57996b 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -547,8 +547,8 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - NONPostObjectInputRequest, NONPostObjectInputResponse, RequestSourceInfo, - RouterHandlerChain, SharedCyfsStack, + CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, + RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -677,7 +677,12 @@ mod GroupDecService { } None => { state_op_env - .create_new(ObjectMapSimpleContentType::Map) + .create_new_with_option( + ObjectMapSimpleContentType::Map, + &CreateObjectMapOption::new_with_owner( + proposal.rpath().group_id().clone(), + ), + ) .await .expect( format!("create_new {} failed", EXAMPLE_VALUE_PATH.as_str()).as_str(), From 9b30a7cc7c64e5b5fb1e75029f727a28e1d37934 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 15:13:47 +0800 Subject: [PATCH 520/553] Testcase for client --- .../cyfs-core/src/group/group_proposal.rs | 1 - .../cyfs-group/src/dec/rpath_service.rs | 20 +- src/tests/group-example/src/main.rs | 231 ++++++++++++------ 3 files changed, 175 insertions(+), 77 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_proposal.rs b/src/component/cyfs-core/src/group/group_proposal.rs index 508418f7b..e011afdf7 100644 --- a/src/component/cyfs-core/src/group/group_proposal.rs +++ b/src/component/cyfs-core/src/group/group_proposal.rs @@ -1,7 +1,6 @@ use crate::{CoreObjectType, GroupRPath}; use async_trait::async_trait; use cyfs_base::*; -use sha2::Digest; #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform)] #[cyfs_protobuf_type(crate::codec::protos::GroupProposalDescContent)] diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index 1f2e836a1..47bd1ffd7 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,8 +1,12 @@ use std::sync::Arc; -use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner}; +use cyfs_base::{ + AnyNamedObject, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, + RsaCPUObjectSigner, TypelessCoreObject, +}; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; +use cyfs_lib::NONObjectInfo; use crate::{ network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, @@ -15,6 +19,7 @@ struct RPathServiceRaw { network_sender: crate::network::Sender, pending_proposal_handle: PendingProposalHandler, hotstuff: Hotstuff, + non_driver: NONDriverHelper, } #[derive(Clone)] @@ -44,7 +49,7 @@ impl RPathService { store, signer, network_sender.clone(), - non_driver, + non_driver.clone(), pending_proposal_consumer, event_notifier, rpath.clone(), @@ -56,6 +61,7 @@ impl RPathService { local_id, rpath, hotstuff, + non_driver, }; Ok(Self(Arc::new(raw))) @@ -71,6 +77,16 @@ impl RPathService { self.rpath(), proposal.desc().object_id() ); + + let object_raw = proposal.to_vec()?; + let any_obj = + AnyNamedObject::Core(TypelessCoreObject::clone_from_slice(object_raw.as_slice())?); + let non_obj = NONObjectInfo::new( + proposal.desc().object_id(), + object_raw, + Some(Arc::new(any_obj)), + ); + self.0.non_driver.put_object(non_obj).await?; self.0.pending_proposal_handle.on_proposal(proposal).await } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 01d57996b..b913490f2 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -8,9 +8,9 @@ use cyfs_base::{ use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group_lib::GroupManager; use cyfs_lib::{ - DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, NONOutputRequestCommon, - NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, NamedObjectStorageCategory, - RequestProtocol, RequestSourceInfo, SharedCyfsStack, + CyfsStackRequestorType, DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, + NONOutputRequestCommon, NONPutObjectOutputRequest, NamedObjectCachePutObjectRequest, + NamedObjectStorageCategory, RequestProtocol, RequestSourceInfo, SharedCyfsStack, }; use cyfs_stack::CyfsStack; use Common::{create_stack, EXAMPLE_RPATH}; @@ -473,7 +473,7 @@ mod Common { dec_app: &DecApp, rpc_port: u16, ws_port: u16, - ) -> (CyfsStack, SharedCyfsStack) { + ) -> (Box, Box) { let params = init_stack_params( people, private_key, @@ -488,20 +488,23 @@ mod Common { log::info!("cyfs-stack.open"); - let stack = CyfsStack::open(params.0, params.1, params.2) - .await - .map_err(|e| { - log::error!("stack start failed: {}", e); - e - }) - .unwrap(); + let stack = Box::new( + CyfsStack::open(params.0, params.1, params.2) + .await + .map_err(|e| { + log::error!("stack start failed: {}", e); + e + }) + .unwrap(), + ); async_std::task::sleep(Duration::from_millis(1000)).await; - let shared_stack = + let shared_stack = Box::new( SharedCyfsStack::open_with_port(Some(dec_app.desc().object_id()), rpc_port, ws_port) .await - .unwrap(); + .unwrap(), + ); shared_stack.wait_online(None).await.unwrap(); @@ -539,7 +542,7 @@ mod GroupDecService { use async_std::sync::Mutex; use cyfs_base::*; use cyfs_core::{ - DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, + CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupProposalObject, }; use cyfs_group_lib::{ @@ -548,7 +551,8 @@ mod GroupDecService { }; use cyfs_lib::{ CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, - RequestSourceInfo, RouterHandlerChain, SharedCyfsStack, + RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, + RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -561,50 +565,82 @@ mod GroupDecService { cyfs_stack: &SharedCyfsStack, local_name: String, dec_app_id: DecAppId, + group_id: ObjectId, + rpath: &str, ) -> GroupManager { let group_mgr = GroupManager::open( cyfs_stack.clone(), - Box::new(GroupRPathDelegateFactory { local_name }), + Box::new(GroupRPathDelegateFactory { + local_name: local_name.clone(), + }), &cyfs_lib::CyfsStackRequestorType::Http, ) .await .unwrap(); - // let source = RequestSourceInfo { - // protocol: todo!(), - // zone: todo!(), - // dec: todo!(), - // verified: todo!(), - // }; + let filter = format!("obj_type == {}", CoreObjectType::GroupProposal as u16,); + let routine = ProposalListener { + service: group_mgr + .start_rpath_service( + group_id, + rpath.to_string(), + Box::new(MyRPathDelegate::new(local_name.to_string())), + ) + .await + .unwrap(), + local_name, + }; - // cyfs_stack - // .router_handlers() - // .handlers(&RouterHandlerChain::PostRouter) - // .post_object() - // .add_handler(RouterHandler::new()); + cyfs_stack + .router_handlers() + .post_object() + .add_handler( + RouterHandlerChain::Handler, + format!("group-proposal-listener-{}", dec_app_id).as_str(), + 0, + Some(filter), + Some("group-proposal".to_string()), + RouterHandlerAction::Pass, + Some(Box::new(routine)), + ) + .await + .unwrap(); group_mgr } } - // pub struct PostProposalRoutine { - // service: RPathService, - // } + pub struct ProposalListener { + service: RPathService, + local_name: String, + } - // #[async_trait::async_trait] - // impl EventListenerAsyncRoutine - // for PostProposalRoutine - // { - // async fn call( - // &self, - // param: &NONPostObjectInputRequest, - // ) -> BuckyResult { - // let (proposal, remain) = GroupProposal::raw_decode(param.object.object_raw.as_slice())?; - // assert_eq!(remain.len(), 0); - // self.service.push_proposal(proposal).await?; - // Ok(NONPostObjectInputResponse { object: None }) - // } - // } + #[async_trait::async_trait] + impl EventListenerAsyncRoutine + for ProposalListener + { + async fn call( + &self, + param: &RouterHandlerPostObjectRequest, + ) -> BuckyResult { + log::info!( + "recv proposal {} from {:?}, local: {}", + param.request.object.object_id, + param.request.common.source.zone, + self.local_name + ); + + let (proposal, remain) = + GroupProposal::raw_decode(param.request.object.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + self.service.push_proposal(&proposal).await.unwrap(); + Ok(RouterHandlerPostObjectResult { + action: RouterHandlerAction::Response, + request: None, + response: None, + }) + } + } pub struct GroupRPathDelegateFactory { local_name: String, @@ -939,6 +975,8 @@ fn create_proposal( async fn main_run() { log::info!("main_run"); + async_std::task::sleep(Duration::from_millis(10000)).await; + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -972,8 +1010,10 @@ async fn main_run() { ); let dec_app_id = DecAppId::try_from(dec_app.desc().object_id()).unwrap(); - let mut admin_stacks: Vec<(CyfsStack, SharedCyfsStack)> = vec![]; - let mut group_mgrs: Vec = vec![]; + let mut admin_stacks: Vec<(Box, Box)> = vec![]; + let mut admin_group_mgrs: Vec = vec![]; + let mut member_stacks: Vec<(Box, Box)> = vec![]; + let mut member_group_mgrs: Vec = vec![]; let mut rpc_port = 32217_u16; let mut ws_port = 33217_u16; for ((admin, _), (device, private_key)) in admins.iter() { @@ -1000,25 +1040,60 @@ async fn main_run() { ws_port += 1; } + for ((member, _), (device, private_key)) in members.iter() { + let (cyfs_stack, shared_stack) = create_stack( + member, + private_key, + device, + admins + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + members + .iter() + .map(|m| (m.0 .0.clone(), m.1 .0.clone())) + .collect(), + &group, + &dec_app, + rpc_port, + ws_port, + ) + .await; + member_stacks.push((cyfs_stack, shared_stack)); + rpc_port += 1; + ws_port += 1; + } + async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { let (_, shared_stack) = admin_stacks.get(i).unwrap(); let ((admin, _), _) = admins.get(i).unwrap(); let local_name = admin.name().unwrap(); - let group_mgr = - DecService::run(&shared_stack, local_name.to_string(), dec_app_id.clone()).await; - - let service = group_mgr - .start_rpath_service( - group.desc().object_id(), - EXAMPLE_RPATH.to_string(), - Box::new(MyRPathDelegate::new(local_name.to_string())), - ) - .await - .unwrap(); - group_mgrs.push(group_mgr); + let group_mgr = DecService::run( + &shared_stack, + local_name.to_string(), + dec_app_id.clone(), + group_id, + EXAMPLE_RPATH.as_str(), + ) + .await; + + admin_group_mgrs.push(group_mgr); + } + + for i in 0..member_stacks.len() { + let (_, shared_stack) = member_stacks.get(i).unwrap(); + let ((member, _), _) = members.get(i).unwrap(); + let group_mgr = GroupManager::open_as_client( + shared_stack.as_ref().clone(), + &CyfsStackRequestorType::WebSocket, + ) + .await + .unwrap(); + + member_group_mgrs.push(group_mgr); } async_std::task::sleep(Duration::from_millis(10000)).await; @@ -1029,9 +1104,9 @@ async fn main_run() { let PROPOSAL_COUNT = 20usize; for i in 1..PROPOSAL_COUNT { - let (_, stack) = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); - let owner = &admins.get(i % admins.len()).unwrap().0 .0; + let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let owner = &members.get(i % members.len()).unwrap().0 .0; let proposal = create_proposal( i as u64, owner.desc().object_id(), @@ -1039,11 +1114,6 @@ async fn main_run() { dec_app_id.object_id().clone(), ); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); - let noc = stack.non_service().clone(); let buf = proposal.to_vec().unwrap(); @@ -1073,16 +1143,29 @@ async fn main_run() { for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); - let stack = admin_stacks.get(i % admin_stacks.len()).unwrap(); - let group_mgr = group_mgrs.get(i % group_mgrs.len()).unwrap(); + let stack = member_stacks.get(i % member_stacks.len()).unwrap(); + let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); + let ((member, _), _) = members.get(i % members.len()).unwrap(); + let local_name = member.name().map(|n| n.to_string()); - let service = group_mgr - .find_rpath_service(&group_id, &EXAMPLE_RPATH) - .await - .unwrap(); + let client = group_mgr + .rpath_client(group_id, dec_app_id.clone(), &EXAMPLE_RPATH) + .await; async_std::task::spawn(async move { - service.push_proposal(&proposal).await.unwrap(); + log::info!( + "client {:?} will post proposal {}", + local_name, + proposal.desc().object_id(), + ); + + let result = client.post_proposal(&proposal).await; + log::info!( + "client {:?} post proposal {}, result: {:?}", + local_name, + proposal.desc().object_id(), + result.map(|o| o.map(|o| o.object_id)) + ); }); if i % 10 == 0 { @@ -1093,7 +1176,7 @@ async fn main_run() { async_std::task::sleep(Duration::from_millis(10000)).await; - // let client = group_mgrs + // let client = admin_group_mgrs // .get(0) // .unwrap() // .rpath_client( From 373446975467065f479da92e81eac282292629a2 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 14 Mar 2023 21:16:25 +0800 Subject: [PATCH 521/553] Complete the signature for group --- .../cyfs-group-lib/src/rpath_client.rs | 2 +- .../cyfs-stack/src/resolver/device_manager.rs | 106 +++++++++++++++++- .../cyfs-stack/src/zone/zone_manager.rs | 14 +-- src/tests/group-example/src/main.rs | 51 ++++++--- 4 files changed, 149 insertions(+), 24 deletions(-) diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 7d7c9a613..6474fce9d 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -42,7 +42,7 @@ impl RPathClient { .requestor .post_object(NONPostObjectOutputRequest { common: NONOutputRequestCommon { - req_path: None, + req_path: Some("post-proposal".to_string()), source: None, dec_id: self.0.local_dec_id.clone(), level: NONAPILevel::Router, diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 2a9aa3d56..97e822c31 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -5,6 +5,7 @@ use cyfs_bdt::DeviceCache; use cyfs_lib::*; use async_trait::async_trait; +use std::collections::HashSet; use std::collections::{hash_map::Entry, HashMap}; use std::sync::{Arc, RwLock}; @@ -87,7 +88,7 @@ impl DeviceInfoManagerImpl { self.list.read().unwrap().get(device_id).map(|d| d.clone()) } - async fn verfiy_own_signs( + async fn verfiy_single_own_signs( &self, object_id: &ObjectId, object: &Arc, @@ -122,6 +123,103 @@ impl DeviceInfoManagerImpl { } } + async fn verfiy_group_own_signs( + &self, + object_id: &ObjectId, + object: &Arc, + ) -> BuckyResult<()> { + if object_id.obj_type_code() != ObjectTypeCode::Group { + let msg = format!( + "verify object own's body sign by owner failed for expect group, id = {}", + object_id + ); + warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let group = object.as_group(); + let sign_object_ids = HashSet::::from_iter( + [ + group.admins().iter().map(|m| m.id).collect::>(), + group.members().iter().map(|m| m.id).collect::>(), + ] + .concat() + .into_iter(), + ); + + // all singatures + let results = futures::future::join_all( + sign_object_ids + .into_iter() + .map(|id| self.verify_with_object(object_id.clone(), object.clone(), id)), + ) + .await; + + results + .into_iter() + .find(|r| r.is_err()) + .map_or(Ok(()), |r| r) + } + + async fn verify_with_object( + &self, + object_id: ObjectId, + object: Arc, + signer_id: ObjectId, + ) -> BuckyResult<()> { + let mut signer_obj = self + .obj_searcher + .search_ex(None, &signer_id, ObjectSearcherFlags::full()) + .await + .map_err(|err| { + error!( + "verify object(group) own's body sign find signer failed! id={}, err={:?}", + object_id, err + ); + err + })?; + + let singer_obj_any = signer_obj.object.take(); + let req = VerifyObjectInnerRequest { + sign_type: VerifySignType::Body, + object: ObjectInfo { + object_id: object_id.clone(), + object: object.clone(), + }, + sign_object: VerifyObjectType::Object(NONSlimObjectInfo::new( + signer_id, + Some(signer_obj.object_raw), + singer_obj_any, + )), + }; + + match self.obj_verifier.verify_object_inner(req).await { + Ok(ret) => { + if ret.valid { + info!( + "verify object(group) own's body sign success! id={}", + object_id, + ); + Ok(()) + } else { + let msg = format!( + "verify object(group) own's body sign unmatch! id={}", + object_id, + ); + error!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)) + } + } + Err(e) => { + error!( + "verify object(group) own's body sign by owner error! id={}, {}", + object_id, e + ); + Err(e) + } + } + } + async fn verfiy_owner(&self, device_id: &DeviceId, device: Option<&Device>) -> BuckyResult<()> { let d; let device = match device { @@ -427,7 +525,11 @@ impl DeviceCache for DeviceInfoManager { object_id: &ObjectId, object: &Arc, ) -> BuckyResult<()> { - self.0.verfiy_own_signs(object_id, object).await + if ObjectTypeCode::Group == object_id.obj_type_code() { + self.0.verfiy_group_own_signs(object_id, object).await + } else { + self.0.verfiy_single_own_signs(object_id, object).await + } } fn clone_cache(&self) -> Box { diff --git a/src/component/cyfs-stack/src/zone/zone_manager.rs b/src/component/cyfs-stack/src/zone/zone_manager.rs index 61f284bc4..b96884306 100644 --- a/src/component/cyfs-stack/src/zone/zone_manager.rs +++ b/src/component/cyfs-stack/src/zone/zone_manager.rs @@ -646,13 +646,13 @@ impl ZoneManager { match owner_object.ood_list() { Ok(list) => { if list.len() > 0 { - let work_mode = owner_object.ood_work_mode().unwrap().to_owned(); - debug!( - "get ood list from owner object ood_list: owner={}, work_mode={:?}, list={:?}", - owner_id, work_mode, list - ); - if obj_type == ObjectTypeCode::People { + let work_mode = owner_object.ood_work_mode().unwrap().to_owned(); + debug!( + "get ood list from owner object ood_list: owner={}, work_mode={:?}, list={:?}", + owner_id, work_mode, list + ); + return Ok((work_mode, list.to_owned())); } else if obj_type == ObjectTypeCode::Group { let group = owner_object.into_group(); @@ -666,7 +666,7 @@ impl ZoneManager { .filter(|id| id.obj_type_code() == ObjectTypeCode::Device) .map(|id| DeviceId::try_from(id).unwrap()) .collect(); - return Ok((work_mode, list)); + return Ok((OODWorkMode::Standalone, list)); } else { unreachable!() } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b913490f2..d3999ea0a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -29,10 +29,10 @@ mod Common { use async_std::fs; use cyfs_base::{ AnyNamedObject, Area, Device, DeviceCategory, DeviceId, Endpoint, EndpointArea, Group, - GroupMember, IpAddr, NamedObject, ObjectDesc, People, PrivateKey, Protocol, RawConvertTo, - RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, StandardObject, - TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, NON_STACK_SYNC_BDT_VPORT, - SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, + GroupMember, IpAddr, NamedObject, ObjectDesc, ObjectLink, People, PrivateKey, Protocol, + RawConvertTo, RawDecode, RawEncode, RawFrom, RsaCPUObjectSigner, Signer, SocketAddr, + StandardObject, TypelessCoreObject, UniqueId, NON_STACK_BDT_VPORT, + NON_STACK_SYNC_BDT_VPORT, SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, }; use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; @@ -166,8 +166,8 @@ mod Common { fn create_group( founder: &People, - admins: Vec<&People>, - members: Vec<&People>, + admins: Vec<(&People, &PrivateKey)>, + members: Vec<(&People, &PrivateKey)>, oods: Vec<&Device>, ) -> Group { log::info!("create group"); @@ -176,13 +176,13 @@ mod Common { group.check_org_body_content_mut().set_admins( admins .iter() - .map(|m| GroupMember::from_member_id(m.desc().object_id())) + .map(|m| GroupMember::from_member_id(m.0.desc().object_id())) .collect(), ); group.set_members( members .iter() - .map(|m| GroupMember::from_member_id(m.desc().object_id())) + .map(|m| GroupMember::from_member_id(m.0.desc().object_id())) .collect(), ); group.set_ood_list( @@ -195,6 +195,29 @@ mod Common { log::info!("create group: {:?}", group.desc().object_id()); + let body_hash = group.body().as_ref().unwrap().raw_hash_value().unwrap(); + let signers = [admins, members].concat(); + signers + .into_iter() + .map(|(owner, private_key)| { + let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); + + async_std::task::block_on(async move { + let body_signature = signer + .sign( + body_hash.as_slice(), + &cyfs_base::SignatureSource::Object(ObjectLink { + obj_id: owner.desc().object_id(), + obj_owner: None, + }), + ) + .await + .unwrap(); + body_signature + }) + }) + .for_each(|signature| group.signs_mut().push_body_sign(signature)); + group } @@ -315,8 +338,8 @@ mod Common { } pub async fn init_group( - admins: Vec<&People>, - members: Vec<&People>, + admins: Vec<(&People, &PrivateKey)>, + members: Vec<(&People, &PrivateKey)>, oods: Vec<&Device>, ) -> Group { fs::create_dir_all("./test-group") @@ -340,7 +363,7 @@ mod Common { } } - let group = create_group(admins.get(0).unwrap(), admins, members, oods); + let group = create_group(admins.get(0).unwrap().0, admins, members, oods); fs::write("./test-group/group.desc", group.to_vec().unwrap()) .await .expect("save file ./test-group/group.desc failed"); @@ -976,7 +999,7 @@ async fn main_run() { log::info!("main_run"); async_std::task::sleep(Duration::from_millis(10000)).await; - + cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") .console("debug") @@ -998,8 +1021,8 @@ async fn main_run() { let admins = init_admins().await; let members = init_members().await; let group = init_group( - admins.iter().map(|m| &m.0 .0).collect(), - members.iter().map(|m| &m.0 .0).collect(), + admins.iter().map(|m| (&m.0 .0, &m.0 .1)).collect(), + members.iter().map(|m| (&m.0 .0, &m.0 .1)).collect(), admins.iter().map(|m| &m.1 .0).collect(), ) .await; From 01ca46f99e2a1d79618d2c0e2e3325a5045096aa Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Mar 2023 16:49:36 +0800 Subject: [PATCH 522/553] Response for proposal from RPathService --- .../cyfs-group-lib/src/group_manager.rs | 5 +- .../cyfs-group-lib/src/input_request.rs | 5 +- .../cyfs-group-lib/src/output_request.rs | 5 +- src/component/cyfs-group-lib/src/requestor.rs | 56 ++---- .../cyfs-group-lib/src/rpath_client.rs | 7 +- .../cyfs-group-lib/src/rpath_service.rs | 10 +- .../cyfs-group/examples/app_example.rs | 179 ------------------ .../src/consensus/hotstuff/hotstuff.rs | 167 +++++++++------- .../cyfs-group/src/dec/rpath_service.rs | 32 ++-- .../cyfs-stack/src/group/transform.rs | 8 +- .../src/group_api/router/local_service.rs | 2 +- .../src/group_api/service/group_handler.rs | 16 +- .../cyfs-stack/src/stack/group_non_driver.rs | 15 +- src/tests/group-example/src/main.rs | 34 +++- 14 files changed, 215 insertions(+), 326 deletions(-) delete mode 100644 src/component/cyfs-group/examples/app_example.rs diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 61a11698d..07bae1f7a 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -8,7 +8,7 @@ use cyfs_base::{ use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; use cyfs_lib::{ CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, - NONPostObjectInputResponse, RouterHandlerAction, RouterHandlerChain, + NONPostObjectInputResponse, RequestGlobalStatePath, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; @@ -75,6 +75,7 @@ impl GroupManager { ); // let filter = "*".to_string(); + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Some("group/inner-cmd")); router_handler_manager .post_object() @@ -83,7 +84,7 @@ impl GroupManager { format!("group-cmd-{}", dec_id).as_str(), 0, Some(filter), - Some("group-inner".to_string()), + Some(req_path.format_string()), RouterHandlerAction::Pass, Some(Box::new(mgr.clone())), ) diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index 0f861ea3c..54df4dda9 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -1,4 +1,5 @@ use cyfs_base::ObjectId; +use cyfs_lib::NONObjectInfo; pub struct GroupStartServiceInputRequest { pub group_id: ObjectId, @@ -7,4 +8,6 @@ pub struct GroupStartServiceInputRequest { pub struct GroupStartServiceInputResponse {} -pub struct GroupPushProposalInputResponse {} +pub struct GroupPushProposalInputResponse { + pub object: Option, +} diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index f65e02e3e..964abcc4b 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -1,4 +1,5 @@ use cyfs_base::ObjectId; +use cyfs_lib::NONObjectInfo; #[derive(Debug)] pub struct GroupStartServiceOutputRequest { @@ -8,4 +9,6 @@ pub struct GroupStartServiceOutputRequest { pub struct GroupStartServiceOutputResponse {} -pub struct GroupPushProposalOutputResponse {} +pub struct GroupPushProposalOutputResponse { + pub object: Option, +} diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index b77f93dad..af17be0c6 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -166,47 +166,29 @@ impl GroupRequestor { let mut resp = self.requestor.request(http_req).await?; - match resp.status() { - code if code.is_success() => { - let body = resp.body_string().await.map_err(|e| { - let msg = format!( - "group push proposal failed, read body string error! req={:?}/{} {}", - proposal.rpath(), + let status = resp.status(); + if status.is_success() { + match status { + http_types::StatusCode::NoContent => { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::info!( + "push proposal but empty response! obj={}, {}", proposal_id, e ); - log::error!("{}", msg); - - BuckyError::from(msg) - })?; - - // let resp = GroupPushProposalOutputResponse::decode_string(&body).map_err(|e| { - // error!( - // "decode group push proposal resp from body string error: body={} {}", - // body, e, - // ); - // e - // })?; - - log::debug!( - "group push proposal success, req={:?}/{}", - proposal.rpath(), - proposal_id - ); - - Ok(GroupPushProposalOutputResponse {}) - } - code @ _ => { - let e = RequestorHelper::error_from_resp(&mut resp).await; - log::error!( - "group push proposal failed: rpath={:?}/{}, status={}, {}", - proposal.rpath(), - proposal_id, - code, - e - ); - Err(e) + Err(e) + } + _ => { + log::info!("push proposal success: {}", proposal_id); + let object = NONRequestorHelper::decode_option_object_info(&mut resp).await?; + let ret = GroupPushProposalOutputResponse { object }; + Ok(ret) + } } + } else { + let e = RequestorHelper::error_from_resp(&mut resp).await; + log::error!("push proposal error! object={}, {}", proposal_id, e); + Err(e) } } } diff --git a/src/component/cyfs-group-lib/src/rpath_client.rs b/src/component/cyfs-group-lib/src/rpath_client.rs index 6474fce9d..2eaf71315 100644 --- a/src/component/cyfs-group-lib/src/rpath_client.rs +++ b/src/component/cyfs-group-lib/src/rpath_client.rs @@ -4,6 +4,7 @@ use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo}; use cyfs_core::{GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ NONAPILevel, NONObjectInfo, NONOutputRequestCommon, NONPostObjectOutputRequest, NONRequestor, + RequestGlobalStatePath, }; struct RPathClientRaw { @@ -38,11 +39,15 @@ impl RPathClient { &self, proposal: &GroupProposal, ) -> BuckyResult> { + let req_path = RequestGlobalStatePath::new( + Some(proposal.rpath().dec_id().clone()), + Some("group/proposal"), + ); self.0 .requestor .post_object(NONPostObjectOutputRequest { common: NONOutputRequestCommon { - req_path: Some("post-proposal".to_string()), + req_path: Some(req_path.format_string()), source: None, dec_id: self.0.local_dec_id.clone(), level: NONAPILevel::Router, diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 66d0d83f4..d6aa6972d 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -3,7 +3,8 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_lib::{ - HttpRequestorRef, IsolatePathOpEnvStub, RootStateOpEnvAccess, SharedCyfsStack, SingleOpEnvStub, + HttpRequestorRef, IsolatePathOpEnvStub, NONObjectInfo, RootStateOpEnvAccess, SharedCyfsStack, + SingleOpEnvStub, }; use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; @@ -23,7 +24,10 @@ impl RPathService { &self.0.rpath } - pub async fn push_proposal(&self, proposal: &GroupProposal) -> BuckyResult<()> { + pub async fn push_proposal( + &self, + proposal: &GroupProposal, + ) -> BuckyResult> { // post http self.0 .requestor @@ -32,7 +36,7 @@ impl RPathService { proposal, ) .await - .map(|_| {}) + .map(|resp| resp.object) } pub(crate) fn new( diff --git a/src/component/cyfs-group/examples/app_example.rs b/src/component/cyfs-group/examples/app_example.rs deleted file mode 100644 index aff70c6d6..000000000 --- a/src/component/cyfs-group/examples/app_example.rs +++ /dev/null @@ -1,179 +0,0 @@ -mod Client { - use cyfs_base::ObjectId; - use cyfs_core::GroupProposal; - use cyfs_group::RPathClient; - - pub struct DecClient {} - - impl DecClient { - async fn do_something(&self, stack: &CyfsStack) { - let rpath_mgr = stack.group_mgr(); - - let rpath_client = rpath_mgr.rpath_client(); - - let field_path = "/xxx/yyy"; - let old_value = rpath_client.get_field(field_path).await; - let param = ObjectId::default(); // param = old_value.value - let proposal = self.make_proposal(param); - rpath_client.post_proposal(proposal).await; - } - - fn make_proposal(&self, param: ObjectId) -> GroupProposal { - unimplemented!() - } - } -} - -mod GroupDecService { - use cyfs_base::*; - use cyfs_core::{DecAppId, GroupConsensusBlock, GroupProposal}; - use cyfs_group::{DelegateFactory, ExecuteResult, RPathDelegate}; - - pub struct DecService {} - - impl DecService { - pub async fn run(stack: &CyfsStack) { - let rpath_mgr = stack.group_mgr(); - - let appid = DecAppId::default(); - let delegate_factory = GroupRPathDelegateFactory {}; - - rpath_mgr.register(appid, delegate_factory) - } - } - - pub struct GroupRPathDelegateFactory {} - - impl GroupRPathDelegateFactory { - pub fn is_accept( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> bool { - // 由应用定义是否接收该rpath,并启动共识过程,参与该rpath的信息维护 - true - } - } - - #[async_trait::async_trait] - impl DelegateFactory for GroupRPathDelegateFactory { - async fn create_rpath_delegate( - &self, - group: &Group, - rpath: &str, - with_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult> { - if self.is_accept(group, rpath, with_block) { - // 如果接受,就提供该rpath的处理响应对象 - Ok(Box::new(MyRPathDelegate::new())) - } else { - Err(BuckyError::new(BuckyErrorCode::Reject, "")) - } - } - - async fn on_state_changed( - &self, - group_id: &ObjectId, - rpath: &str, - state_id: Option, - pre_state_id: Option, - ) { - unimplemented!() - } - } - - pub struct MyRPathDelegate {} - - impl MyRPathDelegate { - pub fn new() -> Self { - MyRPathDelegate {} - } - } - - impl MyRPathDelegate { - pub fn execute( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - ) -> BuckyResult { - let result_state_id = { - /** - * pre_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 - */ - ObjectId::default() - }; - - let receipt = { - /** - * 返回给Client的对象,相当于这个请求的结果或者叫回执? - */ - None - }; - - let context = { - /** - * 执行请求的上下文,运算过程中可能有验证节点无法得到的上下文信息(比如时间戳,随机数) - */ - Some(vec![]) - }; - - /** - * (result_state_id, return_object) = pre_state_id + proposal + context - */ - Ok(ExecuteResult { - context, - result_state_id: Some(result_state_id), - receipt, - }) - } - - pub fn verify( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - execute_result: &ExecuteResult, - ) -> BuckyResult { - /** - * let is_same = (execute_result.result_state_id, execute_result.return_object) - * == pre_state_id + proposal + execute_result.context - */ - Ok(true) - } - } - - #[async_trait::async_trait] - impl RPathDelegate for MyRPathDelegate { - async fn on_execute( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - ) -> BuckyResult { - self.execute(proposal, pre_state_id) - } - - async fn on_verify( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - execute_result: &ExecuteResult, - ) -> BuckyResult { - self.verify(proposal, pre_state_id, execute_result) - } - - async fn on_commited( - &self, - proposal: &GroupProposal, - pre_state_id: Option, - execute_result: &ExecuteResult, - ) { - // 提交到共识链上了,可能有些善后事宜 - unimplemented!() - } - - async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - // 自定义同步Group版本策略 - unimplemented!() - } - } -} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d2dbcc517..23e2152f1 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -17,7 +17,7 @@ use futures::FutureExt; use itertools::Itertools; use crate::{ - consensus::{synchronizer::Synchronizer}, dec_state::StatePusher, helper::Timer, Committee, + consensus::{synchronizer::Synchronizer}, dec_state::{StatePusher, CallReplyNotifier, CallReplyWaiter}, helper::Timer, Committee, GroupStorage, HotstuffMessage, PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, @@ -34,6 +34,7 @@ pub(crate) struct Hotstuff { local_device_id: ObjectId, tx_message: Sender<(HotstuffMessage, ObjectId)>, state_pusher: StatePusher, + proposal_result_notifier: CallReplyNotifier>>, } impl std::fmt::Debug for Hotstuff { @@ -56,6 +57,7 @@ impl Hotstuff { rpath: GroupRPath, ) -> Self { let (tx_message, rx_message) = async_std::channel::bounded(CHANNEL_CAPACITY); + let proposal_result_notifier = CallReplyNotifier::new(); let state_pusher = StatePusher::new( local_id, @@ -64,40 +66,44 @@ impl Hotstuff { non_driver.clone(), ); - let tx_message_runner = tx_message.clone(); - let state_pusher_runner = state_pusher.clone(); + let mut runner = HotstuffRunner::new( + local_id, + local_device_id, + committee, + store, + signer, + network_sender, + non_driver, + tx_message.clone(), + rx_message, + proposal_consumer, + state_pusher.clone(), + event_notifier, + rpath.clone(), + proposal_result_notifier.clone() + ); - { - let rpath2 = rpath.clone(); - async_std::task::spawn(async move { - HotstuffRunner::new( - local_id, - local_device_id, - committee, - store, - signer, - network_sender, - non_driver, - tx_message_runner, - rx_message, - proposal_consumer, - state_pusher_runner, - event_notifier, - rpath2, - ) - .run() - .await - }); - } + async_std::task::spawn(async move { + runner.run() + .await + }); Self { local_device_id, tx_message, state_pusher, - rpath + rpath, + proposal_result_notifier } } + pub async fn wait_proposal_result( + &self, + proposal_id: ObjectId, + ) -> CallReplyWaiter>> { + self.proposal_result_notifier.prepare(proposal_id).await + } + pub async fn on_block(&self, block: cyfs_core::GroupConsensusBlock, remote: ObjectId) { log::debug!("[hotstuff] local: {:?}, on_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", self, @@ -230,6 +236,7 @@ struct HotstuffRunner { rpath: GroupRPath, rx_proposal_waiter: Option<(Receiver<()>, u64)>, state_pusher: StatePusher, + proposal_result_notifier: CallReplyNotifier>>, } impl std::fmt::Debug for HotstuffRunner { @@ -254,6 +261,7 @@ impl HotstuffRunner { state_pusher: StatePusher, event_notifier: RPathEventNotifier, rpath: GroupRPath, + proposal_result_notifier: CallReplyNotifier>>, ) -> Self { let max_round_block = store.block_with_max_round(); let last_qc = store.last_qc(); @@ -319,6 +327,7 @@ impl HotstuffRunner { state_pusher, tx_block_gen, rx_block_gen, + proposal_result_notifier, } } @@ -687,48 +696,9 @@ impl HotstuffRunner { err })?; - if let Some((header_block, old_header_block)) = new_header_block.map(|(header_block, old_header_block, _discard_blocks)| (header_block.clone(), old_header_block)) { - log::info!( - "[hotstuff] local: {:?}, new header-block {:?} committed", - self, header_block.block_id() - ); - - /** - * 这里只清理已经提交的block包含的proposal - * 已经执行过的待提交block包含的proposal在下次打包时候去重 - * */ - self.cleanup_proposal(&header_block).await; - - log::debug!( - "[hotstuff] local: {:?}, process_block-step1 {:?}", - self, block.block_id() - ); - - let (_, qc_block) = self - .store - .pre_commits() - .iter() - .next() - .expect("the pre-commit block must exist."); - - self.notify_block_committed(&header_block, &old_header_block, qc_block).await; - - log::debug!( - "[hotstuff] local: {:?}, process_block-step2 {:?}", - self, block.block_id() - ); - - // notify by leader - if &self.local_id == header_block.owner() { - self.state_pusher - .notify_block_commit(header_block, qc_block.clone()) - .await; - } - - log::debug!( - "[hotstuff] local: {:?}, process_block-step3 {:?}", - self, block.block_id() - ); + if let Some((header_block, old_header_block, _discard_blocks)) = new_header_block { + let header_block = header_block.clone(); + self.on_new_block_commit(&header_block, &old_header_block, block).await; } match self.vote_mgr.add_voting_block(block).await { @@ -795,6 +765,65 @@ impl HotstuffRunner { Ok(()) } + async fn on_new_block_commit(&mut self, new_header_block: &GroupConsensusBlock, old_header_block: &Option, qc_qc_block: &GroupConsensusBlock) { + log::info!( + "[hotstuff] local: {:?}, new header-block {:?} committed, old: {:?}, qc-qc: {}", + self, new_header_block.block_id(), old_header_block.as_ref().map(|b| b.block_id()), qc_qc_block.block_id() + ); + + /** + * 这里只清理已经提交的block包含的proposal + * 已经执行过的待提交block包含的proposal在下次打包时候去重 + * */ + self.cleanup_proposal(new_header_block).await; + + log::debug!( + "[hotstuff] local: {:?}, process_block-step1 {:?}", + self, qc_qc_block.block_id() + ); + + let (_, qc_block) = self + .store + .pre_commits() + .iter() + .next() + .expect("the pre-commit block must exist."); + + self.notify_block_committed(new_header_block, old_header_block, qc_block).await; + + log::debug!( + "[hotstuff] local: {:?}, process_block-step2 {:?}", + self, qc_qc_block.block_id() + ); + + // notify by the block generator + if &self.local_id == new_header_block.owner() { + // push to member + self.state_pusher + .notify_block_commit(new_header_block.clone(), qc_block.clone()) + .await; + + // reply + let futs = new_header_block.proposals().iter().map(|proposal_info| { + let receipt = match proposal_info.receipt.as_ref() { + Some(receipt) => NONObjectInfo::raw_decode(receipt.as_slice()).map(|(receipt, remain)| { + assert_eq!(remain.len(), 0); + Some(receipt) + }), + None => Ok(None), + }; + self.proposal_result_notifier.reply(&proposal_info.proposal, receipt) + }); + + futures::future::join_all(futs).await; + } + + log::debug!( + "[hotstuff] local: {:?}, process_block-step3 {:?}", + self, qc_qc_block.block_id() + ); + } + async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); @@ -916,6 +945,8 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, proposal {} failed {:?}", self, proposal.desc().object_id(), err); + self.proposal_result_notifier.reply(&proposal.desc().object_id(), Err(err.clone())).await; + self.state_pusher .notify_proposal_err(proposal.clone(), err) .await; diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index 47bd1ffd7..ff175960d 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -1,8 +1,8 @@ use std::sync::Arc; use cyfs_base::{ - AnyNamedObject, BuckyResult, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, - RsaCPUObjectSigner, TypelessCoreObject, + AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_group_lib::RPathDelegate; @@ -71,23 +71,27 @@ impl RPathService { &self.0.rpath } - pub async fn push_proposal(&self, proposal: GroupProposal) -> BuckyResult<()> { - log::info!( - "group({:?}) push proposal {}", - self.rpath(), - proposal.desc().object_id() - ); + pub async fn push_proposal( + &self, + proposal: GroupProposal, + ) -> BuckyResult> { + let proposal_id = proposal.desc().object_id(); + + log::info!("group({:?}) push proposal {}", self.rpath(), proposal_id); let object_raw = proposal.to_vec()?; let any_obj = AnyNamedObject::Core(TypelessCoreObject::clone_from_slice(object_raw.as_slice())?); - let non_obj = NONObjectInfo::new( - proposal.desc().object_id(), - object_raw, - Some(Arc::new(any_obj)), - ); + let non_obj = NONObjectInfo::new(proposal_id, object_raw, Some(Arc::new(any_obj))); self.0.non_driver.put_object(non_obj).await?; - self.0.pending_proposal_handle.on_proposal(proposal).await + self.0.pending_proposal_handle.on_proposal(proposal).await?; + + let waiter = self.0.hotstuff.wait_proposal_result(proposal_id).await; + + waiter.wait().await.map_or( + Err(BuckyError::new(BuckyErrorCode::Unknown, "unknown")), + |r| r, + ) } pub fn select_branch(&self, block_id: ObjectId, source: ObjectId) -> BuckyResult<()> { diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs index 50abe1afb..74ee64c85 100644 --- a/src/component/cyfs-stack/src/group/transform.rs +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -72,7 +72,9 @@ impl GroupInputTransformer { .push_proposal(Self::convert_common(req_common), req) .await?; - let resp = GroupPushProposalInputResponse {}; + let resp = GroupPushProposalInputResponse { + object: out_resp.object, + }; Ok(resp) } @@ -144,7 +146,9 @@ impl GroupOutputTransformer { .push_proposal(self.convert_common(req_common), req) .await?; - let resp = GroupPushProposalOutputResponse {}; + let resp = GroupPushProposalOutputResponse { + object: in_resp.object, + }; Ok(resp) } diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs index e14691b5e..a6e65420c 100644 --- a/src/component/cyfs-stack/src/group_api/router/local_service.rs +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -97,7 +97,7 @@ impl GroupInputProcessor for LocalGroupService { service .push_proposal(req) .await - .map(|_| GroupPushProposalInputResponse {}) + .map(|object| GroupPushProposalInputResponse { object }) .map_err(|err| { log::error!( "group push proposal {}-{}-{} {} failed {:?}", diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs index f01f2eaa5..182cc2f2d 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_handler.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -87,15 +87,21 @@ impl GroupRequestHandler { req: NONInputHttpRequest, ) -> tide::Response { match self.on_push_proposal(req).await { - Ok(_) => { - let http_resp: tide::Response = RequestorHelper::new_ok_response(); - - http_resp - } + Ok(resp) => Self::encode_push_proposal_response(resp), Err(e) => RequestorHelper::trans_error(e), } } + pub fn encode_push_proposal_response(resp: GroupPushProposalInputResponse) -> tide::Response { + let mut http_resp = RequestorHelper::new_response(tide::StatusCode::Ok); + + if let Some(object) = resp.object { + NONRequestorHelper::encode_object_info(&mut http_resp, object); + } + + http_resp.into() + } + async fn on_push_proposal( &self, mut req: NONInputHttpRequest, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index fa136b3fa..2c00ed58e 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -4,7 +4,7 @@ use cyfs_base::{AccessString, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, - RequestProtocol, RequestSourceInfo, + RequestGlobalStatePath, RequestProtocol, RequestSourceInfo, }; use crate::{non::NONInputProcessor, non_api::NONService}; @@ -27,10 +27,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + self.non_service .get_object(NONGetObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some(req_path.format_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -57,10 +59,13 @@ impl cyfs_group::NONDriver for GroupNONDriver { async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); log::debug!("put object {} with access {}", obj.object_id, access); + + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { - req_path: None, + req_path: Some(req_path.format_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -93,10 +98,12 @@ impl cyfs_group::NONDriver for GroupNONDriver { let obj_type_code = obj.object_id.obj_type_code(); let obj_type = obj.object.as_ref().map(|obj| obj.obj_type()); + let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Some("group/inner-cmd")); + self.non_service .post_object(NONPostObjectInputRequest { common: NONInputRequestCommon { - req_path: Some("group-inner".to_string()), + req_path: Some(req_path.format_string()), source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d3999ea0a..6b867447a 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -573,9 +573,10 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - CreateObjectMapOption, NONPostObjectInputRequest, NONPostObjectInputResponse, - RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, - RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, + CreateObjectMapOption, GlobalStatePathAccessItem, NONPostObjectInputRequest, + NONPostObjectInputResponse, RequestGlobalStatePath, RequestSourceInfo, RouterHandlerAction, + RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, + RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -614,6 +615,21 @@ mod GroupDecService { local_name, }; + let req_path = RequestGlobalStatePath::new( + Some(dec_app_id.object_id().clone()), + Option::::None, + ) + .format_string(); + + cyfs_stack + .root_state_meta_stub(None, None) + .add_access(GlobalStatePathAccessItem::new( + "group/proposal", + AccessString::full().value(), + )) + .await + .unwrap(); + cyfs_stack .router_handlers() .post_object() @@ -622,7 +638,7 @@ mod GroupDecService { format!("group-proposal-listener-{}", dec_app_id).as_str(), 0, Some(filter), - Some("group-proposal".to_string()), + Some(req_path), RouterHandlerAction::Pass, Some(Box::new(routine)), ) @@ -656,11 +672,13 @@ mod GroupDecService { let (proposal, remain) = GroupProposal::raw_decode(param.request.object.object_raw.as_slice())?; assert_eq!(remain.len(), 0); - self.service.push_proposal(&proposal).await.unwrap(); + + let result = self.service.push_proposal(&proposal).await; + Ok(RouterHandlerPostObjectResult { action: RouterHandlerAction::Response, request: None, - response: None, + response: Some(result.map(|result| NONPostObjectInputResponse { object: result })), }) } } @@ -998,7 +1016,7 @@ fn create_proposal( async fn main_run() { log::info!("main_run"); - async_std::task::sleep(Duration::from_millis(10000)).await; + // async_std::task::sleep(Duration::from_millis(10000)).await; cyfs_debug::CyfsLoggerBuilder::new_app(EXAMPLE_APP_NAME.as_str()) .level("debug") @@ -1197,7 +1215,7 @@ async fn main_run() { } } - async_std::task::sleep(Duration::from_millis(10000)).await; + async_std::task::sleep(Duration::from_millis(20000)).await; // let client = admin_group_mgrs // .get(0) From b5123ba76f3f227889b1ce76e5dfedac86bfd66a Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 15 Mar 2023 20:59:37 +0800 Subject: [PATCH 523/553] Zone for group --- .../cyfs-group/src/dec/group_manager.rs | 33 +++++------ .../cyfs-stack/src/stack/cyfs_stack.rs | 5 +- .../cyfs-stack/src/stack/group_non_driver.rs | 27 ++++++--- src/tests/group-example/src/main.rs | 56 ++++++++++++------- 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 579f63831..766da468e 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -290,22 +290,23 @@ impl GroupManager { // .await; } HotstuffPackage::ProposalResult(proposal_id, result) => { - let rpath = result.as_ref().map_or_else( - |(_, target)| target.check_rpath(), - |(_, block, _)| block.rpath(), - ); - let client = self - .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) - .await?; - client - .on_message( - HotstuffMessage::ProposalResult( - proposal_id, - result.map_err(|(err, _)| err), - ), - remote, - ) - .await; + // TODO: unimplemented + // let rpath = result.as_ref().map_or_else( + // |(_, target)| target.check_rpath(), + // |(_, block, _)| block.rpath(), + // ); + // let client = self + // .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) + // .await?; + // client + // .on_message( + // HotstuffMessage::ProposalResult( + // proposal_id, + // result.map_err(|(err, _)| err), + // ), + // remote, + // ) + // .await; } HotstuffPackage::QueryState(target, sub_path) => { let rpath = target.check_rpath(); diff --git a/src/component/cyfs-stack/src/stack/cyfs_stack.rs b/src/component/cyfs-stack/src/stack/cyfs_stack.rs index 493f6ace8..78256f60d 100644 --- a/src/component/cyfs-stack/src/stack/cyfs_stack.rs +++ b/src/component/cyfs-stack/src/stack/cyfs_stack.rs @@ -434,7 +434,10 @@ impl CyfsStackImpl { let group_manager = GroupManager::new( signer, - Box::new(GroupNONDriver::new(non_service.clone())), + Box::new(GroupNONDriver::new( + non_service.clone(), + device_id.object_id().clone(), + )), bdt_stack.clone(), global_state_manager.clone_processor(), )?; diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 2c00ed58e..7347a4c38 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -11,11 +11,15 @@ use crate::{non::NONInputProcessor, non_api::NONService}; pub struct GroupNONDriver { non_service: Arc, + local_device_id: ObjectId, } impl GroupNONDriver { - pub fn new(non_service: Arc) -> Self { - Self { non_service } + pub fn new(non_service: Arc, local_device_id: ObjectId) -> Self { + Self { + non_service, + local_device_id, + } } } @@ -27,12 +31,17 @@ impl cyfs_group::NONDriver for GroupNONDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { - let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + log::debug!( + "get object {}, local: {}, from: {:?}", + object_id, + self.local_device_id, + from + ); self.non_service .get_object(NONGetObjectInputRequest { common: NONInputRequestCommon { - req_path: Some(req_path.format_string()), + req_path: None, source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { @@ -58,14 +67,18 @@ impl cyfs_group::NONDriver for GroupNONDriver { async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); - log::debug!("put object {} with access {}", obj.object_id, access); - let req_path = RequestGlobalStatePath::new(Some(dec_id.clone()), Option::::None); + log::debug!( + "put object {} with access {}, local: {}", + obj.object_id, + access, + self.local_device_id + ); self.non_service .put_object(NONPutObjectInputRequest { common: NONInputRequestCommon { - req_path: Some(req_path.format_string()), + req_path: None, source: RequestSourceInfo { protocol: RequestProtocol::DataBdt, zone: DeviceZoneInfo { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 6b867447a..6bcc78920 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -2,10 +2,12 @@ use std::{clone, collections::HashSet, sync::Arc, time::Duration}; use async_std::sync::Mutex; use cyfs_base::{ - AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawFrom, - TypelessCoreObject, + AccessString, AnyNamedObject, NamedObject, ObjectDesc, ObjectId, RawConvertTo, RawDecode, + RawFrom, TypelessCoreObject, +}; +use cyfs_core::{ + DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath, Text, TextObj, }; -use cyfs_core::{DecApp, DecAppId, DecAppObj, GroupProposal, GroupProposalObject, GroupRPath}; use cyfs_group_lib::GroupManager; use cyfs_lib::{ CyfsStackRequestorType, DeviceZoneCategory, DeviceZoneInfo, NONObjectInfo, @@ -566,14 +568,14 @@ mod GroupDecService { use cyfs_base::*; use cyfs_core::{ CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, - GroupProposalObject, + GroupProposalObject, Text, TextObj, }; use cyfs_group_lib::{ DelegateFactory, ExecuteResult, GroupManager, GroupObjectMapProcessor, RPathDelegate, RPathService, }; use cyfs_lib::{ - CreateObjectMapOption, GlobalStatePathAccessItem, NONPostObjectInputRequest, + CreateObjectMapOption, GlobalStatePathAccessItem, NONObjectInfo, NONPostObjectInputRequest, NONPostObjectInputResponse, RequestGlobalStatePath, RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, @@ -768,7 +770,7 @@ mod GroupDecService { } }; - let result_value = { + let (result_value, result_value_u64) = { /** * prev_state_id是一个MAP的操作对象,形式待定,可能就是一个SingleOpEnv,但最好支持多级路径操作 */ @@ -785,10 +787,11 @@ mod GroupDecService { let delta = u64::from_be_bytes(delta); let value = prev_value + delta; - ObjectIdDataBuilder::new() + let result_value = ObjectIdDataBuilder::new() .data(&value.to_be_bytes()) .build() - .unwrap() + .unwrap(); + (result_value, value) }; let result_state_id = { @@ -819,14 +822,21 @@ mod GroupDecService { /** * 返回给Client的对象,相当于这个请求的结果或者叫回执? */ - None + let text = Text::build("value", "header", format!("{}", result_value_u64)) + .no_create_time() + .build(); + Some(NONObjectInfo::new( + text.desc().object_id(), + text.to_vec().unwrap(), + None, + )) }; let context = { /** * 执行请求的上下文,运算过程中可能有验证节点无法得到的上下文信息(比如时间戳,随机数) */ - None + Some(Vec::from(result_value_u64.to_le_bytes())) }; /** @@ -855,19 +865,20 @@ mod GroupDecService { .await?; log::info!( - "verify expect: prev-state: {:?}, {:?}/{}/{}, got: {:?}/{}/{}", + "verify expect: prev-state: {:?}, {:?}/{:?}/{:?}, got: {:?}/{:?}/{:?}", prev_state_id, execute_result.result_state_id, - execute_result.context.is_none(), - execute_result.receipt.is_none(), + execute_result.context.as_ref().map(|v| v.to_hex()), + execute_result.receipt.as_ref().map(|r| r.object_id), result.result_state_id, - result.context.is_none(), - result.receipt.is_none() + result.context.as_ref().map(|v| v.to_hex()), + result.receipt.as_ref().map(|r| r.object_id) ); let is_ok = execute_result.result_state_id == result.result_state_id - && execute_result.context.is_none() - && execute_result.receipt.is_none(); + && execute_result.context == result.context + && execute_result.receipt.as_ref().map(|r| r.object_id) + == result.receipt.as_ref().map(|r| r.object_id); if is_ok { Ok(()) @@ -1201,11 +1212,18 @@ async fn main_run() { ); let result = client.post_proposal(&proposal).await; + let result_text = result.as_ref().map(|obj| { + obj.as_ref().map(|obj| { + Text::raw_decode(obj.object_raw.as_slice()) + .map(|(txt, _)| txt.value().to_string()) + }) + }); log::info!( - "client {:?} post proposal {}, result: {:?}", + "client {:?} post proposal {}, result: {:?}, result-text: {:?}", local_name, proposal.desc().object_id(), - result.map(|o| o.map(|o| o.object_id)) + result.as_ref().map(|o| o.as_ref().map(|o| o.object_id)), + result_text ); }); From 3d62581f5db41290a26c627986c63b5ce6892d5b Mon Sep 17 00:00:00 2001 From: streetycat <34021271+streetycat@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:56:48 +0800 Subject: [PATCH 524/553] Buckyos (#123) * Add interface create_new_with_option for RootStateStub to add params(owner/dec) * Split the function AnyNamedObject::raw_decode to little. * Fix: send cache packages after tunnel connection * Fix: Wrong path detection causes dec app installation or startup error on windows --------- Co-authored-by: jing-git Co-authored-by: weiqiushi --- src/component/cyfs-base/src/objects/any.rs | 297 ++++++++++++--------- 1 file changed, 171 insertions(+), 126 deletions(-) diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index d0184f297..bea4f1650 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -343,6 +343,162 @@ impl AnyNamedObject { pub fn nonce(&self) -> &Option { match_any_obj!(self, o, { o.nonce() }, _chunk_id, { &None }) } + + fn raw_decode_device<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (device, buf) = Device::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/device error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Device(device)), + buf, + )) + } + + fn raw_decode_people<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (people, buf) = People::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/people error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::People(people)), + buf, + )) + } + + fn raw_decode_app_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::AppGroup(app_group)), + buf, + )) + } + + fn raw_decode_simple_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); + e + })?; + return Ok(( + AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), + buf, + )); + } + + fn raw_decode_org<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (org, buf) = Org::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/org error:{}", e); + e + })?; + return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); + } + + fn raw_decode_union_account<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/ua error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::UnionAccount(ua)), + buf, + )) + } + + fn raw_decode_file<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (file, buf) = File::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/file error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::File(file)), buf)) + } + + fn raw_decode_dir<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (dir, buf) = Dir::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/dir error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Dir(dir)), buf)) + } + + fn raw_decode_diff<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (diff, buf) = Diff::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/diff error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Diff(diff)), buf)) + } + + fn raw_decode_proof_of_service<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (prof, buf) = ProofOfService::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/prof error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::ProofOfService(prof)), + buf, + )) + } + + fn raw_decode_tx<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (tx, buf) = Tx::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/tx error:{}", e); + e + })?; + Ok((AnyNamedObject::Standard(StandardObject::Tx(tx)), buf)) + } + + fn raw_decode_action<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (action, buf) = Action::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/action error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Action(action)), + buf, + )) + } + + fn raw_decode_object_map<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (relation, buf) = ObjectMap::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/relation error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::ObjectMap(relation)), + buf, + )) + } + + fn raw_decode_contract<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (contract, buf) = Contract::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/contract error:{}", e); + e + })?; + Ok(( + AnyNamedObject::Standard(StandardObject::Contract(contract)), + buf, + )) + } + + fn raw_decode_custom<'de>( + buf: &'de [u8], + is_dec_app_object: bool, + ) -> Result<(Self, &'de [u8]), BuckyError> { + if is_dec_app_object { + // println!("is dec app object"); + + let (dec_obj, buf) = TypelessDECAppObject::raw_decode(buf)?; + Ok((AnyNamedObject::DECApp(dec_obj), buf)) + } else { + // println!("is core object"); + + let (core_obj, buf) = TypelessCoreObject::raw_decode(buf)?; + Ok((AnyNamedObject::Core(core_obj), buf)) + } + } } impl RawEncode for AnyNamedObject { @@ -375,137 +531,26 @@ impl<'de> RawDecode<'de> for AnyNamedObject { })?; match obj_type_info.obj_type_code() { - ObjectTypeCode::Device => { - let (device, buf) = Device::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/device error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Device(device)), - buf, - )); - } - ObjectTypeCode::People => { - let (people, buf) = People::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/people error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::People(people)), - buf, - )); - } - ObjectTypeCode::AppGroup => { - let (app_group, buf) = AppGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/app_group error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::AppGroup(app_group)), - buf, - )); - } - ObjectTypeCode::Group => { - let (group, buf) = Group::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/group error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Group(group)), buf)); - } - ObjectTypeCode::UnionAccount => { - let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/ua error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::UnionAccount(ua)), - buf, - )); - } + ObjectTypeCode::Device => Self::raw_decode_device(buf), + ObjectTypeCode::People => Self::raw_decode_people(buf), + ObjectTypeCode::AppGroup => Self::raw_decode_app_group(buf), + ObjectTypeCode::UnionAccount => Self::raw_decode_union_account(buf), ObjectTypeCode::Chunk => { unreachable!(); } - ObjectTypeCode::File => { - let (file, buf) = File::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/file error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::File(file)), buf)); - } - ObjectTypeCode::Dir => { - let (dir, buf) = Dir::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/dir error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Dir(dir)), buf)); - } - ObjectTypeCode::Diff => { - let (diff, buf) = Diff::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/diff error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Diff(diff)), buf)); - } - ObjectTypeCode::ProofOfService => { - let (prof, buf) = ProofOfService::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/prof error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::ProofOfService(prof)), - buf, - )); - } - ObjectTypeCode::Tx => { - let (tx, buf) = Tx::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/tx error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Tx(tx)), buf)); - } - ObjectTypeCode::Action => { - let (action, buf) = Action::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/action error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Action(action)), - buf, - )); - } - ObjectTypeCode::ObjectMap => { - let (relation, buf) = ObjectMap::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/relation error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::ObjectMap(relation)), - buf, - )); - } - ObjectTypeCode::Contract => { - let (contract, buf) = Contract::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/contract error:{}", e); - e - })?; - return Ok(( - AnyNamedObject::Standard(StandardObject::Contract(contract)), - buf, - )); - } + ObjectTypeCode::File => Self::raw_decode_file(buf), + ObjectTypeCode::Dir => Self::raw_decode_dir(buf), + ObjectTypeCode::Diff => Self::raw_decode_diff(buf), + ObjectTypeCode::ProofOfService => Self::raw_decode_proof_of_service(buf), + ObjectTypeCode::Tx => Self::raw_decode_tx(buf), + ObjectTypeCode::Action => Self::raw_decode_action(buf), + ObjectTypeCode::ObjectMap => Self::raw_decode_object_map(buf), + ObjectTypeCode::Contract => Self::raw_decode_contract(buf), ObjectTypeCode::Custom => { - return if obj_type_info.is_decapp_object() { - // println!("is dec app object"); - - let (dec_obj, buf) = TypelessDECAppObject::raw_decode(buf)?; - Ok((AnyNamedObject::DECApp(dec_obj), buf)) - } else { - // println!("is core object"); - - let (core_obj, buf) = TypelessCoreObject::raw_decode(buf)?; - Ok((AnyNamedObject::Core(core_obj), buf)) - }; + Self::raw_decode_custom(buf, obj_type_info.is_decapp_object()) } + ObjectTypeCode::SimpleGroup => Self::raw_decode_simple_group(buf), + ObjectTypeCode::Org => Self::raw_decode_org(buf), } } } From e8932a963388dde841ab7bfae056fbcbb46861cc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Mar 2023 17:01:58 +0800 Subject: [PATCH 525/553] Ensure the result-state is exist on the GroupState --- src/component/cyfs-base/src/objects/any.rs | 19 +- .../protos/group_bft_protocol.proto | 8 +- src/component/cyfs-group-lib/src/delegate.rs | 2 - .../cyfs-group-lib/src/group_manager.rs | 19 +- .../src/objects/group_command.rs | 24 - .../cyfs-group-lib/src/rpath_service.rs | 4 - .../src/consensus/hotstuff/hotstuff.rs | 929 +++++++++++------- .../cyfs-group/src/dec/group_events.rs | 6 - .../cyfs-group/src/network/protocol.rs | 2 +- .../cyfs-group/src/network/sender.rs | 12 +- .../cyfs-stack/src/stack/group_non_driver.rs | 4 +- src/tests/group-example/src/main.rs | 106 +- 12 files changed, 703 insertions(+), 432 deletions(-) diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index bea4f1650..355ded409 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -377,25 +377,17 @@ impl AnyNamedObject { )) } - fn raw_decode_simple_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { - let (simple_group, buf) = SimpleGroup::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/simple_group error:{}", e); + fn raw_decode_group<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { + let (simple_group, buf) = Group::raw_decode(buf).map_err(|e| { + log::error!("AnyNamedObject::raw_decode/group error:{}", e); e })?; return Ok(( - AnyNamedObject::Standard(StandardObject::SimpleGroup(simple_group)), + AnyNamedObject::Standard(StandardObject::Group(simple_group)), buf, )); } - fn raw_decode_org<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { - let (org, buf) = Org::raw_decode(buf).map_err(|e| { - log::error!("AnyNamedObject::raw_decode/org error:{}", e); - e - })?; - return Ok((AnyNamedObject::Standard(StandardObject::Org(org)), buf)); - } - fn raw_decode_union_account<'de>(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> { let (ua, buf) = UnionAccount::raw_decode(buf).map_err(|e| { log::error!("AnyNamedObject::raw_decode/ua error:{}", e); @@ -549,8 +541,7 @@ impl<'de> RawDecode<'de> for AnyNamedObject { ObjectTypeCode::Custom => { Self::raw_decode_custom(buf, obj_type_info.is_decapp_object()) } - ObjectTypeCode::SimpleGroup => Self::raw_decode_simple_group(buf), - ObjectTypeCode::Org => Self::raw_decode_org(buf), + ObjectTypeCode::Group => Self::raw_decode_group(buf), } } } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto index 2bfdd8d21..427e17681 100644 --- a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -54,10 +54,6 @@ message GroupCommandVerify { } message GroupCommandCommited { - bytes proposal = 1; // Proposal.to_vec() - optional bytes prev_state_id = 2; // ObjectId - optional bytes result_state_id = 3; // ObjectId - optional bytes receipt = 4; // NONObjectInfo.to_vec() - optional bytes context = 5; // Vec - bytes block = 6; // Block.to_vec() + optional bytes prev_state_id = 1; // ObjectId + bytes block = 2; // Block.to_vec() } diff --git a/src/component/cyfs-group-lib/src/delegate.rs b/src/component/cyfs-group-lib/src/delegate.rs index d678438c3..14adb523c 100644 --- a/src/component/cyfs-group-lib/src/delegate.rs +++ b/src/component/cyfs-group-lib/src/delegate.rs @@ -38,9 +38,7 @@ pub trait RPathDelegate: Sync + Send { async fn on_commited( &self, - proposal: &GroupProposal, prev_state_id: &Option, - execute_result: &ExecuteResult, block: &GroupConsensusBlock, object_map_processor: &dyn GroupObjectMapProcessor, ); diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index 07bae1f7a..c15200386 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -5,7 +5,10 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, RawConvertTo, RawDecode, }; -use cyfs_core::{CoreObjectType, DecAppId, GroupConsensusBlock, GroupProposalObject, GroupRPath}; +use cyfs_core::{ + CoreObjectType, DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupProposalObject, + GroupRPath, +}; use cyfs_lib::{ CyfsStackRequestorType, DeviceZoneCategory, HttpRequestorRef, NONObjectInfo, NONPostObjectInputResponse, RequestGlobalStatePath, RouterHandlerAction, RouterHandlerChain, @@ -343,7 +346,7 @@ impl GroupManager { } async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { - let rpath = cmd.proposal.rpath(); + let rpath = cmd.block.rpath(); let service = self .find_or_restart_service( rpath.group_id(), @@ -356,21 +359,13 @@ impl GroupManager { .map_err(|err| { log::warn!( "group on_commited find service {:?} failed, err: {:?}", - cmd.proposal.rpath(), + cmd.block.rpath(), err ); err })?; - let result = ExecuteResult { - result_state_id: cmd.result_state_id.take(), - receipt: cmd.receipt.take(), - context: cmd.context.take(), - }; - - service - .on_commited(&cmd.proposal, &cmd.prev_state_id, &result, &cmd.block) - .await; + service.on_commited(&cmd.prev_state_id, &cmd.block).await; Ok(()) } diff --git a/src/component/cyfs-group-lib/src/objects/group_command.rs b/src/component/cyfs-group-lib/src/objects/group_command.rs index 912ced438..0e441d98f 100644 --- a/src/component/cyfs-group-lib/src/objects/group_command.rs +++ b/src/component/cyfs-group-lib/src/objects/group_command.rs @@ -260,11 +260,7 @@ impl ProtobufTransform<&GroupCommandVerify> for super::codec::protos::GroupComma #[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransformType)] #[cyfs_protobuf_type(super::codec::protos::GroupCommandCommited)] pub struct GroupCommandCommited { - pub proposal: GroupProposal, pub prev_state_id: Option, - pub result_state_id: Option, - pub receipt: Option, - pub context: Option>, pub block: GroupConsensusBlock, } @@ -275,17 +271,7 @@ impl ProtobufTransform for GroupComm Some(prev_state_id) => Some(ObjectId::raw_decode(prev_state_id.as_slice())?.0), None => None, }, - proposal: GroupProposal::raw_decode(value.proposal.as_slice())?.0, - result_state_id: match value.result_state_id.as_ref() { - Some(result_state_id) => Some(ObjectId::raw_decode(result_state_id.as_slice())?.0), - None => None, - }, - receipt: match value.receipt.as_ref() { - Some(receipt) => Some(NONObjectInfo::raw_decode(receipt.as_slice())?.0), - None => None, - }, block: GroupConsensusBlock::raw_decode(&value.block.as_slice())?.0, - context: value.context, }) } } @@ -293,20 +279,10 @@ impl ProtobufTransform for GroupComm impl ProtobufTransform<&GroupCommandCommited> for super::codec::protos::GroupCommandCommited { fn transform(value: &GroupCommandCommited) -> BuckyResult { Ok(Self { - proposal: value.proposal.to_vec()?, prev_state_id: match value.prev_state_id.as_ref() { Some(prev_state_id) => Some(prev_state_id.to_vec()?), None => None, }, - result_state_id: match value.result_state_id.as_ref() { - Some(result_state_id) => Some(result_state_id.to_vec()?), - None => None, - }, - receipt: match value.receipt.as_ref() { - Some(receipt) => Some(receipt.to_vec()?), - None => None, - }, - context: value.context.clone(), block: value.block.to_vec()?, }) } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index d6aa6972d..74f113e3f 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -104,17 +104,13 @@ impl RPathService { pub(crate) async fn on_commited( &self, - proposal: &GroupProposal, prev_state_id: &Option, - execute_result: &ExecuteResult, block: &GroupConsensusBlock, ) { self.0 .delegate .on_commited( - proposal, prev_state_id, - execute_result, block, &GroupObjectMapProcessorImpl { stack: self.0.stack.clone(), diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 23e2152f1..e7f69f9a1 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,31 +1,38 @@ -use std::{collections::HashMap, sync::Arc, time::{SystemTime, Duration}}; +use std::{ + collections::HashMap, + fmt::format, + sync::Arc, + time::{Duration, SystemTime}, +}; use async_std::channel::{Receiver, Sender}; use cyfs_base::{ bucky_time_to_system_time, BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, - ObjectDesc, ObjectId, ObjectLink, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, - RsaCPUObjectSigner, SignatureSource, Signer, ObjectTypeCode, + ObjectDesc, ObjectId, ObjectLink, ObjectTypeCode, OwnerObjectDesc, RawConvertTo, RawDecode, + RawEncode, RsaCPUObjectSigner, SignatureSource, Signer, }; use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; -use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote, ExecuteResult}; -use cyfs_lib::{NONObjectInfo}; +use cyfs_group_lib::{ExecuteResult, HotstuffBlockQCVote, HotstuffTimeoutVote}; +use cyfs_lib::NONObjectInfo; use futures::FutureExt; use itertools::Itertools; use crate::{ - consensus::{synchronizer::Synchronizer}, dec_state::{StatePusher, CallReplyNotifier, CallReplyWaiter}, helper::Timer, Committee, - GroupStorage, HotstuffMessage, - PendingProposalConsumer, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, TIME_PRECISION, PROPOSAL_MAX_TIMEOUT, RPathEventNotifier, GroupObjectMapProcessor, + consensus::synchronizer::Synchronizer, + dec_state::{CallReplyNotifier, CallReplyWaiter, StatePusher}, + helper::Timer, + Committee, GroupObjectMapProcessor, GroupStorage, HotstuffMessage, PendingProposalConsumer, + RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, + HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, }; /** * TODO: generate empty block when the 'Node' is synchronizing - * + * * synchronizing: max_quorum_round - round > THRESHOLD */ @@ -80,20 +87,17 @@ impl Hotstuff { state_pusher.clone(), event_notifier, rpath.clone(), - proposal_result_notifier.clone() + proposal_result_notifier.clone(), ); - async_std::task::spawn(async move { - runner.run() - .await - }); + async_std::task::spawn(async move { runner.run().await }); Self { local_device_id, tx_message, state_pusher, rpath, - proposal_result_notifier + proposal_result_notifier, } } @@ -222,6 +226,7 @@ struct HotstuffRunner { high_qc: Option, // 最后一次通过投票的确认信息 tc: Option, max_quorum_round: u64, + max_quorum_height: u64, timer: Timer, // 定时器 vote_mgr: VoteMgr, network_sender: crate::network::Sender, @@ -267,17 +272,19 @@ impl HotstuffRunner { let last_qc = store.last_qc(); let last_tc = store.last_tc(); - let last_vote_round = store - .last_vote_round(); + let last_vote_round = store.last_vote_round(); let block_quorum_round = last_qc.as_ref().map_or(0, |qc| qc.round); let timeout_quorum_round = last_tc.as_ref().map_or(0, |tc| tc.round); let quorum_round = block_quorum_round.max(timeout_quorum_round); - let (max_round_block_round, max_round_qc_round) = max_round_block.as_ref().map_or((0, 0), |block| { - let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); - (block.round(), qc_round) - }); - let round = last_vote_round.max(quorum_round + 1).max(max_round_block_round); - + let (max_round_block_round, max_round_qc_round) = + max_round_block.as_ref().map_or((0, 0), |block| { + let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + (block.round(), qc_round) + }); + let round = last_vote_round + .max(quorum_round + 1) + .max(max_round_block_round); + log::debug!("[hotstuff] local: {:?}-{:?}-{}, startup with last_vote_round = {}, quorum_round = {}/{}, max_round_block_round = {}/{}" , rpath, local_device_id, round, last_vote_round, block_quorum_round, timeout_quorum_round, max_round_block_round, max_round_qc_round); @@ -291,7 +298,14 @@ impl HotstuffRunner { let vote_mgr = VoteMgr::new(committee.clone(), round); let init_timer_interval = store.group().consensus_interval(); - let max_height = store.header_height() + 2; + let max_quorum_round = round - 1; + let header_height = store.header_height(); + let max_height = header_height + 2; + let max_quorum_height = if header_height == 0 { + 0 + } else { + header_height + 1 + }; let synchronizer = Synchronizer::new( network_sender.clone(), @@ -323,7 +337,8 @@ impl HotstuffRunner { proposal_consumer, rx_proposal_waiter: None, tc, - max_quorum_round: round - 1, + max_quorum_round, + max_quorum_height, state_pusher, tx_block_gen, rx_block_gen, @@ -361,13 +376,17 @@ impl HotstuffRunner { */ Self::check_block_result_state(block)?; - log::debug!("[hotstuff] local: {:?}, handle_block-step2: {:?}", + log::debug!( + "[hotstuff] local: {:?}, handle_block-step2: {:?}", self, - block.block_id()); + block.block_id() + ); { // check leader - let leader_owner = self.get_leader_owner(Some(block.group_chunk_id()), block.round()).await?; + let leader_owner = self + .get_leader_owner(Some(block.group_chunk_id()), block.round()) + .await?; if &leader_owner != block.owner() { log::warn!("[hotstuff] local: {:?}, receive block({:?}) from invalid leader({}), expected {:?}", @@ -395,19 +414,24 @@ impl HotstuffRunner { let quorum_round = block.qc().as_ref().map_or(0, |qc| qc.round); self.update_max_quorum_round(quorum_round); + self.update_max_quorum_height(block.height() - 1); - log::debug!("[hotstuff] local: {:?}, handle_block-step3: {:?}", + log::debug!( + "[hotstuff] local: {:?}, handle_block-step3: {:?}", self, - block.block_id()); + block.block_id() + ); let prev_block = match self.check_block_linked(&block, remote).await { Ok(link) => link, - Err(err) => return err + Err(err) => return err, }; - log::debug!("[hotstuff] local: {:?}, handle_block-step4: {:?}", + log::debug!( + "[hotstuff] local: {:?}, handle_block-step4: {:?}", self, - block.block_id()); + block.block_id() + ); self.synchronizer.pop_link_from(block); @@ -471,33 +495,38 @@ impl HotstuffRunner { prev_block: &Option, remote: &ObjectId, ) -> BuckyResult<()> { - let mut prev_state_id = match prev_block - .as_ref() { - Some(prev_block) => { - let result_state_id = prev_block.result_state_id(); - if let Some(result_state_id) = result_state_id { - self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]).await?; - } - result_state_id.clone() - }, - None => None - }; + let mut prev_state_id = match prev_block.as_ref() { + Some(prev_block) => { + let result_state_id = prev_block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]) + .await?; + } + result_state_id.clone() + } + None => None, + }; for proposal_exe_info in block.proposals() { // 去重 if let Some(prev_block_id) = block.prev_block_id() { - if self.store + let is_already_finished = self.store .is_proposal_finished(&proposal_exe_info.proposal, prev_block_id) .await.map_err(|err| { log::warn!("[hotstuff] local: {:?}, check proposal {:?} in block {:?} with prev-block {:?} duplicate failed, {:?}." , self, proposal_exe_info.proposal, block.block_id(), prev_block_id, err); err - })? { - log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." + })?; + + if is_already_finished { + log::warn!("[hotstuff] local: {:?}, proposal {:?} in block {:?} with prev-block {:?} has finished before." , self, proposal_exe_info.proposal, block.block_id(), prev_block_id); - - return Err(BuckyError::new(BuckyErrorCode::ErrorState, "duplicate proposal")) - } + + return Err(BuckyError::new( + BuckyErrorCode::ErrorState, + "duplicate proposal", + )); + } } let proposal = proposals.get(&proposal_exe_info.proposal).unwrap(); @@ -509,9 +538,9 @@ impl HotstuffRunner { err })?; - + Some(receipt) - }, + } None => None, }; @@ -551,7 +580,11 @@ impl HotstuffRunner { Ok(()) } - async fn get_leader_owner(&self, group_chunk_id: Option<&ObjectId>, round: u64) -> BuckyResult { + async fn get_leader_owner( + &self, + group_chunk_id: Option<&ObjectId>, + round: u64, + ) -> BuckyResult { let leader = self .committee .get_leader(group_chunk_id, round) @@ -587,32 +620,37 @@ impl HotstuffRunner { match leader_owner { Some(owner) => Ok(owner), None => { - log::warn!("[hotstuff] local: {:?}, a owner must be set to the device {}", + log::warn!( + "[hotstuff] local: {:?}, a owner must be set to the device {}", self, leader ); - Err(BuckyError::new(BuckyErrorCode::InvalidTarget, "no owner for device")) + Err(BuckyError::new( + BuckyErrorCode::InvalidTarget, + "no owner for device", + )) } } } - async fn check_block_linked(&mut self, block: &GroupConsensusBlock, remote: ObjectId) -> Result, BuckyResult<()>> { - match self.store.block_linked(block).await - .map_err(|err| Err(err))? { - + async fn check_block_linked( + &mut self, + block: &GroupConsensusBlock, + remote: ObjectId, + ) -> Result, BuckyResult<()>> { + match self + .store + .block_linked(block) + .await + .map_err(|err| Err(err))? + { crate::storage::BlockLinkState::Expired => { - log::warn!( - "[hotstuff] local: {:?}, receive block expired.", - self - ); + log::warn!("[hotstuff] local: {:?}, receive block expired.", self); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } crate::storage::BlockLinkState::Duplicate => { - log::warn!( - "[hotstuff] local: {:?}, receive duplicate block.", - self - ); - Err( Err(BuckyError::new( + log::warn!("[hotstuff] local: {:?}, receive duplicate block.", self); + Err(Err(BuckyError::new( BuckyErrorCode::AlreadyExists, "duplicate block", ))) @@ -625,7 +663,8 @@ impl HotstuffRunner { ); // 顺序连接状态 - Self::check_empty_block_result_state_with_prev(block, &prev_block).map_err(|err| Err(err))?; + Self::check_empty_block_result_state_with_prev(block, &prev_block) + .map_err(|err| Err(err))?; Ok(prev_block) } crate::storage::BlockLinkState::Pending => { @@ -656,7 +695,10 @@ impl HotstuffRunner { "[hotstuff] local: {:?}, receive block in invalid branch.", self ); - Err( Err(BuckyError::new(BuckyErrorCode::Conflict, "conflict branch"))) + Err(Err(BuckyError::new( + BuckyErrorCode::Conflict, + "conflict branch", + ))) } } } @@ -665,17 +707,21 @@ impl HotstuffRunner { &mut self, block: &GroupConsensusBlock, remote: ObjectId, - proposals: &HashMap + proposals: &HashMap, ) -> BuckyResult<()> { /** * 验证过的块执行这个函数 */ - if let Err(err) = self.non_driver.put_block(block).await { - if err.code() != BuckyErrorCode::AlreadyExists && err.code() != BuckyErrorCode::NotChange { + if err.code() != BuckyErrorCode::AlreadyExists + && err.code() != BuckyErrorCode::NotChange + { log::warn!( "[hotstuff] local: {:?}, put new block {:?}/{}/{} to noc", - self, block.block_id(), block.height(), block.round() + self, + block.block_id(), + block.height(), + block.round() ); return Err(err); } @@ -683,14 +729,19 @@ impl HotstuffRunner { log::info!( "[hotstuff] local: {:?}, will push new block {:?}/{}/{} to storage", - self, block.block_id(), block.height(), block.round() + self, + block.block_id(), + block.height(), + block.round() ); let debug_identify = self.debug_identify(); let new_header_block = self.store.push_block(block.clone()).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, push verified block {:?} to storage failed {:?}", - debug_identify, block.block_id(), err + debug_identify, + block.block_id(), + err ); err @@ -698,59 +749,76 @@ impl HotstuffRunner { if let Some((header_block, old_header_block, _discard_blocks)) = new_header_block { let header_block = header_block.clone(); - self.on_new_block_commit(&header_block, &old_header_block, block).await; + self.on_new_block_commit(&header_block, &old_header_block, block) + .await; } match self.vote_mgr.add_voting_block(block).await { VoteThresholded::QC(qc) => { log::debug!( "[hotstuff] local: {:?}, the qc of block {:?} has received before", - self, block.block_id() + self, + block.block_id() ); return self.process_block_qc(qc, block).await; - }, + } VoteThresholded::TC(tc, max_high_qc_block) => { log::debug!( "[hotstuff] local: {:?}, the timeout-qc of block {:?} has received before", - self, block.block_id() + self, + block.block_id() ); return self .process_timeout_qc(tc, max_high_qc_block.as_ref()) - .await + .await; } VoteThresholded::None => {} } log::debug!( "[hotstuff] local: {:?}, process_block-step4 {:?}", - self, block.block_id() + self, + block.block_id() ); if block.round() != self.round { log::debug!( "[hotstuff] local: {:?}, not my round {}, expect {}", - self, block.round(), self.round + self, + block.round(), + self.round ); // 不是我的投票round return Ok(()); } if let Some(vote) = self.make_vote(block, proposals, &remote).await { - log::info!("[hotstuff] local: {:?}, vote to block {}, round: {}", - self, block.block_id(), block.round()); + log::info!( + "[hotstuff] local: {:?}, vote to block {}, round: {}", + self, + block.block_id(), + block.round() + ); - let next_leader = self.committee.get_leader(None, self.round + 1).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get next leader in round {} failed {:?}", - self, self.round + 1, err - ); + let next_leader = self + .committee + .get_leader(None, self.round + 1) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, get next leader in round {} failed {:?}", + self, + self.round + 1, + err + ); - err - })?; + err + })?; if self.local_device_id == next_leader { - self.handle_vote(&vote, Some(block), self.local_device_id).await?; + self.handle_vote(&vote, Some(block), self.local_device_id) + .await?; } else { self.network_sender .post_message( @@ -765,12 +833,28 @@ impl HotstuffRunner { Ok(()) } - async fn on_new_block_commit(&mut self, new_header_block: &GroupConsensusBlock, old_header_block: &Option, qc_qc_block: &GroupConsensusBlock) { + async fn on_new_block_commit( + &mut self, + new_header_block: &GroupConsensusBlock, + old_header_block: &Option, + qc_qc_block: &GroupConsensusBlock, + ) { log::info!( "[hotstuff] local: {:?}, new header-block {:?} committed, old: {:?}, qc-qc: {}", - self, new_header_block.block_id(), old_header_block.as_ref().map(|b| b.block_id()), qc_qc_block.block_id() + self, + new_header_block.block_id(), + old_header_block.as_ref().map(|b| b.block_id()), + qc_qc_block.block_id() ); + if new_header_block.height() <= self.max_quorum_height - 2 { + log::info!( + "[hotstuff] local: {:?}, new header-block {:?} committed, old: {:?}, qc-qc: {}, ignore notify history block({}/{})", + self, new_header_block.block_id(), old_header_block.as_ref().map(|b| b.block_id()), qc_qc_block.block_id(), new_header_block.height(), self.max_quorum_height + ); + return; + } + /** * 这里只清理已经提交的block包含的proposal * 已经执行过的待提交block包含的proposal在下次打包时候去重 @@ -779,7 +863,8 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, process_block-step1 {:?}", - self, qc_qc_block.block_id() + self, + qc_qc_block.block_id() ); let (_, qc_block) = self @@ -789,11 +874,13 @@ impl HotstuffRunner { .next() .expect("the pre-commit block must exist."); - self.notify_block_committed(new_header_block, old_header_block, qc_block).await; + self.notify_block_committed(new_header_block, old_header_block, qc_block) + .await; log::debug!( "[hotstuff] local: {:?}, process_block-step2 {:?}", - self, qc_qc_block.block_id() + self, + qc_qc_block.block_id() ); // notify by the block generator @@ -806,13 +893,16 @@ impl HotstuffRunner { // reply let futs = new_header_block.proposals().iter().map(|proposal_info| { let receipt = match proposal_info.receipt.as_ref() { - Some(receipt) => NONObjectInfo::raw_decode(receipt.as_slice()).map(|(receipt, remain)| { - assert_eq!(remain.len(), 0); - Some(receipt) - }), + Some(receipt) => { + NONObjectInfo::raw_decode(receipt.as_slice()).map(|(receipt, remain)| { + assert_eq!(remain.len(), 0); + Some(receipt) + }) + } None => Ok(None), }; - self.proposal_result_notifier.reply(&proposal_info.proposal, receipt) + self.proposal_result_notifier + .reply(&proposal_info.proposal, receipt) }); futures::future::join_all(futs).await; @@ -820,59 +910,42 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, process_block-step3 {:?}", - self, qc_qc_block.block_id() + self, + qc_qc_block.block_id() ); } - async fn notify_block_committed(&self, new_header: &GroupConsensusBlock, old_header_block: &Option, qc_block: &GroupConsensusBlock) -> BuckyResult<()> { - assert_eq!(new_header.prev_block_id(), old_header_block.as_ref().map(|b| b.block_id().object_id())); - - let mut pre_state_id = old_header_block - .as_ref() - .map_or(None, |b| b.result_state_id().clone()); + async fn notify_block_committed( + &self, + new_header: &GroupConsensusBlock, + old_header_block: &Option, + qc_block: &GroupConsensusBlock, + ) -> BuckyResult<()> { + assert_eq!( + new_header.prev_block_id(), + old_header_block.as_ref().map(|b| b.block_id().object_id()) + ); - for proposal in new_header.proposals() { - let proposal_obj = self - .non_driver - .get_proposal(&proposal.proposal, None) - .await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, get proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, new_header.block_id(), err - ); + if let Some(result_state_id) = new_header.result_state_id() { + self.make_sure_result_state(result_state_id, &[new_header.owner()]) + .await?; + } - err - })?; - let receipt = match proposal.receipt.as_ref() { - Some(receipt) => { - let (receipt, remain) = NONObjectInfo::raw_decode(receipt.as_slice()).map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, decode receipt of proposal {:?} in header-block {:?} before commit-notify failed {:?}", - self, proposal.proposal, new_header.block_id(), err - ); - err - })?; - assert_eq!(remain.len(), 0); - Some(receipt) + let prev_state_id = match old_header_block.as_ref() { + Some(old_header_block) => { + let result_state_id = old_header_block.result_state_id(); + if let Some(result_state_id) = result_state_id { + self.make_sure_result_state(result_state_id, &[old_header_block.owner()]) + .await?; } - None => None, - }; + result_state_id.clone() + } + None => None, + }; - self.event_notifier - .on_commited( - proposal_obj, - pre_state_id, - &ExecuteResult { - result_state_id: proposal.result_state.clone(), - receipt, - context: proposal.context.clone(), - }, - new_header.clone(), - ) - .await; - - pre_state_id = proposal.result_state.clone(); - } + self.event_notifier + .on_commited(prev_state_id, new_header.clone()) + .await; Ok(()) } @@ -880,8 +953,11 @@ impl HotstuffRunner { async fn process_qc(&mut self, qc: &Option) { let qc_round = qc.as_ref().map_or(0, |qc| qc.round); - log::debug!("[hotstuff] local: {:?}, process_qc round {}", - self, qc_round); + log::debug!( + "[hotstuff] local: {:?}, process_qc round {}", + self, + qc_round + ); self.advance_round(qc_round).await; self.update_high_qc(qc); @@ -889,15 +965,23 @@ impl HotstuffRunner { async fn advance_round(&mut self, round: u64) { if round < self.round { - log::debug!("[hotstuff] local: {:?}, round {} timeout expect {}", - self, round, self.round); + log::debug!( + "[hotstuff] local: {:?}, round {} timeout expect {}", + self, + round, + self.round + ); return; } - match self.committee.get_group(None).await { + match self.committee.get_group(None).await { Ok(group) => { - log::info!("[hotstuff] local: {:?}, update round from {} to {}", - self, self.round, round + 1); + log::info!( + "[hotstuff] local: {:?}, update round from {} to {}", + self, + self.round, + round + 1 + ); self.timer.reset(group.consensus_interval()); self.round = round + 1; @@ -917,8 +1001,12 @@ impl HotstuffRunner { if to_high_round > cur_high_round { self.high_qc = qc.clone(); - log::info!("[hotstuff] local: {:?}, update high-qc from {} to {}", - self, cur_high_round, to_high_round); + log::info!( + "[hotstuff] local: {:?}, update high-qc from {} to {}", + self, + cur_high_round, + to_high_round + ); } } @@ -928,6 +1016,12 @@ impl HotstuffRunner { } } + fn update_max_quorum_height(&mut self, quorum_height: u64) { + if quorum_height > self.max_quorum_height { + self.max_quorum_height = quorum_height; + } + } + async fn cleanup_proposal(&mut self, commited_block: &GroupConsensusBlock) -> BuckyResult<()> { let proposals = commited_block .proposals() @@ -935,24 +1029,38 @@ impl HotstuffRunner { .map(|proposal| proposal.proposal) .collect::>(); - log::debug!("[hotstuff] local: {:?}, remove proposals: {:?}", - self, proposals.len()); + log::debug!( + "[hotstuff] local: {:?}, remove proposals: {:?}", + self, + proposals.len() + ); self.proposal_consumer.remove_proposals(proposals).await } async fn notify_proposal_err(&self, proposal: &GroupProposal, err: BuckyError) { - log::debug!("[hotstuff] local: {:?}, proposal {} failed {:?}", - self, proposal.desc().object_id(), err); + log::debug!( + "[hotstuff] local: {:?}, proposal {} failed {:?}", + self, + proposal.desc().object_id(), + err + ); - self.proposal_result_notifier.reply(&proposal.desc().object_id(), Err(err.clone())).await; + self.proposal_result_notifier + .reply(&proposal.desc().object_id(), Err(err.clone())) + .await; self.state_pusher .notify_proposal_err(proposal.clone(), err) .await; } - async fn make_vote(&mut self, block: &GroupConsensusBlock, mut proposals: &HashMap, remote: &ObjectId) -> Option { + async fn make_vote( + &mut self, + block: &GroupConsensusBlock, + mut proposals: &HashMap, + remote: &ObjectId, + ) -> Option { if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -973,9 +1081,9 @@ impl HotstuffRunner { true } else if let Some(tc) = block.tc() { block.round() == tc.round + 1 - // && qc_round - // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() - // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others + // && qc_round + // >= tc.votes.iter().map(|v| v.high_qc_round).max().unwrap() + // maybe some block timeout happened, the leaders has the larger round QC, but not broadcast to others } else { false }; @@ -1003,10 +1111,10 @@ impl HotstuffRunner { block.prev_block_id() ); - return None - }, + return None; + } }, - None => None + None => None, }; match self.check_group_is_latest(block.group_chunk_id()).await { @@ -1023,7 +1131,11 @@ impl HotstuffRunner { // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 let mut proposal_temp: HashMap = HashMap::new(); if proposals.len() == 0 && block.proposals().len() > 0 { - match self.non_driver.load_all_proposals_for_block(block, &mut proposal_temp).await { + match self + .non_driver + .load_all_proposals_for_block(block, &mut proposal_temp) + .await + { Ok(_) => proposals = &proposal_temp, Err(err) => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", @@ -1031,7 +1143,7 @@ impl HotstuffRunner { block.block_id(), err ); - return None + return None; } } } else { @@ -1039,7 +1151,8 @@ impl HotstuffRunner { } if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", self, block.block_id(), ); @@ -1049,16 +1162,28 @@ impl HotstuffRunner { if proposals.len() != block.proposals().len() { let mut dup_proposals = block.proposals().clone(); dup_proposals.sort_unstable_by_key(|p| p.proposal); - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for proposals {:?} duplicate", self, block.block_id(), - dup_proposals.iter().group_by(|p| p.proposal).into_iter().map(|g| (g.0, g.1.count())).filter(|g| g.1 > 1).map(|g| g.0).collect_vec() + dup_proposals + .iter() + .group_by(|p| p.proposal) + .into_iter() + .map(|g| (g.0, g.1.count())) + .filter(|g| g.1 > 1) + .map(|g| g.0) + .collect_vec() ); return None; } - if let Err(err) = self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote).await { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + if let Err(err) = self + .check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote) + .await + { + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", self, block.block_id(), err @@ -1066,16 +1191,24 @@ impl HotstuffRunner { return None; } - log::debug!("[hotstuff] local: {:?}, make-vote before sign {}, round: {}", - self, block.block_id(), block.round()); + log::debug!( + "[hotstuff] local: {:?}, make-vote before sign {}, round: {}", + self, + block.block_id(), + block.round() + ); let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => { - log::debug!("[hotstuff] local: {:?}, make-vote after sign {}, round: {}", - self, block.block_id(), block.round()); - + log::debug!( + "[hotstuff] local: {:?}, make-vote after sign {}, round: {}", + self, + block.block_id(), + block.round() + ); + vote - }, + } Err(e) => { log::warn!( "[hotstuff] local: {:?}, signature for block-vote failed, block: {}, err: {}", @@ -1099,11 +1232,16 @@ impl HotstuffRunner { Some(vote) } - fn check_timestamp_precision(block: &GroupConsensusBlock, prev_block: Option<&GroupConsensusBlock>, proposals: &HashMap) -> bool { + fn check_timestamp_precision( + block: &GroupConsensusBlock, + prev_block: Option<&GroupConsensusBlock>, + proposals: &HashMap, + ) -> bool { let now = SystemTime::now(); let block_timestamp = bucky_time_to_system_time(block.named_object().desc().create_time()); if Self::calc_time_delta(now, block_timestamp) > TIME_PRECISION { - log::warn!("[hotstuff] block {} check timestamp {:?} failed with now {:?}", + log::warn!( + "[hotstuff] block {} check timestamp {:?} failed with now {:?}", block.block_id(), block_timestamp, now @@ -1112,31 +1250,36 @@ impl HotstuffRunner { false } else { if let Some(prev_block) = prev_block { - let prev_block_time = bucky_time_to_system_time(prev_block.named_object().desc().create_time()); + let prev_block_time = + bucky_time_to_system_time(prev_block.named_object().desc().create_time()); if let Ok(duration) = prev_block_time.duration_since(block_timestamp) { if duration > TIME_PRECISION { - log::warn!("[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", + log::warn!( + "[hotstuff] block {} check timestamp {:?} failed with prev-block {:?}", block.block_id(), block_timestamp, prev_block_time ); - return false + return false; } - } + } } for proposal in block.proposals() { let proposal_id = proposal.proposal; - let proposal = proposals.get(&proposal_id).expect("should load all proposals"); + let proposal = proposals + .get(&proposal_id) + .expect("should load all proposals"); let proposal_timestamp = bucky_time_to_system_time(proposal.desc().create_time()); if Self::calc_time_delta(block_timestamp, proposal_timestamp) > TIME_PRECISION { - log::warn!("[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", + log::warn!( + "[hotstuff] block {} check timestamp {:?} failed with proposal({:?}) {:?}", block.block_id(), block_timestamp, proposal_id, proposal_timestamp ); - return false + return false; } } true @@ -1163,7 +1306,9 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, receive timeout vote({}/{}/{:?}), local-round: {}", self, - vote.block_id, vote.round, vote.prev_block_id, + vote.block_id, + vote.round, + vote.prev_block_id, self.round ); return Ok(()); @@ -1173,7 +1318,9 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, verify vote({}/{}/{:?}) failed {:?}", self, - vote.block_id, vote.round, vote.prev_block_id, + vote.block_id, + vote.round, + vote.prev_block_id, err ); err @@ -1188,23 +1335,31 @@ impl HotstuffRunner { }; let is_prev_none = prev_block.is_none(); - let qc = self.vote_mgr.add_vote(vote.clone(), prev_block).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, add vote({}/{}/{:?}) prev-block: {} failed {:?}", - self, - vote.block_id, vote.round, vote.prev_block_id, - if is_prev_none {"None"} else {"Some"}, + let qc = self + .vote_mgr + .add_vote(vote.clone(), prev_block) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, add vote({}/{}/{:?}) prev-block: {} failed {:?}", + self, + vote.block_id, + vote.round, + vote.prev_block_id, + if is_prev_none { "None" } else { "Some" }, + err + ); err - ); - err - })?; + })?; if let Some((qc, block)) = qc { log::info!( "[hotstuff] local: {:?}, vote({}/{}/{:?}) prev-block: {} qc", self, - vote.block_id, vote.round, vote.prev_block_id, - if is_prev_none {"None"} else {"Some"} + vote.block_id, + vote.round, + vote.prev_block_id, + if is_prev_none { "None" } else { "Some" } ); self.process_block_qc(qc, &block).await?; @@ -1318,7 +1473,8 @@ impl HotstuffRunner { self.committee .verify_timeout(timeout, block.as_ref()) - .await.map_err(|err| { + .await + .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, handle_timeout: {:?}, verify failed {:?}", self, @@ -1334,7 +1490,8 @@ impl HotstuffRunner { let tc = self .vote_mgr .add_timeout(timeout.clone(), block.as_ref()) - .await.map_err(|err| { + .await + .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, handle_timeout: {:?}, check tc failed {:?}", self, @@ -1377,16 +1534,20 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); - let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", - self, - tc.round, - err - ); + let new_leader = self + .committee + .get_leader(None, self.round) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get new leader failed {:?}", + self, + tc.round, + err + ); - err - })?; + err + })?; if self.local_device_id == new_leader { self.generate_block(Some(tc)).await; Ok(()) @@ -1425,7 +1586,7 @@ impl HotstuffRunner { let max_high_qc = match max_high_qc { Some(max_high_qc) => max_high_qc, - None => return Ok(()) + None => return Ok(()), }; if tc.round < self.round { @@ -1436,12 +1597,13 @@ impl HotstuffRunner { ); return Ok(()); } - + if max_high_qc.high_qc_round >= tc.round { log::warn!( "[hotstuff] local: {:?}, handle_tc: {:?} ignore for high-qc round {} invalid", self, - tc.round, max_high_qc.high_qc_round + tc.round, + max_high_qc.high_qc_round ); return Ok(()); @@ -1476,15 +1638,18 @@ impl HotstuffRunner { Some(block) }; - self.committee.verify_tc(tc, block.as_ref()).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, handle_tc: {:?} verify tc failed {:?}", - self, - tc.round, + self.committee + .verify_tc(tc, block.as_ref()) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} verify tc failed {:?}", + self, + tc.round, + err + ); err - ); - err - })?; + })?; log::debug!("[hotstuff] local: {:?}, save-tc round {}", self, tc.round); @@ -1496,15 +1661,19 @@ impl HotstuffRunner { self.advance_round(tc.round).await; self.tc = Some(tc.clone()); - let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, handle_tc: {:?} get new leader failed {:?}", - self, - tc.round, + let new_leader = self + .committee + .get_leader(None, self.round) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} get new leader failed {:?}", + self, + tc.round, + err + ); err - ); - err - })?; + })?; if self.local_device_id == new_leader { self.generate_block(Some(tc.clone())).await; @@ -1513,10 +1682,7 @@ impl HotstuffRunner { } async fn local_timeout_round(&mut self) -> BuckyResult<()> { - log::debug!( - "[hotstuff] local: {:?}, local_timeout_round", - self, - ); + log::debug!("[hotstuff] local: {:?}, local_timeout_round", self,); let latest_group = match self.committee.get_group(None).await { Ok(group) => { @@ -1526,7 +1692,8 @@ impl HotstuffRunner { Err(err) => { log::warn!( "[hotstuff] local: {:?}, local_timeout_round get latest group failed {:?}", - self, err + self, + err ); self.timer.reset(HOTSTUFF_TIMEOUT_DEFAULT); @@ -1539,10 +1706,13 @@ impl HotstuffRunner { self.round, self.local_device_id, &self.signer, - ).await.map_err(|err| { + ) + .await + .map_err(|err| { log::warn!( "[hotstuff] local: {:?}, local_timeout_round create new timeout-vote failed {:?}", - self, err + self, + err ); err })?; @@ -1550,7 +1720,9 @@ impl HotstuffRunner { self.store.set_last_vote_round(self.round).await?; self.broadcast(HotstuffMessage::TimeoutVote(timeout.clone()), &latest_group); - self.tx_message.send((HotstuffMessage::TimeoutVote(timeout), self.local_device_id)).await; + self.tx_message + .send((HotstuffMessage::TimeoutVote(timeout), self.local_device_id)) + .await; Ok(()) } @@ -1561,19 +1733,32 @@ impl HotstuffRunner { log::debug!( "[hotstuff] local: {:?}, generate_block with qc {:?} and tc {:?}, now: {:?}", self, - self.high_qc.as_ref().map(|qc| format!("{}/{}/{:?}", qc.block_id, qc.round, qc.votes.iter().map(|v| v.voter).collect::>())), - tc.as_ref().map(|tc| format!("{}/{:?}", tc.round, tc.votes.iter().map(|v| v.voter).collect::>())), + self.high_qc.as_ref().map(|qc| format!( + "{}/{}/{:?}", + qc.block_id, + qc.round, + qc.votes.iter().map(|v| v.voter).collect::>() + )), + tc.as_ref().map(|tc| format!( + "{}/{:?}", + tc.round, + tc.votes.iter().map(|v| v.voter).collect::>() + )), now ); - let mut proposals = self.proposal_consumer.query_proposals().await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, generate_block query proposal failed {:?}", - self, + let mut proposals = self + .proposal_consumer + .query_proposals() + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, generate_block query proposal failed {:?}", + self, + err + ); err - ); - err - })?; + })?; proposals.sort_by(|left, right| left.desc().create_time().cmp(&right.desc().create_time())); @@ -1581,10 +1766,11 @@ impl HotstuffRunner { Some(qc) => { let prev_block = self.store.find_block_in_cache(&qc.block_id)?; if let Some(result_state_id) = prev_block.result_state_id() { - self.make_sure_result_state(result_state_id, &[prev_block.owner()]).await?; + self.make_sure_result_state(result_state_id, &[prev_block.owner()]) + .await?; } Some(prev_block) - }, + } None => None, }; let latest_group = self.committee.get_group(None).await.map_err(|err| { @@ -1593,7 +1779,7 @@ impl HotstuffRunner { self, err ); - + err })?; @@ -1626,25 +1812,29 @@ impl HotstuffRunner { } let create_time = bucky_time_to_system_time(proposal.desc().create_time()); - if Self::calc_time_delta(now, create_time) - > TIME_PRECISION - { + if Self::calc_time_delta(now, create_time) > TIME_PRECISION { // 时间误差太大 remove_proposals.push(proposal.desc().object_id()); time_adjust_proposals.push(proposal); continue; } - let ending = proposal.effective_ending() - .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), - |ending| bucky_time_to_system_time(ending)); + let ending = proposal + .effective_ending() + .map_or(now.checked_add(PROPOSAL_MAX_TIMEOUT).unwrap(), |ending| { + bucky_time_to_system_time(ending) + }); if now >= ending { remove_proposals.push(proposal.desc().object_id()); timeout_proposals.push(proposal); continue; } - match self.event_notifier.on_execute(proposal.clone(), result_state_id).await { + match self + .event_notifier + .on_execute(proposal.clone(), result_state_id) + .await + { Ok(exe_result) => { result_state_id = exe_result.result_state_id; executed_proposals.push((proposal, exe_result)); @@ -1656,7 +1846,8 @@ impl HotstuffRunner { }; } - self.notify_adjust_time_proposals(time_adjust_proposals).await; + self.notify_adjust_time_proposals(time_adjust_proposals) + .await; self.notify_timeout_proposals(timeout_proposals).await; self.notify_failed_proposals(failed_proposals).await; self.remove_pending_proposals(remove_proposals).await; @@ -1673,11 +1864,20 @@ impl HotstuffRunner { } let proposals_map = HashMap::from_iter( - executed_proposals.iter() - .map(|(proposal, _)| (proposal.desc().object_id(), proposal.clone())) + executed_proposals + .iter() + .map(|(proposal, _)| (proposal.desc().object_id(), proposal.clone())), ); - let block = self.package_block_with_proposals(executed_proposals, &latest_group, result_state_id, &prev_block, tc).await?; + let block = self + .package_block_with_proposals( + executed_proposals, + &latest_group, + result_state_id, + &prev_block, + tc, + ) + .await?; self.broadcast(HotstuffMessage::Block(block.clone()), &latest_group); self.tx_block_gen.send((block, proposals_map)).await; @@ -1691,10 +1891,17 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, generate_block timestamp err {:?}", self, - time_adjust_proposals.iter().map(|proposal| { - let desc = proposal.desc(); - (desc.object_id(), desc.owner(), bucky_time_to_system_time(desc.create_time())) - }).collect::>() + time_adjust_proposals + .iter() + .map(|proposal| { + let desc = proposal.desc(); + ( + desc.object_id(), + desc.owner(), + bucky_time_to_system_time(desc.create_time()), + ) + }) + .collect::>() ); } @@ -1713,15 +1920,21 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, generate_block timeout {:?}", self, - timeout_proposals.iter().map(|proposal| { - let desc = proposal.desc(); - ( - desc.object_id(), - desc.owner(), - bucky_time_to_system_time(desc.create_time()), - proposal.effective_ending().as_ref().map(|ending| bucky_time_to_system_time(*ending)) - ) - }).collect::>() + timeout_proposals + .iter() + .map(|proposal| { + let desc = proposal.desc(); + ( + desc.object_id(), + desc.owner(), + bucky_time_to_system_time(desc.create_time()), + proposal + .effective_ending() + .as_ref() + .map(|ending| bucky_time_to_system_time(*ending)), + ) + }) + .collect::>() ); } @@ -1740,14 +1953,13 @@ impl HotstuffRunner { log::warn!( "[hotstuff] local: {:?}, generate_block failed proposal {:?}", self, - failed_proposals.iter().map(|(proposal, err)| { - let desc = proposal.desc(); - ( - desc.object_id(), - desc.owner(), - err.clone() - ) - }).collect::>() + failed_proposals + .iter() + .map(|(proposal, err)| { + let desc = proposal.desc(); + (desc.object_id(), desc.owner(), err.clone()) + }) + .collect::>() ); } @@ -1771,12 +1983,13 @@ impl HotstuffRunner { .await; } - async fn package_block_with_proposals(&self, + async fn package_block_with_proposals( + &self, executed_proposals: Vec<(GroupProposal, ExecuteResult)>, group: &Group, result_state_id: Option, prev_block: &Option, - tc: Option + tc: Option, ) -> BuckyResult { let proposal_count = executed_proposals.len(); let proposals_param = executed_proposals @@ -1811,7 +2024,10 @@ impl HotstuffRunner { log::info!( "[hotstuff] local: {:?}, generate_block new block {}/{}/{}, with proposals: {}", self, - block.block_id(), block.height(), block.round(), proposal_count + block.block_id(), + block.height(), + block.round(), + proposal_count ); self.sign_block(&mut block).await.map_err(|err| { @@ -1858,7 +2074,9 @@ impl HotstuffRunner { let rpath = self.rpath.clone(); async_std::task::spawn(async move { - network_sender.broadcast(msg, rpath.clone(), targets.as_slice()).await + network_sender + .broadcast(msg, rpath.clone(), targets.as_slice()) + .await }); Ok(()) @@ -1880,24 +2098,26 @@ impl HotstuffRunner { ); will_wait_proposals = true - }, + } Some(pre_block) => { if pre_block.proposals().len() == 0 { match pre_block.prev_block_id() { Some(pre_pre_block_id) => { - let pre_pre_block = - match self.store.find_block_in_cache(pre_pre_block_id) { - Ok(pre_pre_block) => pre_pre_block, - Err(err) => { - log::warn!( + let pre_pre_block = match self + .store + .find_block_in_cache(pre_pre_block_id) + { + Ok(pre_pre_block) => pre_pre_block, + Err(err) => { + log::warn!( "[hotstuff] local: {:?}, new empty block will generate for find prev-block {} failed {:?}", self, pre_pre_block_id, err ); - return false; - } - }; + return false; + } + }; if pre_pre_block.proposals().len() == 0 { log::warn!( "[hotstuff] local: {:?}, new empty block will ignore for 2 prev-block({}/{}) is empty", @@ -1926,7 +2146,7 @@ impl HotstuffRunner { if will_wait_proposals { match self.proposal_consumer.wait_proposals().await { Ok(rx) => self.rx_proposal_waiter = Some((rx, self.round)), - _ => return false + _ => return false, } } @@ -1934,12 +2154,12 @@ impl HotstuffRunner { } async fn handle_proposal_waiting(&mut self) -> BuckyResult<()> { - log::debug!( - "[hotstuff] local: {:?}, handle_proposal_waiting", - self - ); + log::debug!("[hotstuff] local: {:?}, handle_proposal_waiting", self); - assert_eq!(self.committee.get_leader(None, self.round).await?, self.local_device_id); + assert_eq!( + self.committee.get_leader(None, self.round).await?, + self.local_device_id + ); self.generate_block(self.with_tc()).await } @@ -1983,58 +2203,111 @@ impl HotstuffRunner { Ok(latest_chunk_id.as_object_id() == group_chunk_id) } - async fn make_sure_result_state(&self, result_state_id: &ObjectId, remotes: &[&ObjectId]) -> BuckyResult<()> { + async fn make_sure_result_state( + &self, + result_state_id: &ObjectId, + remotes: &[&ObjectId], + ) -> BuckyResult<()> { // TODO: 需要一套通用的同步ObjectMap树的实现,这里缺少对于异常的处理 let obj_map_processor = self.store.get_object_map_processor(); + let local_trace_log = format!("{:?}", self); #[async_recursion::async_recursion] - async fn make_sure_sub_tree(root_id: &ObjectId, non_driver: crate::network::NONDriverHelper, remote: &ObjectId, obj_map_processor: &dyn GroupObjectMapProcessor) -> BuckyResult<()> { + async fn make_sure_sub_tree( + root_id: &ObjectId, + non_driver: crate::network::NONDriverHelper, + remote: &ObjectId, + obj_map_processor: &dyn GroupObjectMapProcessor, + local_trace_log: &str, + ) -> BuckyResult<()> { if root_id.is_data() { return Ok(()); } if non_driver.get_object(&root_id, None).await.is_ok() { // TODO: 可能有下级分支子树因为异常不齐全 + log::debug!( + "[hotstuff] {} make_sure_result_state {} already exist.", + local_trace_log, + root_id + ); return Ok(()); } - let obj = non_driver.get_object(root_id, Some(remote)).await.map_err(|err| { - log::warn!("get branch {} failed {:?}", root_id, err); - err - })?; + let obj = non_driver + .get_object(root_id, Some(remote)) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] {} get branch {} failed {:?}", + local_trace_log, + root_id, + err + ); + err + })?; match obj.object.as_ref() { Some(obj) if obj.obj_type_code() == ObjectTypeCode::ObjectMap => { - let single_op_env = obj_map_processor.create_single_op_env().await?; - single_op_env.load(root_id).await?; + let single_op_env = obj_map_processor.create_single_op_env().await.map_err(|err| { + log::warn!("[hotstuff] {} make_sure_result_state {} create_single_op_env failed {:?}.", local_trace_log, root_id, err); + err + })?; + single_op_env.load(root_id).await.map_err(|err| { + log::warn!( + "[hotstuff] {} make_sure_result_state {} load failed {:?}.", + local_trace_log, + root_id, + err + ); + err + })?; loop { let branchs = single_op_env.next(16).await?; for branch in branchs.list.iter() { let branch_id = match branch { - cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => match diff_map.1.altered.as_ref() { - Some(branch_id) => branch_id, - None => continue, - }, + cyfs_base::ObjectMapContentItem::DiffMap(diff_map) => { + match diff_map.1.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + } + } cyfs_base::ObjectMapContentItem::Map(map) => &map.1, - cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => match diff_set.altered.as_ref() { - Some(branch_id) => branch_id, - None => continue, - }, + cyfs_base::ObjectMapContentItem::DiffSet(diff_set) => { + match diff_set.altered.as_ref() { + Some(branch_id) => branch_id, + None => continue, + } + } cyfs_base::ObjectMapContentItem::Set(set) => set, }; - make_sure_sub_tree(branch_id, non_driver.clone(), remote, obj_map_processor).await?; + make_sure_sub_tree( + branch_id, + non_driver.clone(), + remote, + obj_map_processor, + local_trace_log, + ) + .await?; } if branchs.list.len() < 16 { - return Ok(()) + return Ok(()); } } - }, - _ => return Ok(()) + } + _ => return Ok(()), } } let mut result = Ok(()); for remote in remotes { - result = make_sure_sub_tree(result_state_id, self.non_driver.clone(), remote, obj_map_processor).await; + result = make_sure_sub_tree( + result_state_id, + self.non_driver.clone(), + remote, + obj_map_processor, + local_trace_log.as_str(), + ) + .await; if result.is_ok() { return result; } diff --git a/src/component/cyfs-group/src/dec/group_events.rs b/src/component/cyfs-group/src/dec/group_events.rs index a25accb19..5573cab44 100644 --- a/src/component/cyfs-group/src/dec/group_events.rs +++ b/src/component/cyfs-group/src/dec/group_events.rs @@ -109,17 +109,11 @@ impl RPathEventNotifier { pub async fn on_commited( &self, - proposal: GroupProposal, prev_state_id: Option, - execute_result: &ExecuteResult, block: GroupConsensusBlock, ) { let cmd = GroupCommandCommited { - proposal, prev_state_id, - result_state_id: execute_result.result_state_id.clone(), - receipt: execute_result.receipt.clone(), - context: execute_result.context.clone(), block, }; diff --git a/src/component/cyfs-group/src/network/protocol.rs b/src/component/cyfs-group/src/network/protocol.rs index 1f2a46a73..b6eec1177 100644 --- a/src/component/cyfs-group/src/network/protocol.rs +++ b/src/component/cyfs-group/src/network/protocol.rs @@ -461,7 +461,7 @@ impl RawEncode for HotstuffPackage { HotstuffPackage::SyncRequest(addr, min, max) => { buf[0] = 4; let buf = &mut buf[1..]; - encode_with_length(buf, addr, purpose, 2)?; + let buf = encode_with_length(buf, addr, purpose, 2)?; let buf = min.raw_encode(buf, purpose)?; max.raw_encode(buf, purpose) } diff --git a/src/component/cyfs-group/src/network/sender.rs b/src/component/cyfs-group/src/network/sender.rs index dcbc64a53..a33e09187 100644 --- a/src/component/cyfs-group/src/network/sender.rs +++ b/src/component/cyfs-group/src/network/sender.rs @@ -63,7 +63,17 @@ impl Sender { let mut buf = Vec::with_capacity(len); buf.resize(len, 0); let remain = pkg.raw_encode(buf.as_mut_slice(), &None).unwrap(); - assert_eq!(remain.len(), 0); + + assert_eq!( + remain.len(), + 0, + "[group-sender] {:?}-{} post group message to {:?} encode err, pkg: {:?}, len: {}", + pkg.rpath(), + self.local_device_id, + remote, + pkg, + buf.len() + ); log::debug!( "[group-sender] {:?}-{} post group message to {:?}, pkg: {:?}, len: {}", diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 7347a4c38..7613e3447 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -31,7 +31,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { - log::debug!( + log::info!( "get object {}, local: {}, from: {:?}", object_id, self.local_device_id, @@ -68,7 +68,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); - log::debug!( + log::info!( "put object {} with access {}, local: {}", obj.object_id, access, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 6bcc78920..7ededd629 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -575,10 +575,11 @@ mod GroupDecService { RPathService, }; use cyfs_lib::{ - CreateObjectMapOption, GlobalStatePathAccessItem, NONObjectInfo, NONPostObjectInputRequest, - NONPostObjectInputResponse, RequestGlobalStatePath, RequestSourceInfo, RouterHandlerAction, - RouterHandlerChain, RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, - RouterHandlerPostObjectResult, SharedCyfsStack, + CreateObjectMapOption, GlobalStatePathAccessItem, NONAPILevel, NONGetObjectInputRequest, + NONGetObjectOutputRequest, NONInputRequestCommon, NONObjectInfo, NONOutputRequestCommon, + NONPostObjectInputRequest, NONPostObjectInputResponse, RequestGlobalStatePath, + RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, + RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -598,6 +599,8 @@ mod GroupDecService { cyfs_stack.clone(), Box::new(GroupRPathDelegateFactory { local_name: local_name.clone(), + stack: cyfs_stack.clone(), + dec_id: dec_app_id.object_id().clone(), }), &cyfs_lib::CyfsStackRequestorType::Http, ) @@ -610,7 +613,11 @@ mod GroupDecService { .start_rpath_service( group_id, rpath.to_string(), - Box::new(MyRPathDelegate::new(local_name.to_string())), + Box::new(MyRPathDelegate::new( + local_name.to_string(), + cyfs_stack.clone(), + dec_app_id.object_id().clone(), + )), ) .await .unwrap(), @@ -687,6 +694,8 @@ mod GroupDecService { pub struct GroupRPathDelegateFactory { local_name: String, + stack: SharedCyfsStack, + dec_id: ObjectId, } impl GroupRPathDelegateFactory { @@ -712,7 +721,11 @@ mod GroupDecService { ) -> BuckyResult> { if self.is_accept(group_id, rpath, with_block) { // 如果接受,就提供该rpath的处理响应对象 - Ok(Box::new(MyRPathDelegate::new(self.local_name.clone()))) + Ok(Box::new(MyRPathDelegate::new( + self.local_name.clone(), + self.stack.clone(), + self.dec_id.clone(), + ))) } else { Err(BuckyError::new(BuckyErrorCode::Reject, "")) } @@ -721,14 +734,18 @@ mod GroupDecService { pub struct MyRPathDelegate { local_name: String, + stack: SharedCyfsStack, + dec_id: ObjectId, finished_proposals: Arc>>, } impl MyRPathDelegate { - pub fn new(local_name: String) -> Self { + pub fn new(local_name: String, stack: SharedCyfsStack, dec_id: ObjectId) -> Self { MyRPathDelegate { local_name, finished_proposals: Arc::new(Mutex::new(HashSet::new())), + stack, + dec_id, } } } @@ -918,19 +935,12 @@ mod GroupDecService { async fn on_commited( &self, - proposal: &GroupProposal, prev_state_id: &Option, - execute_result: &ExecuteResult, block: &GroupConsensusBlock, object_map_processor: &dyn GroupObjectMapProcessor, ) { // 提交到共识链上了,可能有些善后事宜 - let delta_buf = proposal.params().as_ref().unwrap().as_slice(); - let mut delta = [0u8; 8]; - delta.copy_from_slice(delta_buf); - let delta = u64::from_be_bytes(delta); - let prev_value = match prev_state_id { Some(prev_state_id) => { let state_op_env = object_map_processor @@ -958,14 +968,14 @@ mod GroupDecService { u64::from_be_bytes(prev_value) }); - let result_value = match execute_result.result_state_id { + let result_value = match block.result_state_id() { Some(result_state_id) => { let state_op_env = object_map_processor .create_sub_tree_op_env(None) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env - .load(result_state_id) + .load(result_state_id.clone()) .await .expect(format!("load {} failed", result_state_id).as_str()); state_op_env @@ -985,21 +995,53 @@ mod GroupDecService { u64::from_be_bytes(result_value) }); - let proposal_id = proposal.desc().object_id(); + let proposal_infos = + futures::future::join_all(block.proposals().iter().map(|proposal_info| async { + let proposal = self + .stack + .non_service() + .get_object(NONGetObjectOutputRequest { + common: NONOutputRequestCommon { + req_path: None, + source: None, + dec_id: Some(self.dec_id), + level: NONAPILevel::Router, + target: Some(block.owner().clone()), + flags: 0, + }, + object_id: proposal_info.proposal, + inner_path: None, + }) + .await + .unwrap(); + let proposal = proposal.object; + let (proposal, _remain) = + GroupProposal::raw_decode(proposal.object_raw.as_slice()).unwrap(); + + let delta_buf = proposal.params().as_ref().unwrap().as_slice(); + let mut delta = [0u8; 8]; + delta.copy_from_slice(delta_buf); + let delta = u64::from_be_bytes(delta); + (proposal_info.proposal, delta) + })) + .await; log::info!( - "proposal commited: height: {}/{}, delta: {}, result: {} -> {}, proposal: {}, block: {}, local: {}", + "proposal commited: height: {}/{}, delta: {:?}, result: {} -> {}, proposal: {:?}, block: {}, local: {}", block.height(), block.round(), - delta, + proposal_infos.iter().map(|(_, delta)| *delta).collect::>(), prev_value, result_value, - proposal_id, + proposal_infos.iter().map(|(id, _)| *id).collect::>(), block.block_id(), self.local_name ); - let is_new_finished = self.finished_proposals.lock().await.insert(proposal_id); - assert!(is_new_finished); + let mut finished_proposals = self.finished_proposals.lock().await; + block.proposals().iter().for_each(|proposal_info| { + let is_new_finished = finished_proposals.insert(proposal_info.proposal); + assert!(is_new_finished); + }); } } } @@ -1148,13 +1190,13 @@ async fn main_run() { member_group_mgrs.push(group_mgr); } - async_std::task::sleep(Duration::from_millis(10000)).await; + // async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 20usize; + let PROPOSAL_COUNT = 200usize; for i in 1..PROPOSAL_COUNT { let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); @@ -1187,13 +1229,7 @@ async fn main_run() { }; noc.put_object(req).await; proposals.push(proposal); - } - // futures::future::join_all(prepare_futures).await; - - log::info!("proposals prepared."); - - for i in 1..PROPOSAL_COUNT { let proposal = proposals.get(i - 1).unwrap().clone(); let stack = member_stacks.get(i % member_stacks.len()).unwrap(); let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); @@ -1227,12 +1263,18 @@ async fn main_run() { ); }); - if i % 10 == 0 { - async_std::task::sleep(Duration::from_millis(1000)).await; + if i % 28 == 0 { + async_std::task::sleep(Duration::from_millis(4000)).await; log::info!("will push new proposals, i: {}", i); } } + // futures::future::join_all(prepare_futures).await; + + log::info!("proposals prepared."); + + // for i in 1..PROPOSAL_COUNT {} + async_std::task::sleep(Duration::from_millis(20000)).await; // let client = admin_group_mgrs From 8057f4cf969a6edf4ea02e3fae2ff3895d828102 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Mar 2023 20:43:00 +0800 Subject: [PATCH 526/553] Timeout and retry to avoid the long-pending in NON --- .../src/consensus/hotstuff/hotstuff.rs | 36 +++++ .../cyfs-group/src/dec/group_manager.rs | 12 +- .../cyfs-group/src/network/non_driver.rs | 30 ++++- .../cyfs-stack/src/stack/group_non_driver.rs | 126 ++++++++++++++++-- src/tests/group-example/src/main.rs | 20 ++- 5 files changed, 206 insertions(+), 18 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e7f69f9a1..d69207622 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1061,6 +1061,12 @@ impl HotstuffRunner { mut proposals: &HashMap, remote: &ObjectId, ) -> Option { + log::debug!( + "[hotstuff] local: {:?} make vote {} step 0", + self, + block.block_id() + ); + if block.round() <= self.store.last_vote_round() { log::debug!("[hotstuff] local: {:?}, make vote ignore for timeouted block {}/{}, last vote roud: {}", self, block.block_id(), block.round(), self.store.last_vote_round()); @@ -1117,6 +1123,12 @@ impl HotstuffRunner { None => None, }; + log::debug!( + "[hotstuff] local: {:?} make vote {} step 1", + self, + block.block_id() + ); + match self.check_group_is_latest(block.group_chunk_id()).await { Ok(is_latest) if is_latest => {} _ => { @@ -1128,6 +1140,12 @@ impl HotstuffRunner { } } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 2", + self, + block.block_id() + ); + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 let mut proposal_temp: HashMap = HashMap::new(); if proposals.len() == 0 && block.proposals().len() > 0 { @@ -1150,6 +1168,12 @@ impl HotstuffRunner { assert_eq!(proposals.len(), block.proposals().len()); } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 3", + self, + block.block_id() + ); + if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { log::warn!( "[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", @@ -1178,6 +1202,12 @@ impl HotstuffRunner { return None; } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 4", + self, + block.block_id() + ); + if let Err(err) = self .check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote) .await @@ -1229,6 +1259,12 @@ impl HotstuffRunner { return None; } + log::debug!( + "[hotstuff] local: {:?} make vote {} step 5", + self, + block.block_id() + ); + Some(vote) } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 766da468e..f7e874cff 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -107,7 +107,11 @@ impl GroupManager { let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); let state_mgr = local_info.global_state_mgr.clone(); - let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let non_driver = NONDriverHelper::new( + local_info.non_driver.clone(), + dec_id.clone(), + local_device_id.object_id().clone(), + ); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), non_driver.clone(), @@ -386,7 +390,11 @@ impl GroupManager { let local_id = local_info.bdt_stack.local_const().owner().unwrap(); let local_device_id = local_info.bdt_stack.local_device_id(); let signer = local_info.signer.clone(); - let non_driver = NONDriverHelper::new(local_info.non_driver.clone(), dec_id.clone()); + let non_driver = NONDriverHelper::new( + local_info.non_driver.clone(), + dec_id.clone(), + local_device_id.object_id().clone(), + ); let root_state_mgr = local_info.global_state_mgr.clone(); let network_sender = crate::network::Sender::new( local_info.datagram.clone(), diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index c7f9e7d93..b8a2ac29b 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -38,14 +38,20 @@ pub(crate) struct NONDriverHelper { driver: Arc>, dec_id: ObjectId, cache: NONObjectCache, + local_device_id: ObjectId, } impl NONDriverHelper { - pub fn new(driver: Arc>, dec_id: ObjectId) -> Self { + pub fn new( + driver: Arc>, + dec_id: ObjectId, + local_device_id: ObjectId, + ) -> Self { Self { driver, dec_id, cache: NONObjectCache::new(), + local_device_id, } } @@ -239,14 +245,32 @@ impl NONDriverHelper { _ => panic!("invalid remote type: {:?}", block_owner.obj_type_code()), }; + log::debug!( + "{} load_all_proposals_for_block {} from {}", + self.local_device_id, + block.block_id(), + remote + ); + let load_futs = block.proposals().iter().map(|proposal| { let proposal_id = proposal.proposal; let non_driver = non_driver.clone(); let remote = remote.clone(); async move { - non_driver + let ret = non_driver .get_proposal(&proposal_id, Some(remote.object_id())) - .await + .await; + + log::debug!( + "{} load_all_proposals_for_block {}/{} from {}, ret: {:?}", + self.local_device_id, + block.block_id(), + proposal_id, + remote, + ret.as_ref().map(|_| ()) + ); + + ret } }); diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 7613e3447..5f00c6640 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -1,14 +1,17 @@ -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; -use cyfs_base::{AccessString, BuckyResult, ObjectId}; +use cyfs_base::{AccessString, BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; use cyfs_lib::{ DeviceZoneCategory, DeviceZoneInfo, NONAPILevel, NONGetObjectInputRequest, NONInputRequestCommon, NONObjectInfo, NONPostObjectInputRequest, NONPutObjectInputRequest, RequestGlobalStatePath, RequestProtocol, RequestSourceInfo, }; +use futures::FutureExt; use crate::{non::NONInputProcessor, non_api::NONService}; +const TIMEOUT_HALF: Duration = Duration::from_millis(2000); + pub struct GroupNONDriver { non_service: Arc, local_device_id: ObjectId, @@ -21,11 +24,8 @@ impl GroupNONDriver { local_device_id, } } -} -#[async_trait::async_trait] -impl cyfs_group::NONDriver for GroupNONDriver { - async fn get_object( + async fn get_object_impl( &self, dec_id: &ObjectId, object_id: &ObjectId, @@ -65,7 +65,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { .map(|resp| resp.object) } - async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + async fn put_object_impl(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { let access = AccessString::full(); log::info!( @@ -102,7 +102,7 @@ impl cyfs_group::NONDriver for GroupNONDriver { .map(|_| ()) } - async fn post_object( + async fn post_object_impl( &self, dec_id: &ObjectId, obj: NONObjectInfo, @@ -149,3 +149,113 @@ impl cyfs_group::NONDriver for GroupNONDriver { }) } } + +#[async_trait::async_trait] +impl cyfs_group::NONDriver for GroupNONDriver { + async fn get_object( + &self, + dec_id: &ObjectId, + object_id: &ObjectId, + from: Option<&ObjectId>, + ) -> BuckyResult { + let fut1 = match futures::future::select( + self.get_object_impl(dec_id, object_id, from).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!( + "group get object timeout (type={:?}) from {:?}, local: {:?}", + object_id.obj_type_code(), + from, + self.local_device_id + ); + + match futures::future::select( + self.get_object_impl(dec_id, object_id, from).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } + + async fn put_object(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { + let fut1 = match futures::future::select( + self.put_object_impl(dec_id, obj.clone()).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!( + "group put object timeout (type={:?}/{:?}), local: {:?}", + obj.object_id.obj_type_code(), + obj.object.as_ref().map(|o| o.obj_type()), + self.local_device_id + ); + + match futures::future::select( + self.put_object_impl(dec_id, obj).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } + + async fn post_object( + &self, + dec_id: &ObjectId, + obj: NONObjectInfo, + to: Option<&ObjectId>, + ) -> BuckyResult> { + let fut1 = match futures::future::select( + self.post_object_impl(dec_id, obj.clone(), to).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!( + "group post object timeout (type={:?}/{:?}) to {:?}, local: {:?}", + obj.object_id.obj_type_code(), + obj.object.as_ref().map(|o| o.obj_type()), + to, + self.local_device_id + ); + + match futures::future::select( + self.post_object_impl(dec_id, obj, to).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } +} diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 7ededd629..752e9c4ac 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -578,8 +578,9 @@ mod GroupDecService { CreateObjectMapOption, GlobalStatePathAccessItem, NONAPILevel, NONGetObjectInputRequest, NONGetObjectOutputRequest, NONInputRequestCommon, NONObjectInfo, NONOutputRequestCommon, NONPostObjectInputRequest, NONPostObjectInputResponse, RequestGlobalStatePath, - RequestSourceInfo, RouterHandlerAction, RouterHandlerChain, RouterHandlerManagerProcessor, - RouterHandlerPostObjectRequest, RouterHandlerPostObjectResult, SharedCyfsStack, + RequestSourceInfo, RootStateOpEnvAccess, RouterHandlerAction, RouterHandlerChain, + RouterHandlerManagerProcessor, RouterHandlerPostObjectRequest, + RouterHandlerPostObjectResult, SharedCyfsStack, }; use cyfs_util::EventListenerAsyncRoutine; @@ -758,7 +759,10 @@ mod GroupDecService { object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { let state_op_env = object_map_processor - .create_sub_tree_op_env(None) + .create_sub_tree_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) .await .expect(format!("create_sub_tree_op_env failed").as_str()); let prev_value = match prev_state_id { @@ -944,7 +948,10 @@ mod GroupDecService { let prev_value = match prev_state_id { Some(prev_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env(None) + .create_sub_tree_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env @@ -971,7 +978,10 @@ mod GroupDecService { let result_value = match block.result_state_id() { Some(result_state_id) => { let state_op_env = object_map_processor - .create_sub_tree_op_env(None) + .create_sub_tree_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) .await .expect(format!("create_sub_tree_op_env failed").as_str()); state_op_env From 000a0422e27c616f557451d6f6af93ab60aa24a0 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 16 Mar 2023 20:44:07 +0800 Subject: [PATCH 527/553] Rebuild result-state by DEC.on_verify when it's download from remote failed. --- .../src/consensus/hotstuff/hotstuff.rs | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index d69207622..2d416c357 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1074,11 +1074,25 @@ impl HotstuffRunner { return None; } + let mut only_rebuild_result_state = false; if self.max_quorum_round >= self.round { - log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", - self, block.block_id(), block.round(), self.max_quorum_round, self.round); + if let Some(result_state_id) = block.result_state_id() { + if self + .make_sure_result_state(result_state_id, &[block.owner(), remote]) + .await + .is_err() + { + // download from remote failed, we need to calcute the result-state by the DEC.on_verify + only_rebuild_result_state = true; + } + } - return None; + if !only_rebuild_result_state { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{}.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + + return None; + } } // round只能逐个递增 @@ -1129,14 +1143,16 @@ impl HotstuffRunner { block.block_id() ); - match self.check_group_is_latest(block.group_chunk_id()).await { - Ok(is_latest) if is_latest => {} - _ => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", - self, - block.block_id()); + if !only_rebuild_result_state { + match self.check_group_is_latest(block.group_chunk_id()).await { + Ok(is_latest) if is_latest => {} + _ => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", + self, + block.block_id()); - return None; + return None; + } } } @@ -1146,7 +1162,6 @@ impl HotstuffRunner { block.block_id() ); - // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 let mut proposal_temp: HashMap = HashMap::new(); if proposals.len() == 0 && block.proposals().len() > 0 { match self @@ -1174,7 +1189,10 @@ impl HotstuffRunner { block.block_id() ); - if !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) { + // 时间和本地误差太大,不签名,打包的proposal时间和block时间差距太大,也不签名 + if !only_rebuild_result_state + && !Self::check_timestamp_precision(block, prev_block.as_ref(), proposals) + { log::warn!( "[hotstuff] local: {:?}, make vote to block {} ignore for timestamp mismatch", self, @@ -1183,7 +1201,7 @@ impl HotstuffRunner { return None; } - if proposals.len() != block.proposals().len() { + if !only_rebuild_result_state && proposals.len() != block.proposals().len() { let mut dup_proposals = block.proposals().clone(); dup_proposals.sort_unstable_by_key(|p| p.proposal); log::warn!( @@ -1228,6 +1246,12 @@ impl HotstuffRunner { block.round() ); + if only_rebuild_result_state { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{} rebuild only.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + return None; + } + let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => { log::debug!( From 4c9270f6f7a56d142e45b72db2ba2e126d2a4f99 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 17 Mar 2023 20:58:11 +0800 Subject: [PATCH 528/553] Add signature for desc --- .../cyfs-stack/src/resolver/device_manager.rs | 3 ++- src/tests/group-example/src/main.rs | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 97e822c31..7deeb0083 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -128,6 +128,7 @@ impl DeviceInfoManagerImpl { object_id: &ObjectId, object: &Arc, ) -> BuckyResult<()> { + // TODO: 先验证所有成员签名,但这跟Group的变更策略有关,最终可能要跟链上比对才能验证,因为如果Group变更只需要部分成员签名,这将导致Group上只携带部分成员的签名 if object_id.obj_type_code() != ObjectTypeCode::Group { let msg = format!( "verify object own's body sign by owner failed for expect group, id = {}", @@ -181,7 +182,7 @@ impl DeviceInfoManagerImpl { let singer_obj_any = signer_obj.object.take(); let req = VerifyObjectInnerRequest { - sign_type: VerifySignType::Body, + sign_type: VerifySignType::Both, object: ObjectInfo { object_id: object_id.clone(), object: object.clone(), diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 752e9c4ac..880732884 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -197,6 +197,7 @@ mod Common { log::info!("create group: {:?}", group.desc().object_id()); + let desc_hash = group.desc().raw_hash_value().unwrap(); let body_hash = group.body().as_ref().unwrap().raw_hash_value().unwrap(); let signers = [admins, members].concat(); signers @@ -205,6 +206,17 @@ mod Common { let signer = RsaCPUObjectSigner::new(private_key.public(), private_key.clone()); async_std::task::block_on(async move { + let desc_signature = signer + .sign( + desc_hash.as_slice(), + &cyfs_base::SignatureSource::Object(ObjectLink { + obj_id: owner.desc().object_id(), + obj_owner: None, + }), + ) + .await + .unwrap(); + let body_signature = signer .sign( body_hash.as_slice(), @@ -215,10 +227,13 @@ mod Common { ) .await .unwrap(); - body_signature + (desc_signature, body_signature) }) }) - .for_each(|signature| group.signs_mut().push_body_sign(signature)); + .for_each(|(desc_signature, body_signature)| { + group.signs_mut().push_desc_sign(desc_signature); + group.signs_mut().push_body_sign(body_signature); + }); group } From 06f66fb1bed561a61d8e3a30ba73ec6e9f7db961 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 8 Apr 2023 16:40:21 +0800 Subject: [PATCH 529/553] Remove fields for rights in `Group`. --- .../protos/standard_objects-permission.proto | 115 -------- .../cyfs-base/protos/standard_objects.proto | 59 +--- src/component/cyfs-base/src/objects/group.rs | 262 ++---------------- src/component/cyfs-chunk-lib/src/chunk.rs | 32 --- .../cyfs-core/protos/core_objects.proto | 2 +- .../cyfs-core/src/group/group_blob.rs | 44 +++ .../src/group/group_consensus_block.rs | 18 +- src/component/cyfs-core/src/group/mod.rs | 2 + .../src/objects/group_update_proposal.rs | 53 ++-- src/component/cyfs-group/Cargo.toml | 1 - .../src/consensus/hotstuff/hotstuff.rs | 53 ++-- .../consensus/synchronizer/synchronizer.rs | 2 +- .../src/consensus/vote/committee.rs | 30 +- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 4 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/rpath_service.rs | 1 - .../src/dec_state/dec_state_requestor.rs | 2 +- .../src/dec_state/dec_state_synchronizer.rs | 18 +- .../cyfs-group/src/dec_state/state_pusher.rs | 22 +- src/component/cyfs-group/src/helper/timer.rs | 2 - .../cyfs-group/src/network/listener.rs | 2 +- .../cyfs-group/src/network/non_driver.rs | 14 +- .../cyfs-group/src/storage/group_storage.rs | 24 +- src/tests/group-example/src/main.rs | 2 - 24 files changed, 182 insertions(+), 583 deletions(-) delete mode 100644 src/component/cyfs-base/protos/standard_objects-permission.proto create mode 100644 src/component/cyfs-core/src/group/group_blob.rs diff --git a/src/component/cyfs-base/protos/standard_objects-permission.proto b/src/component/cyfs-base/protos/standard_objects-permission.proto deleted file mode 100644 index 09f9e3684..000000000 --- a/src/component/cyfs-base/protos/standard_objects-permission.proto +++ /dev/null @@ -1,115 +0,0 @@ -syntax="proto3"; - -// contract -message ContractBodyContent { - bytes data = 1; -} - -// device -message DeviceBodyContent { - repeated bytes endpoints = 1; - repeated bytes sn_list = 2; - repeated bytes passive_pn_list = 3; - optional string name = 4; - optional uint32 bdt_version = 5; -} - -// dir -message DirBodyContent { - enum Type { - Chunk = 0; - ObjList = 1; - } - Type type = 1; - optional bytes chunk_id = 2; - - // 使用list编码hash_map - message ObjItem { - bytes obj_id = 1; - bytes value = 2; - } - repeated ObjItem obj_list = 3; -} - -// file -message ChunkList { - enum Type { - ChunkInList = 0; - ChunkInFile = 1; - ChunkInBundle = 2; - } - enum HashMethod { - Serial = 0; - } - - Type type = 1; - repeated bytes chunk_id_list = 2; - bytes file_id = 3; - optional HashMethod hash_method = 4; -} - -message FileBodyContent { - ChunkList chunk_list = 1; -} - -// people -message PeopleBodyContent { - repeated bytes ood_list = 1; - optional string name = 2; - optional bytes icon = 3; - optional string ood_work_mode = 4; -} - -message GroupMember { - bytes id = 1; - string title = 2; -} - -message CommonGroupBodyContent { - string name = 1; - optional bytes icon = 2; - string description = 3; - - repeated GroupMember members = 4; - - repeated bytes ood_list = 5; - - optional bytes prev_version = 6; - uint64 version_num = 7; -} - -// simple_group -message SimpleGroupDescContent { - bytes unique_id = 1; - bytes founder_id = 2; - repeated GroupMember admins = 3; -} - -message SimpleGroupBodyContent { - CommonGroupBodyContent common = 1; -} - -// org -message OrgDescContent { - bytes unique_id = 1; - bytes founder_id = 2; -} - -message OrgBodyContent { - repeated GroupMember admins = 1; - CommonGroupBodyContent common = 2; -} - -// tx -message TxBodyContent { - bytes data = 1; -} - -// proof_of_service -message ProofData { - bytes data = 1; -} - -message ProofOfServiceBodyContent { - ProofData data = 1; -} \ No newline at end of file diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index 4a9714958..a363ec57a 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -63,39 +63,6 @@ message PeopleBodyContent { message GroupMember { bytes id = 1; string title = 2; - string role = 3; // for acl - uint64 shares = 4; -} - -message GroupMethodACL { - string name = 1; - - // target - optional bytes target_dec_id = 2; - optional string rpath = 3; - - double min_support_percent = 4; - string permissions = 5; // ACL-String -} - -message GroupRoleACL { - string name = 1; - - // target - optional bytes target_dec_id = 2; - optional string rpath = 3; - string method = 4; - - double right_percent = 5; - bool is_operator = 6; - string permissions = 7; // ACL-String -} - -message GroupJoinSignature { - bytes signature = 1; // Sign(member_id, group_id, hash, is_admin) - bytes member_id = 2; - bool is_admin = 4; - bytes hash = 5; // Hash(Encode(Group)) } message CommonGroupBodyContent { @@ -105,24 +72,10 @@ message CommonGroupBodyContent { repeated GroupMember members = 4; - uint64 total_equity = 5; - - // acl - repeated GroupMethodACL method_acls = 6; - repeated GroupRoleACL role_acls = 7; - - repeated bytes ood_list = 8; // 1/0 for every member/admin - - optional uint64 history_block_max = 9; - optional uint64 history_block_lifespan = 10; - optional uint64 consensus_interval = 11; // ms - - repeated bytes revoked_conclusions = 12; - - uint64 version = 13; - - // TODO: 这个Group的签名准备放到Group信息变更的提案里 - repeated GroupJoinSignature join_signatures = 14; // signature for every member/admin + repeated bytes ood_list = 5; + + optional bytes prev_blob_id = 6; + uint64 version = 7; } // simple_group @@ -130,7 +83,6 @@ message SimpleGroupDescContent { bytes unique_id = 1; bytes founder_id = 2; repeated GroupMember admins = 3; - uint32 conclusion_limit = 4; // the admins can make any conclusion with the signatures more than ${conclusion_limit} } message SimpleGroupBodyContent { @@ -145,8 +97,7 @@ message OrgDescContent { message OrgBodyContent { repeated GroupMember admins = 1; - optional bytes token_contract = 2; - CommonGroupBodyContent common = 3; + CommonGroupBodyContent common = 2; } // tx diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 5c8cda714..29aee5849 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -1,7 +1,6 @@ use crate::codec as cyfs_base; use crate::*; -use std::collections::HashSet; use std::convert::TryFrom; pub enum GroupMemberScope { @@ -72,6 +71,10 @@ impl GroupBodyContent { self.common().version } + pub fn prev_blob_id(&self) -> &Option { + &self.common().prev_blob_id + } + fn common(&self) -> &CommonGroupBodyContent { match self { GroupBodyContent::Org(body) => &body.common, @@ -94,8 +97,6 @@ pub type GroupDesc = NamedObjectDesc; pub type GroupId = NamedObjectId; pub type Group = NamedObjectBase; -pub const GROUP_DEFAULT_CONSENSUS_INTERVAL: u64 = 5000; // default 5000 ms - impl GroupDesc { pub fn group_id(&self) -> GroupId { GroupId::try_from(self.calculate_id()).unwrap() @@ -106,12 +107,10 @@ impl Group { pub fn new_simple_group( founder_id: ObjectId, admins: Vec, - conclusion_limit: Option, area: Area, ) -> GroupBuilder { let desc_content = SimpleGroupDescContent { unique_id: UniqueId::create_with_random(), - conclusion_limit: conclusion_limit.map_or((admins.len() as u32 >> 1) + 1, |n| n), admins, founder_id, }; @@ -221,19 +220,13 @@ impl Group { self.common_mut().version = version; } - pub fn consensus_interval(&self) -> u64 { - let interval = self.common().consensus_interval; - if interval == 0 { - GROUP_DEFAULT_CONSENSUS_INTERVAL - } else { - interval - } + pub fn prev_blob_id(&self) -> &Option { + &self.common().prev_blob_id } - pub fn set_consensus_interval(&mut self, interval: u64) { - self.common_mut().consensus_interval = interval; + pub fn set_prev_blob_id(&mut self, prev_blob_id: Option) { + self.common_mut().prev_blob_id = prev_blob_id; } - // pub fn join_member( // &self, // member_id: &ObjectId, @@ -387,8 +380,6 @@ impl Group { pub struct GroupMember { pub id: ObjectId, pub title: String, - pub role: String, - pub shares: u64, } impl GroupMember { @@ -396,8 +387,6 @@ impl GroupMember { GroupMember { id, title: "".to_string(), - role: "".to_string(), - shares: 0, } } } @@ -409,8 +398,6 @@ impl TryFrom for GroupMember { let ret = Self { id: ProtobufCodecHelper::decode_buf(value.id)?, title: value.title, - role: value.role, - shares: value.shares, }; Ok(ret) @@ -425,159 +412,6 @@ impl TryFrom<&GroupMember> for protos::GroupMember { ret.id = value.id.to_vec()?; ret.title = value.title.clone(); - ret.role = value.role.clone(); - ret.shares = value.shares; - - Ok(ret) - } -} - -#[derive(Clone, Debug)] -pub struct GroupMethodACL { - pub name: String, - pub target_dec_id: Option, - pub rpath: Option, - pub min_support_percent: f64, - pub permissions: String, // ACL-String -} - -impl TryFrom for GroupMethodACL { - type Error = BuckyError; - - fn try_from(mut value: protos::GroupMethodACL) -> BuckyResult { - let ret = Self { - name: value.take_name(), - target_dec_id: if value.has_target_dec_id() { - Some(ProtobufCodecHelper::decode_buf(value.take_target_dec_id())?) - } else { - None - }, - rpath: if value.has_rpath() { - Some(value.take_rpath()) - } else { - None - }, - min_support_percent: value.min_support_percent, - permissions: value.take_permissions(), // ACL-String - }; - - Ok(ret) - } -} - -impl TryFrom<&GroupMethodACL> for protos::GroupMethodACL { - type Error = BuckyError; - - fn try_from(value: &GroupMethodACL) -> BuckyResult { - let mut ret = Self::new(); - - ret.name = value.name.clone(); - if let Some(dec_id) = &value.target_dec_id { - ret.set_target_dec_id(dec_id.to_vec()?); - } - if let Some(rpath) = &value.rpath { - ret.set_rpath(rpath.clone()); - } - ret.min_support_percent = value.min_support_percent; - ret.permissions = value.permissions.clone(); - - Ok(ret) - } -} - -#[derive(Clone, Debug)] -pub struct GroupRoleACL { - pub name: String, - pub target_dec_id: Option, - pub rpath: Option, - pub method: String, - - pub right_percent: f64, - pub is_operator: bool, - pub permissions: String, // ACL-String -} - -impl TryFrom for GroupRoleACL { - type Error = BuckyError; - - fn try_from(mut value: protos::GroupRoleACL) -> BuckyResult { - let ret = Self { - name: value.take_name(), - target_dec_id: if value.has_target_dec_id() { - Some(ProtobufCodecHelper::decode_buf(value.take_target_dec_id())?) - } else { - None - }, - rpath: if value.has_rpath() { - Some(value.take_rpath()) - } else { - None - }, - method: value.take_method(), - right_percent: value.right_percent, - is_operator: value.is_operator, - permissions: value.take_permissions(), // ACL-String - }; - - Ok(ret) - } -} - -impl TryFrom<&GroupRoleACL> for protos::GroupRoleACL { - type Error = BuckyError; - - fn try_from(value: &GroupRoleACL) -> BuckyResult { - let mut ret = Self::new(); - - ret.set_name(value.name.clone()); - if let Some(dec_id) = &value.target_dec_id { - ret.set_target_dec_id(dec_id.to_vec()?); - } - if let Some(rpath) = &value.rpath { - ret.set_rpath(rpath.clone()); - } - ret.method = value.method.clone(); - ret.right_percent = value.right_percent; - ret.is_operator = value.is_operator; - ret.permissions = value.permissions.clone(); - - Ok(ret) - } -} - -#[derive(Clone, Debug)] -pub struct GroupJoinSignature { - signature: Signature, - member_id: ObjectId, - is_admin: bool, - hash: HashValue, -} - -impl TryFrom for GroupJoinSignature { - type Error = BuckyError; - - fn try_from(value: protos::GroupJoinSignature) -> BuckyResult { - let ret = Self { - signature: ProtobufCodecHelper::decode_buf(value.signature)?, - member_id: ProtobufCodecHelper::decode_buf(value.member_id)?, - is_admin: value.is_admin, - hash: ProtobufCodecHelper::decode_buf(value.hash)?, - }; - - Ok(ret) - } -} - -impl TryFrom<&GroupJoinSignature> for protos::GroupJoinSignature { - type Error = BuckyError; - - fn try_from(value: &GroupJoinSignature) -> BuckyResult { - let mut ret = Self::new(); - - ret.signature = value.signature.to_vec()?; - ret.member_id = value.member_id.to_vec()?; - ret.is_admin = value.is_admin; - ret.hash = value.hash.to_vec()?; Ok(ret) } @@ -590,22 +424,11 @@ struct CommonGroupBodyContent { description: String, members: Vec, - total_equity: u64, - - // map优化以快速匹配 - method_acls: Vec, - - role_acls: Vec, ood_list: Vec, - history_block_max: u64, - history_block_lifespan: u64, - - revoked_conclusions: HashSet, version: u64, - consensus_interval: u64, - join_signatures: Vec, + prev_blob_id: Option, } impl CommonGroupBodyContent { @@ -621,16 +444,9 @@ impl CommonGroupBodyContent { icon, description, members, - total_equity: 0, - method_acls: vec![], - role_acls: vec![], ood_list, - history_block_max: 0, - history_block_lifespan: 0, - revoked_conclusions: HashSet::default(), version: 0, - consensus_interval: 0, - join_signatures: vec![], + prev_blob_id: None, } } } @@ -648,24 +464,13 @@ impl TryFrom for CommonGroupBodyContent { }, description: value.take_description(), members: ProtobufCodecHelper::decode_value_list(value.take_members())?, - total_equity: value.total_equity, - method_acls: ProtobufCodecHelper::decode_value_list(value.take_method_acls())?, - role_acls: ProtobufCodecHelper::decode_value_list(value.take_role_acls())?, ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, - history_block_max: value.get_history_block_max(), - history_block_lifespan: value.get_history_block_lifespan(), - revoked_conclusions: HashSet::from_iter(ProtobufCodecHelper::decode_buf_list( - value.take_revoked_conclusions(), - )?), version: value.version, - consensus_interval: if value.has_consensus_interval() { - value.get_consensus_interval() + prev_blob_id: if value.has_prev_blob_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_prev_blob_id())?) } else { - 0 + None }, - join_signatures: ProtobufCodecHelper::decode_value_list( - value.take_join_signatures().into_vec(), - )?, }; Ok(ret) @@ -685,33 +490,14 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { ret.description = value.description.clone(); ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); - ret.total_equity = value.total_equity; - ret.set_method_acls(ProtobufCodecHelper::encode_nested_list(&value.method_acls)?); - ret.set_role_acls(ProtobufCodecHelper::encode_nested_list(&value.role_acls)?); ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( value.ood_list.as_slice(), )?); - if value.history_block_max > 0 { - ret.set_history_block_max(value.history_block_max); - } - if value.history_block_lifespan > 0 { - ret.set_history_block_lifespan(value.history_block_lifespan); - } - ret.set_revoked_conclusions(ProtobufCodecHelper::encode_buf_list( - value - .revoked_conclusions - .iter() - .map(|id| id.clone()) - .collect::>() - .as_slice(), - )?); + ret.version = value.version; - if value.consensus_interval > 0 { - ret.set_consensus_interval(value.consensus_interval); + if let Some(prev_blob_id) = &value.prev_blob_id { + ret.set_prev_blob_id(prev_blob_id.to_vec()?); } - ret.set_join_signatures(ProtobufCodecHelper::encode_nested_list( - &value.join_signatures, - )?); Ok(ret) } @@ -722,7 +508,6 @@ pub struct SimpleGroupDescContent { unique_id: UniqueId, founder_id: ObjectId, admins: Vec, - conclusion_limit: u32, } impl TryFrom for SimpleGroupDescContent { @@ -732,7 +517,6 @@ impl TryFrom for SimpleGroupDescContent { let ret = Self { unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, admins: ProtobufCodecHelper::decode_value_list(value.admins)?, - conclusion_limit: value.conclusion_limit, founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, }; @@ -749,7 +533,6 @@ impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { ret.unique_id = value.unique_id.to_vec()?; ret.founder_id = value.founder_id.to_vec()?; ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); - ret.conclusion_limit = value.conclusion_limit; Ok(ret) } @@ -833,7 +616,6 @@ impl TryFrom<&OrgDescContent> for protos::OrgDescContent { #[derive(Clone, Debug, Default)] pub struct OrgBodyContent { admins: Vec, - token_contract: Option, common: CommonGroupBodyContent, } @@ -849,7 +631,6 @@ impl OrgBodyContent { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), admins, - token_contract: None, } } @@ -868,13 +649,6 @@ impl TryFrom for OrgBodyContent { fn try_from(mut value: protos::OrgBodyContent) -> BuckyResult { let ret = Self { admins: ProtobufCodecHelper::decode_value_list(value.take_admins())?, - token_contract: if value.has_token_contract() { - Some(ProtobufCodecHelper::decode_buf( - value.take_token_contract(), - )?) - } else { - None - }, common: ProtobufCodecHelper::decode_value(value.take_common())?, }; @@ -891,10 +665,6 @@ impl TryFrom<&OrgBodyContent> for protos::OrgBodyContent { ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); ret.set_common(ProtobufCodecHelper::encode_nested_item(&value.common)?); - if let Some(token_contract) = value.token_contract { - ret.set_token_contract(token_contract.to_vec()?); - } - Ok(ret) } } diff --git a/src/component/cyfs-chunk-lib/src/chunk.rs b/src/component/cyfs-chunk-lib/src/chunk.rs index cc7114070..054cb052b 100644 --- a/src/component/cyfs-chunk-lib/src/chunk.rs +++ b/src/component/cyfs-chunk-lib/src/chunk.rs @@ -309,35 +309,3 @@ impl async_std::io::Write for ChunkWrite { Poll::Ready(Ok(())) } } - -impl From<&Group> for ChunkMeta { - fn from(group: &Group) -> Self { - let len = group.raw_measure(&None).unwrap(); - let mut buf = vec![0u8; len]; - let remain = group.raw_encode(buf.as_mut_slice(), &None).unwrap(); - assert_eq!(remain.len(), 0); - ChunkMeta::MemChunk(buf) - } -} - -impl TryFrom<&ChunkMeta> for Group { - type Error = BuckyError; - - fn try_from(value: &ChunkMeta) -> Result { - match value { - ChunkMeta::MemChunk(buf) => { - let (group, remain) = Group::raw_decode(buf.as_slice())?; - assert_eq!(remain.len(), 0); - Ok(group) - } - ChunkMeta::MMapChunk(_, _) => Err(BuckyError::new( - BuckyErrorCode::InvalidFormat, - format!("expected ChunkMeta::MemChunk, got ChunkMeta::MMapChunk"), - )), - ChunkMeta::SharedMemChunk(_, _, _) => Err(BuckyError::new( - BuckyErrorCode::InvalidFormat, - format!("expected ChunkMeta::MemChunk, got ChunkMeta::SharedMemChunk"), - )), - } - } -} diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 8048b3951..d49009e4c 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -417,7 +417,7 @@ message GroupConsensusBlockDescContent { bytes meta_block_id = 5; uint64 round = 7; - bytes group_chunk_id = 8; + bytes group_blob_id = 8; } message GroupConsensusBlockBodyContent { diff --git a/src/component/cyfs-core/src/group/group_blob.rs b/src/component/cyfs-core/src/group/group_blob.rs new file mode 100644 index 000000000..90829215d --- /dev/null +++ b/src/component/cyfs-core/src/group/group_blob.rs @@ -0,0 +1,44 @@ +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, RawDecode, RawEncode, +}; + +use crate::{Storage, StorageObj}; + +pub trait GroupBlob: Sized { + fn to_blob(&self) -> Storage; + + fn from_blob(blob: &Storage) -> BuckyResult; + + fn blob_storage_id(&self) -> String; +} + +impl GroupBlob for Group { + fn to_blob(&self) -> Storage { + let len = self.raw_measure(&None).unwrap(); + let mut buf = vec![0u8; len]; + let remain = self.raw_encode(buf.as_mut_slice(), &None).unwrap(); + assert_eq!(remain.len(), 0); + Storage::create_with_hash(self.blob_storage_id().as_str(), buf) + } + + fn from_blob(blob: &Storage) -> BuckyResult { + let group_buf = blob.value(); + let (group, remain) = Group::raw_decode(group_buf.as_slice())?; + assert_eq!(remain.len(), 0); + + let expected_id = group.blob_storage_id(); + + if blob.id() != expected_id { + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + format!("unknown storage, expect {}, got {}", expected_id, blob.id()), + )); + } + + Ok(group) + } + + fn blob_storage_id(&self) -> String { + format!("group@{}@{}", self.desc().object_id(), self.version()) + } +} diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 7d447ad15..4b4bf4f9a 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -16,7 +16,7 @@ pub struct GroupConsensusBlockDescContent { height: u64, meta_block_id: ObjectId, round: u64, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, } impl DescContent for GroupConsensusBlockDescContent { @@ -55,8 +55,8 @@ impl GroupConsensusBlockDescContent { self.round } - pub fn group_chunk_id(&self) -> &ObjectId { - &self.group_chunk_id + pub fn group_blob_id(&self) -> &ObjectId { + &self.group_blob_id } } @@ -242,7 +242,7 @@ pub trait GroupConsensusBlockObject { height: u64, meta_block_id: ObjectId, round: u64, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, qc: Option, tc: Option, owner: ObjectId, @@ -259,7 +259,7 @@ pub trait GroupConsensusBlockObject { fn named_object(&self) -> &NamedObjectBase; fn named_object_mut(&mut self) -> &mut NamedObjectBase; fn round(&self) -> u64; - fn group_chunk_id(&self) -> &ObjectId; + fn group_blob_id(&self) -> &ObjectId; fn qc(&self) -> &Option; fn tc(&self) -> &Option; } @@ -272,7 +272,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { height: u64, meta_block_id: ObjectId, round: u64, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, qc: Option, tc: Option, owner: ObjectId, @@ -287,7 +287,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { meta_block_id, body_hash: body.hash(), round, - group_chunk_id, + group_blob_id, }; let block = GroupConsensusBlockBuilder::new(desc, body) @@ -371,9 +371,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { desc.round } - fn group_chunk_id(&self) -> &ObjectId { + fn group_blob_id(&self) -> &ObjectId { let desc = self.0.desc().content(); - &desc.group_chunk_id + &desc.group_blob_id } fn qc(&self) -> &Option { diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index d7134a3c0..0fa271b8c 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,10 +4,12 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; +mod group_blob; pub use group_consensus_block::*; pub use group_proposal::*; // pub use group_proposal_decide_param::*; +pub use group_blob::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; diff --git a/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs index f06d876b9..4f79316b6 100644 --- a/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs +++ b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs @@ -2,7 +2,6 @@ use std::mem; use async_std::task; use cyfs_base::*; -use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ GroupProposal, GroupProposalBuilder, GroupProposalDescContent, GroupProposalObject, GroupPropsalDecideParam, GroupRPath, GroupUpdateGroupPropsalParam, @@ -13,13 +12,13 @@ use crate::{GROUP_METHOD_UPDATE, STATEPATH_GROUP_DEC_ID, STATEPATH_GROUP_DEC_RPA pub struct GroupUpdateProposal { proposal: GroupProposal, target_dec_id: Vec, - from_chunk_id: Option, + from_blob_id: Option, to_group: Group, } impl GroupUpdateProposal { pub fn create( - from_group_chunk_id: Option, + from_group_blob_id: Option, to_group: Group, owner: ObjectId, target_dec_id: Vec, @@ -28,7 +27,7 @@ impl GroupUpdateProposal { effective_ending: Option, ) -> GroupUpdateProposalBuilder { GroupUpdateProposalBuilder::create( - from_group_chunk_id, + from_group_blob_id, to_group, owner, target_dec_id, @@ -65,8 +64,8 @@ impl GroupUpdateProposal { self.target_dec_id.as_slice() } - pub fn from_chunk_id(&self) -> &Option { - &self.from_chunk_id + pub fn from_blob_id(&self) -> &Option { + &self.from_blob_id } pub fn to_group(&self) -> &Group { @@ -125,24 +124,24 @@ impl TryFrom for GroupUpdateProposal { } let payload = value.payload().as_ref().unwrap(); - let (group_chunk, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); + let (group_blob, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); assert_eq!(remain.len(), 0); - let to_group = Group::try_from(&group_chunk)?; + let to_group = Group::try_from(&group_blob)?; - let to_chunk_id = - task::block_on(async { group_chunk.to_chunk().await.unwrap().calculate_id() }); - if &to_chunk_id.object_id() != param.to_chunk_id() { + let to_blob_id = + task::block_on(async { group_blob.to_chunk().await.unwrap().calculate_id() }); + if &to_blob_id.object_id() != param.to_blob_id() { return Err(BuckyError::new( BuckyErrorCode::InvalidFormat, - "the chunk in GroupUpdateProposal.body is not match with the to_chunk_id in desc.param", + "the chunk in GroupUpdateProposal.body is not match with the to_blob_id in desc.param", )); } let ret = Self { proposal: value, target_dec_id: Vec::from(param.target_dec_id()), - from_chunk_id: param.from_chunk_id().clone(), + from_blob_id: param.from_blob_id().clone(), to_group, }; @@ -153,13 +152,13 @@ impl TryFrom for GroupUpdateProposal { pub struct GroupUpdateProposalBuilder { proposal: GroupProposalBuilder, target_dec_id: Vec, - from_chunk_id: Option, + from_blob_id: Option, to_group: Option, } impl GroupUpdateProposalBuilder { pub fn create( - from_group_chunk_id: Option, + from_group_blob_id: Option, to_group: Group, owner: ObjectId, target_dec_id: Vec, @@ -167,20 +166,20 @@ impl GroupUpdateProposalBuilder { effective_begining: Option, effective_ending: Option, ) -> Self { - let group_chunk = ChunkMeta::from(&to_group); - let group_chunk_vec = { - let len = group_chunk.raw_measure(&None).unwrap(); + let group_blob = ChunkMeta::from(&to_group); + let group_blob_vec = { + let len = group_blob.raw_measure(&None).unwrap(); let mut buf = vec![0u8; len]; - let remain = group_chunk.raw_encode(buf.as_mut_slice(), &None).unwrap(); + let remain = group_blob.raw_encode(buf.as_mut_slice(), &None).unwrap(); assert_eq!(remain.len(), 0); buf }; - let to_chunk_id = - task::block_on(async { group_chunk.to_chunk().await.unwrap().calculate_id() }); + let to_blob_id = + task::block_on(async { group_blob.to_chunk().await.unwrap().calculate_id() }); let param = - GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_chunk_id.object_id()); + GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_blob_id.object_id()); let param_vec = { let len = param.raw_measure(&None).unwrap(); let mut buf = vec![0u8; len]; @@ -196,7 +195,7 @@ impl GroupUpdateProposalBuilder { update_rpath, GROUP_METHOD_UPDATE.to_string(), Some(param_vec), - Some(group_chunk_vec), + Some(group_blob_vec), None, owner, meta_block_id, @@ -207,7 +206,7 @@ impl GroupUpdateProposalBuilder { Self { proposal, target_dec_id, - from_chunk_id: from_group_chunk_id, + from_blob_id: from_group_blob_id, to_group: Some(to_group), } } @@ -237,15 +236,15 @@ impl GroupUpdateProposalBuilder { pub fn build(mut self) -> GroupUpdateProposal { let mut target_dec_id: Vec = vec![]; - let mut from_chunk_id: Option = None; + let mut from_blob_id: Option = None; let to_group = self.to_group.take().unwrap(); mem::swap(&mut target_dec_id, &mut self.target_dec_id); - mem::swap(&mut from_chunk_id, &mut self.from_chunk_id); + mem::swap(&mut from_blob_id, &mut self.from_blob_id); GroupUpdateProposal { proposal: self.proposal.build(), target_dec_id, - from_chunk_id, + from_blob_id, to_group, } } diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 1caf5b9a4..7a28cf89b 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,5 +32,4 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-chunk-lib = { path = '../../component/cyfs-chunk-lib' } cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 2d416c357..c19a807fa 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -1,6 +1,5 @@ use std::{ collections::HashMap, - fmt::format, sync::Arc, time::{Duration, SystemTime}, }; @@ -11,10 +10,9 @@ use cyfs_base::{ ObjectDesc, ObjectId, ObjectLink, ObjectTypeCode, OwnerObjectDesc, RawConvertTo, RawDecode, RawEncode, RsaCPUObjectSigner, SignatureSource, Signer, }; -use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, - GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupBlob, GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, + GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::{ExecuteResult, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; @@ -27,7 +25,8 @@ use crate::{ helper::Timer, Committee, GroupObjectMapProcessor, GroupStorage, HotstuffMessage, PendingProposalConsumer, RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, + GROUP_DEFAULT_CONSENSUS_INTERVAL, HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, + TIME_PRECISION, }; /** @@ -297,7 +296,7 @@ impl HotstuffRunner { let tc = last_tc.clone(); let vote_mgr = VoteMgr::new(committee.clone(), round); - let init_timer_interval = store.group().consensus_interval(); + let init_timer_interval = GROUP_DEFAULT_CONSENSUS_INTERVAL; let max_quorum_round = round - 1; let header_height = store.header_height(); let max_height = header_height + 2; @@ -385,7 +384,7 @@ impl HotstuffRunner { { // check leader let leader_owner = self - .get_leader_owner(Some(block.group_chunk_id()), block.round()) + .get_leader_owner(Some(block.group_blob_id()), block.round()) .await?; if &leader_owner != block.owner() { @@ -582,17 +581,17 @@ impl HotstuffRunner { async fn get_leader_owner( &self, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { let leader = self .committee - .get_leader(group_chunk_id, round) + .get_leader(group_blob_id, round) .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", self, - group_chunk_id, round, + group_blob_id, round, err ); @@ -983,7 +982,7 @@ impl HotstuffRunner { round + 1 ); - self.timer.reset(group.consensus_interval()); + self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); self.round = round + 1; self.vote_mgr.cleanup(self.round); self.tc = None; @@ -1144,7 +1143,7 @@ impl HotstuffRunner { ); if !only_rebuild_result_state { - match self.check_group_is_latest(block.group_chunk_id()).await { + match self.check_group_is_latest(block.group_blob_id()).await { Ok(is_latest) if is_latest => {} _ => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", @@ -1746,7 +1745,7 @@ impl HotstuffRunner { let latest_group = match self.committee.get_group(None).await { Ok(group) => { - self.timer.reset(group.consensus_interval()); + self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); group } Err(err) => { @@ -2062,11 +2061,7 @@ impl HotstuffRunner { }) .collect(); - let group_chunk_id = ChunkMeta::from(group) - .to_chunk() - .await - .unwrap() - .calculate_id(); + let group_blob_id = group.to_blob().desc().object_id(); let mut block = GroupConsensusBlock::create( self.rpath.clone(), @@ -2075,7 +2070,7 @@ impl HotstuffRunner { prev_block.as_ref().map_or(0, |b| b.height()) + 1, ObjectId::default(), // TODO: meta block id self.round, - group_chunk_id.object_id(), + group_blob_id, self.high_qc.clone(), tc, self.local_id, @@ -2256,11 +2251,11 @@ impl HotstuffRunner { Ok(()) } - async fn check_group_is_latest(&self, group_chunk_id: &ObjectId) -> BuckyResult { + async fn check_group_is_latest(&self, group_blob_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; - let group_chunk = ChunkMeta::from(&latest_group).to_chunk().await?; - let latest_chunk_id = group_chunk.calculate_id(); - Ok(latest_chunk_id.as_object_id() == group_chunk_id) + let group_blob = latest_group.to_blob(); + let latest_chunk_id = group_blob.desc().object_id(); + Ok(&latest_chunk_id == group_blob_id) } async fn make_sure_result_state( @@ -2379,16 +2374,16 @@ impl HotstuffRunner { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. let max_round_block = self.store.block_with_max_round(); - let group_chunk_id = max_round_block.as_ref().map(|block| block.group_chunk_id()); - let last_group = self.committee.get_group(group_chunk_id).await; - let latest_group = match group_chunk_id.as_ref() { + let group_blob_id = max_round_block.as_ref().map(|block| block.group_blob_id()); + let last_group = self.committee.get_group(group_blob_id).await; + let latest_group = match group_blob_id.as_ref() { Some(_) => self.committee.get_group(None).await, None => last_group.clone(), }; - let duration = latest_group - .as_ref() - .map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| g.consensus_interval()); + let duration = latest_group.as_ref().map_or(HOTSTUFF_TIMEOUT_DEFAULT, |g| { + GROUP_DEFAULT_CONSENSUS_INTERVAL + }); self.timer.reset(duration); if let Ok(leader) = self.committee.get_leader(None, self.round).await { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 59cb43b96..1052d4268 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -6,7 +6,7 @@ use std::{ }; use async_std::channel::{Receiver, Sender}; -use cyfs_base::{BuckyResult, NamedObject, ObjectDesc, ObjectId}; +use cyfs_base::{BuckyResult, NamedObject, ObjectId}; use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; use futures::FutureExt; diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 398274723..6b32187a3 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -9,13 +9,11 @@ use cyfs_base::{ ObjectDesc, ObjectId, OwnerObjectDesc, RsaCPUObjectVerifier, SignatureSource, SingleKeyObjectDesc, Verifier, }; -use cyfs_chunk_lib::ChunkMeta; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupBlob, GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use cyfs_lib::NONObjectInfo; use crate::network::NONDriverHelper; @@ -24,7 +22,7 @@ pub(crate) struct Committee { group_id: ObjectId, non_driver: NONDriverHelper, local_device_id: ObjectId, - group_cache: Arc>>, // (group_chunk_id, group) + group_cache: Arc>>, // (group_blob_id, group) } impl Committee { @@ -37,16 +35,16 @@ impl Committee { } } - pub async fn get_group(&self, group_chunk_id: Option<&ObjectId>) -> BuckyResult { - self.check_group(group_chunk_id, None).await + pub async fn get_group(&self, group_blob_id: Option<&ObjectId>) -> BuckyResult { + self.check_group(group_blob_id, None).await } pub async fn quorum_threshold( &self, voters: &HashSet, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, ) -> BuckyResult { - let group = self.check_group(group_chunk_id, None).await?; + let group = self.check_group(group_blob_id, None).await?; let voters: Vec<&ObjectId> = voters .iter() .filter(|id| { @@ -64,10 +62,10 @@ impl Committee { pub async fn get_leader( &self, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { - let group = self.check_group(group_chunk_id, None).await?; + let group = self.check_group(group_blob_id, None).await?; let i = (round % (group.ood_list().len() as u64)) as usize; Ok(group.ood_list()[i].object_id().clone()) } @@ -94,7 +92,7 @@ impl Committee { ); let group = self - .check_group(Some(block.group_chunk_id()), Some(&from)) + .check_group(Some(block.group_blob_id()), Some(&from)) .await?; if !self.check_block_sign(&block, &group).await? { @@ -162,7 +160,7 @@ impl Committee { )); } - self.check_group(Some(block_desc.content().group_chunk_id()), Some(&from)) + self.check_group(Some(block_desc.content().group_blob_id()), Some(&from)) .await?; log::debug!( @@ -252,7 +250,7 @@ impl Committee { let is_enough = self .quorum_threshold( &tc.votes.iter().map(|v| v.voter).collect(), - prev_block.map(|b| b.group_chunk_id()), + prev_block.map(|b| b.group_blob_id()), ) .await?; @@ -316,7 +314,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block_desc.group_chunk_id()), + Some(prev_block_desc.group_blob_id()), ) .await?; @@ -366,8 +364,8 @@ impl Committee { .get_group(&self.group_id, chunk_id, from) .await?; - let group_chunk = ChunkMeta::from(&group).to_chunk().await?; - let calc_id = group_chunk.calculate_id().object_id(); + let group_blob = group.to_blob(); + let calc_id = group_blob.desc().object_id(); if let Some(id) = chunk_id { assert_eq!(&calc_id, id); } diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 6a9735a7f..d2128a20f 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -244,7 +244,7 @@ impl QCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.0).collect(), - Some(block.group_chunk_id()), + Some(block.group_blob_id()), ) .await?; if self.thresholded { @@ -315,7 +315,7 @@ impl TCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.voter).collect(), - block.map(|block| block.group_chunk_id()), + block.map(|block| block.group_blob_id()), ) .await?; diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 77a652a7e..61f8a1106 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -22,3 +22,4 @@ pub const STATE_NOTIFY_COUNT_PER_ROUND: usize = 8; pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; pub const MEMORY_CACHE_DURATION: Duration = Duration::from_secs(300); +pub const GROUP_DEFAULT_CONSENSUS_INTERVAL: u64 = 5000; // default 5000 ms diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index ff175960d..a43f99b99 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -5,7 +5,6 @@ use cyfs_base::{ RawConvertTo, RawFrom, RsaCPUObjectSigner, TypelessCoreObject, }; use cyfs_core::{GroupProposal, GroupRPath}; -use cyfs_group_lib::RPathDelegate; use cyfs_lib::NONObjectInfo; use crate::{ diff --git a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs index 8fd67496b..b9d33efc4 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_requestor.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; -use cyfs_core::{GroupConsensusBlockObject, GroupRPath}; +use cyfs_core::{GroupRPath}; use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::NONObjectInfo; use futures::FutureExt; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index e019db892..382a67120 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -104,7 +104,7 @@ impl DecStateSynchronizer { struct DecStateSynchronizerCache { state_cache: DecStorageCache, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, group: Group, } @@ -112,7 +112,7 @@ struct UpdateNotifyInfo { header_block: GroupConsensusBlock, qc: HotstuffBlockQC, remotes: HashSet, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, group: Group, } @@ -247,7 +247,7 @@ impl DecStateSynchronizerRunner { header_block: notify_info.header_block.clone(), qc: notify_info.qc.clone(), }, - group_chunk_id: notify_info.group_chunk_id, + group_blob_id: notify_info.group_blob_id, group: notify_info.group.clone(), }); self.update_notifies = None; @@ -276,15 +276,15 @@ impl DecStateSynchronizerRunner { if self.state_cache.is_none() { let state_cache = self.store.cur_state().await; if let Some(state_cache) = state_cache { - let group_chunk_id = state_cache.header_block.group_chunk_id().clone(); + let group_blob_id = state_cache.header_block.group_blob_id().clone(); let group = self .non_driver - .get_group(self.rpath.group_id(), Some(&group_chunk_id), None) + .get_group(self.rpath.group_id(), Some(&group_blob_id), None) .await; if let Ok(group) = group { self.state_cache = Some(DecStateSynchronizerCache { state_cache, - group_chunk_id, + group_blob_id, group, }); } @@ -320,15 +320,15 @@ impl DecStateSynchronizerRunner { { let group = self .committee - .check_group(Some(header_block.group_chunk_id()), None) + .check_group(Some(header_block.group_blob_id()), None) .await?; - let group_chunk_id = header_block.group_chunk_id().clone(); + let group_blob_id = header_block.group_blob_id().clone(); self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc: qc, remotes: HashSet::from([remote]), - group_chunk_id, + group_blob_id, group, }); }; diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 99c3fed62..acf061ae7 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -88,7 +88,7 @@ impl StatePusher { struct HeaderBlockNotifyProgress { header_block: GroupConsensusBlock, qc_block: GroupConsensusBlock, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, members: Vec, total_notify_times: usize, cur_block_notify_times: usize, @@ -218,14 +218,10 @@ impl StateChanggeRunner { return; } - if block.group_chunk_id() != progress.header_block.group_chunk_id() { + if block.group_blob_id() != progress.header_block.group_blob_id() { let group = self .non_driver - .get_group( - block.rpath().group_id(), - Some(block.group_chunk_id()), - None, - ) + .get_group(block.rpath().group_id(), Some(block.group_blob_id()), None) .await; if group.is_err() { return; @@ -238,7 +234,7 @@ impl StateChanggeRunner { .collect(); } - progress.group_chunk_id = block.group_chunk_id().clone(); + progress.group_blob_id = block.group_blob_id().clone(); progress.total_notify_times += progress.cur_block_notify_times; progress.cur_block_notify_times = 0; progress.header_block = block; @@ -247,11 +243,7 @@ impl StateChanggeRunner { None => { let group = self .non_driver - .get_group( - block.rpath().group_id(), - Some(block.group_chunk_id()), - None, - ) + .get_group(block.rpath().group_id(), Some(block.group_blob_id()), None) .await; if group.is_err() { return; @@ -268,12 +260,12 @@ impl StateChanggeRunner { None => return, }; - let group_chunk_id = block.group_chunk_id().clone(); + let group_blob_id = block.group_blob_id().clone(); self.notify_progress = Some(HeaderBlockNotifyProgress { header_block: block, qc_block, - group_chunk_id, + group_blob_id, members, total_notify_times, cur_block_notify_times: 0, diff --git a/src/component/cyfs-group/src/helper/timer.rs b/src/component/cyfs-group/src/helper/timer.rs index 6d2ebb234..5edda71b4 100644 --- a/src/component/cyfs-group/src/helper/timer.rs +++ b/src/component/cyfs-group/src/helper/timer.rs @@ -1,6 +1,4 @@ -use std::future::Future; use std::ops::Sub; -use std::pin::Pin; use std::time::{Duration, Instant}; pub struct Timer { diff --git a/src/component/cyfs-group/src/network/listener.rs b/src/component/cyfs-group/src/network/listener.rs index e66ef8a43..02017184d 100644 --- a/src/component/cyfs-group/src/network/listener.rs +++ b/src/component/cyfs-group/src/network/listener.rs @@ -1,4 +1,4 @@ -use std::time::{Duration, Instant}; +use std::time::{Instant}; use cyfs_base::{ObjectId, RawDecode}; use cyfs_bdt::DatagramTunnelGuard; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index b8a2ac29b..3e400ce44 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -163,16 +163,16 @@ impl NONDriverHelper { pub async fn get_group( &self, group_id: &ObjectId, - group_chunk_id: Option<&ObjectId>, + group_blob_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { - // TODO: ignore group_chunk_id first - // match group_chunk_id { - // Some(group_chunk_id) => { - // let chunk = self.get_object(group_chunk_id, from).await?; - // let (group_chunk, remain) = ChunkMeta::raw_decode(chunk.object_raw.as_slice())?; + // TODO: ignore group_blob_id first + // match group_blob_id { + // Some(group_blob_id) => { + // let blob = self.get_object(group_blob_id, from).await?; + // let (group_blob, remain) = Storage::raw_decode(blob.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // let group = Group::try_from(&group_chunk)?; + // let group = Group::from_blob(&group_blob)?; // if &group.desc().object_id() == group_id { // Ok(group) // } else { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 78af14c4b..17756b992 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -4,10 +4,10 @@ use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; -use cyfs_chunk_lib::ChunkMeta; + use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, - HotstuffTimeout, + GroupBlob, GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, + HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; @@ -42,7 +42,7 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, - group_chunk_id: ObjectId, + group_blob_id: ObjectId, cache: StorageCacheInfo, @@ -60,8 +60,8 @@ impl GroupStorage { root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; - let group_chunk = ChunkMeta::from(&group); - let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + let group_blob = group.to_blob(); + let group_blob_id = group_blob.desc().object_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) @@ -77,7 +77,7 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_chunk_id: group_chunk_id.object_id(), + group_blob_id, storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), @@ -108,8 +108,8 @@ impl GroupStorage { log::warn!("get group {} from noc failed {:?}", group_id, err); err })?; - let group_chunk = ChunkMeta::from(&group); - let group_chunk_id = group_chunk.to_chunk().await.unwrap().calculate_id(); + let group_blob = group.to_blob(); + let group_blob_id = group_blob.desc().object_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) @@ -139,7 +139,7 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_chunk_id: group_chunk_id.object_id(), + group_blob_id, storage_engine: StorageEngineGroupState::new( dec_group_state, state_path, @@ -180,8 +180,8 @@ impl GroupStorage { &self.group } - pub fn group_chunk_id(&self) -> &ObjectId { - &self.group_chunk_id + pub fn group_blob_id(&self) -> &ObjectId { + &self.group_blob_id } pub fn dec_state_id(&self) -> &Option { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 880732884..8186031b8 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -193,8 +193,6 @@ mod Common { .collect(), ); - group.set_consensus_interval(5000); - log::info!("create group: {:?}", group.desc().object_id()); let desc_hash = group.desc().raw_hash_value().unwrap(); From 61391631636eba9e729cfe290307d809fcd2168c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 8 Apr 2023 20:17:34 +0800 Subject: [PATCH 530/553] MetaChain: update group --- src/component/cyfs-base-meta/Cargo.toml | 1 + src/component/cyfs-base-meta/src/group.rs | 234 ++++++++++++++++++ src/component/cyfs-base-meta/src/lib.rs | 26 +- .../src/executor/tx_proc/desc_proc.rs | 79 +++++- 4 files changed, 318 insertions(+), 22 deletions(-) create mode 100644 src/component/cyfs-base-meta/src/group.rs diff --git a/src/component/cyfs-base-meta/Cargo.toml b/src/component/cyfs-base-meta/Cargo.toml index 8e23382cf..896044164 100644 --- a/src/component/cyfs-base-meta/Cargo.toml +++ b/src/component/cyfs-base-meta/Cargo.toml @@ -20,5 +20,6 @@ serde_json = '1.0' hex = '0.4.2' async-trait = '0.1.53' async-std = '1.11' +futures = '0.3.25' primitive-types = { version = '0.9' } codec = { package = 'parity-scale-codec', version = '2.0', default-features = false, features = ['derive', 'full'], optional = true } diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs new file mode 100644 index 000000000..a97b79f5d --- /dev/null +++ b/src/component/cyfs-base-meta/src/group.rs @@ -0,0 +1,234 @@ +use std::collections::HashSet; + +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, + ObjectTypeCode, People, PeopleId, RawConvertTo, RsaCPUObjectVerifier, Signature, + SingleKeyObjectDesc, Verifier, +}; +use cyfs_core::GroupBlob; + +async fn verify_signature( + signs: Option<&Vec>, + data_buf: &[u8], + verifier: &RsaCPUObjectVerifier, + signer_id: &PeopleId, +) -> BuckyResult<()> { + let signs = signs.map_or([].as_slice(), |s| s.as_slice()); + let sign = signs.iter().find(|s| match s.sign_source() { + cyfs_base::SignatureSource::Object(signer) => &signer.obj_id == signer_id.object_id(), + _ => false, + }); + + match sign { + Some(sign) => { + if verifier.verify(data_buf, sign).await { + Ok(()) + } else { + let msg = format!("Invalid signature from {}", signer_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)) + } + } + None => { + let msg = format!("Not found signature from {}", signer_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::NotFound, msg)) + } + } +} + +async fn verify_group_signature( + group: &Group, + people_id: &PeopleId, + member_querier: &impl MemberQuerier, +) -> BuckyResult<()> { + let people = member_querier.get_people(people_id).await?; + let verifier = RsaCPUObjectVerifier::new(people.desc().public_key().clone()); + let desc_buf = group.desc().to_vec()?; + verify_signature( + group.signs().desc_signs(), + desc_buf.as_slice(), + &verifier, + people_id, + ) + .await?; + let body_buf = group.body().to_vec()?; + verify_signature( + group.signs().body_signs(), + body_buf.as_slice(), + &verifier, + people_id, + ) + .await +} + +#[async_trait::async_trait] +pub trait MemberQuerier: Send + Sync { + async fn get_people(&self, people_id: &PeopleId) -> BuckyResult; +} + +#[async_trait::async_trait] +pub trait GroupVerifier { + // Check the update is allowed + async fn is_update_valid( + &self, + latest_group: Option<&Group>, + member_querier: &impl MemberQuerier, + ) -> BuckyResult<()>; +} + +#[async_trait::async_trait] +impl GroupVerifier for Group { + async fn is_update_valid( + &self, + latest_group: Option<&Group>, + member_querier: &impl MemberQuerier, + ) -> BuckyResult<()> { + let group_id = self.desc().object_id(); + let (last_admins, last_members) = match latest_group { + Some(latest_group) => { + let latest_group_id = latest_group.desc().object_id(); + if group_id != latest_group_id { + let msg = format!( + "The new group({}) is unmatch with the latest group({}).", + group_id, latest_group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + let latest_group_blob = latest_group.to_blob(); + let latest_group_blob_id = latest_group_blob.desc().object_id(); + if self.version() != latest_group.version() + 1 + || self.prev_blob_id() != &Some(latest_group_blob_id) + { + let msg = format!("Attempt to update group({}) from unknown version({}/{:?}), latest version: {}/{}.", group_id, self.version() - 1, self.prev_blob_id(), latest_group.version(), latest_group_blob_id); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + + (latest_group.admins(), latest_group.members()) + } + None => match self.prev_blob_id() { + Some(prev_blob_id) => { + let msg = format!( + "The latest group({}) is necessary for update. prev_blob_id: {}", + group_id, prev_blob_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + None => ([].as_slice(), [].as_slice()), + }, + }; + + // admins: > 1/2 + // new members: all + + let last_admins = HashSet::::from_iter( + last_admins + .iter() + .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) + .map(|m| m.id), + ); + let last_members = HashSet::::from_iter( + last_members + .iter() + .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) + .map(|m| m.id), + ); + let add_admins = HashSet::::from_iter( + self.admins() + .iter() + .filter(|m| { + m.id.obj_type_code() == ObjectTypeCode::People && !last_admins.contains(&m.id) + }) + .map(|m| m.id), + ); + let add_members = HashSet::::from_iter( + self.members() + .iter() + .filter(|m| { + m.id.obj_type_code() == ObjectTypeCode::People && !last_members.contains(&m.id) + }) + .map(|m| m.id), + ); + + if add_admins.len() != self.admins().len() - last_admins.len() { + let msg = format!( + "Update group({}) with duplicate admins or invalid admins.", + group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + + if add_members.len() != self.members().len() - add_members.len() { + let msg = format!( + "Update group({}) with duplicate members or invalid members.", + group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + + let additionals = add_admins + .union(&add_members) + .map(|id| *id) + .collect::>(); + if additionals.len() != add_admins.len() + add_members.len() { + let msg = format!( + "Update group({}) with admins is not necessary in members.", + group_id + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + + let check_peoples = + futures::future::join_all(last_admins.iter().chain(additionals.iter()).map( + |people_id| async move { + let people_id = PeopleId::try_from(people_id).unwrap(); + verify_group_signature(self, &people_id, member_querier).await + }, + )) + .await; + + let (last_admin_signs, add_member_signs) = check_peoples.split_at(last_admins.len()); + let last_admin_sign_count = last_admin_signs.iter().filter(|s| s.is_ok()).count(); + if last_admin_sign_count <= last_admins.len() / 2 { + let msg = format!( + "Update group({}) failed for signatures from admins in latest version is not enough: expected {}, got {}.", + group_id, + last_admins.len() / 2 + 1, + last_admin_sign_count + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)); + } + + let failed_add_member_sign_pos = add_member_signs.iter().position(|s| s.is_err()); + match failed_add_member_sign_pos { + Some(pos) => { + let msg = format!( + "Update group({}) failed for signatures from additional member({:?}) is invalid.", + group_id, + additionals.get(pos) + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)); + } + None => { + log::info!( + "Update group({}) verify ok, from {:?}/{:?}, to {}/{}", + group_id, + latest_group.map(|group| group.version()), + self.prev_blob_id(), + self.version(), + self.to_blob().desc().object_id() + ); + Ok(()) + } + } + } +} diff --git a/src/component/cyfs-base-meta/src/lib.rs b/src/component/cyfs-base-meta/src/lib.rs index 09481a16d..2beadb599 100644 --- a/src/component/cyfs-base-meta/src/lib.rs +++ b/src/component/cyfs-base-meta/src/lib.rs @@ -1,28 +1,30 @@ extern crate alloc; pub use block::*; +pub use code::*; pub use config::*; +pub use contract::*; pub use event::*; pub use extension::*; +pub use group::*; +pub use nft::*; pub use sn_service::*; pub use spv::*; pub use tx::*; pub use types::*; pub use view::*; -pub use code::*; -pub use contract::*; -pub use nft::*; -mod types; -mod config; mod block; -mod view; -mod event; -mod tx; -mod sn_service; -mod spv; -mod extension; mod code; +mod config; mod contract; -mod nft; +mod event; pub mod evm_def; +mod extension; +mod group; +mod nft; +mod sn_service; +mod spv; +mod tx; +mod types; +mod view; diff --git a/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs b/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs index 6130659d7..713a45b13 100644 --- a/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs +++ b/src/meta/cyfs-meta/src/executor/tx_proc/desc_proc.rs @@ -55,35 +55,60 @@ impl TxExecutor { let desc = ret.unwrap(); if desc.hash()? != tx.desc_hash { - error!("data hash mismatch!, except {}, actual {}", &tx.desc_hash, desc.hash()?); + error!( + "data hash mismatch!, except {}, actual {}", + &tx.desc_hash, + desc.hash()? + ); error!("tx data hex: {}", hex::encode(data)); error!("rust data hex: {}", hex::encode(desc.to_vec().unwrap())); return Err(meta_err!(ERROR_HASH_ERROR)); } let objid = context::id_from_desc(&desc); + let state_ref = context.ref_state().to_rc()?; + + if let SavedMetaObject::Group(group) = &desc { + group + .is_update_valid(None, &PeopleQuerier(state_ref.clone())) + .await?; + } //TODO:是否需要检测已经objid 已经有余额存在? // 是否需要校验caller能否创建desc? - context - .ref_state() - .to_rc()? - .create_obj_desc(&objid, &desc) - .await?; + state_ref.create_obj_desc(&objid, &desc).await?; if let SavedMetaObject::File(file) = &desc { if file.desc().owner().is_some() { - context.ref_state().to_rc()?.set_beneficiary(&file.desc().calculate_id(), file.desc().owner().as_ref().unwrap()).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary( + &file.desc().calculate_id(), + file.desc().owner().as_ref().unwrap(), + ) + .await?; } } else if let SavedMetaObject::Data(data) = &desc { if let Ok(obj) = AnyNamedObject::clone_from_slice(data.data.as_slice()) { if obj.owner().is_some() { - context.ref_state().to_rc()?.set_beneficiary(&obj.calculate_id(), obj.owner().as_ref().unwrap()).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary(&obj.calculate_id(), obj.owner().as_ref().unwrap()) + .await?; } } } else if let SavedMetaObject::Device(device) = &desc { if device.desc().owner().is_some() { - context.ref_state().to_rc()?.set_beneficiary(&device.desc().calculate_id(), device.desc().owner().as_ref().unwrap()).await?; + context + .ref_state() + .to_rc()? + .set_beneficiary( + &device.desc().calculate_id(), + device.desc().owner().as_ref().unwrap(), + ) + .await?; } } @@ -160,11 +185,29 @@ impl TxExecutor { // return Err(ERROR_ACCESS_DENIED); //} - let mut rent_state = context.ref_state().to_rc()?.get_desc_extra(&objid).await?; + let state_ref = context.ref_state().to_rc()?; + + let mut rent_state = state_ref.get_desc_extra(&objid).await?; if rent_state.rent_arrears > 0 { return Err(crate::meta_err!(ERROR_RENT_ARREARS)); } + if let SavedMetaObject::Group(group) = &desc { + let latest_group = state_ref.get_obj_desc(&objid).await?; + if let SavedMetaObject::Group(latest_group) = latest_group { + group + .is_update_valid(Some(&latest_group), &PeopleQuerier(state_ref.clone())) + .await?; + } else { + let msg = format!( + "Attempt get group({}) from different type.", + group.desc().object_id() + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); + } + } + context .ref_state() .to_rc()? @@ -278,3 +321,19 @@ impl TxExecutor { Ok(()) } } + +struct PeopleQuerier(StateRef); + +#[async_trait::async_trait] +impl MemberQuerier for PeopleQuerier { + async fn get_people(&self, people_id: &PeopleId) -> BuckyResult { + let obj = self.0.get_obj_desc(people_id.object_id()).await?; + if let SavedMetaObject::People(people) = obj { + Ok(people) + } else { + let msg = format!("Attempt get people({}) from different type.", people_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) + } + } +} From 3256def37afb1f7ad88af9810fcf37f7f08c8c07 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 10 Apr 2023 14:46:27 +0800 Subject: [PATCH 531/553] Refuse group with empty admins --- src/component/cyfs-base-meta/src/group.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index a97b79f5d..614056d47 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -85,6 +85,13 @@ impl GroupVerifier for Group { member_querier: &impl MemberQuerier, ) -> BuckyResult<()> { let group_id = self.desc().object_id(); + + if self.admins().len() == 0 { + let msg = format!("Update group({}) with no admins.", group_id); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let (last_admins, last_members) = match latest_group { Some(latest_group) => { let latest_group_id = latest_group.desc().object_id(); From 2318c47519a643fc2265db9cfe9bf28517f821ed Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 10 Apr 2023 16:13:24 +0800 Subject: [PATCH 532/553] Support `None` founder_id --- src/component/cyfs-base/src/objects/group.rs | 85 +++++++------------- 1 file changed, 29 insertions(+), 56 deletions(-) diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 29aee5849..5ddd02ae7 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -105,7 +105,7 @@ impl GroupDesc { impl Group { pub fn new_simple_group( - founder_id: ObjectId, + founder_id: Option, admins: Vec, area: Area, ) -> GroupBuilder { @@ -124,7 +124,7 @@ impl Group { .area(area) } - pub fn new_org(founder_id: ObjectId, area: Area) -> GroupBuilder { + pub fn new_org(founder_id: Option, area: Area) -> GroupBuilder { let desc_content = OrgDescContent { founder_id, unique_id: UniqueId::create_with_random(), @@ -139,6 +139,13 @@ impl Group { .area(area) } + pub fn founder_id(&self) -> &Option { + match self.desc().content() { + GroupDescContent::SimpleGroup(s) => &s.founder_id, + GroupDescContent::Org(o) => &o.founder_id, + } + } + pub fn name(&self) -> &str { self.common().name.as_str() } @@ -227,39 +234,6 @@ impl Group { pub fn set_prev_blob_id(&mut self, prev_blob_id: Option) { self.common_mut().prev_blob_id = prev_blob_id; } - // pub fn join_member( - // &self, - // member_id: &ObjectId, - // private_key: &PrivateKey, - // ) -> BuckyResult<&GroupJoinSignature> { - // unimplemented!() - // } - - // pub fn verify( - // &self, - // signature: &GroupJoinSignature, - // member_id: &ObjectId, - // public_key: &PublicKey, - // ) -> BuckyResult { - // unimplemented!() - // } - - // pub fn verify_member( - // &self, - // member_id: &ObjectId, - // is_admin: bool, - // public_key: &PublicKey, - // ) -> BuckyResult { - // unimplemented!() - // } - - // pub fn verify_members( - // &self, - // members: &[(ObjectId, PublicKey)], - // is_admin: bool, - // ) -> BuckyResult { - // unimplemented!() - // } pub fn is_simple_group(&self) -> bool { match self.desc().content() { @@ -354,19 +328,6 @@ impl Group { oods } - // pub fn group_hash(&self) -> ObjectId { - // let mut without_sign = self.clone(); - // without_sign.common_mut().join_signatures = vec![]; - - // let mut hash = HashValue::default(); - // let remain = without_sign - // .raw_encode(hash.as_mut_slice(), &Some(RawEncodePurpose::Hash)) - // .unwrap(); - // assert_eq!(remain.len(), 0); - - // ObjectId::from_slice_value(&hash.as_slice()[..31]) - // } - fn common(&self) -> &CommonGroupBodyContent { self.body().as_ref().unwrap().content().common() } @@ -506,18 +467,22 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { #[derive(Clone, Debug)] pub struct SimpleGroupDescContent { unique_id: UniqueId, - founder_id: ObjectId, + founder_id: Option, admins: Vec, } impl TryFrom for SimpleGroupDescContent { type Error = BuckyError; - fn try_from(value: protos::SimpleGroupDescContent) -> BuckyResult { + fn try_from(mut value: protos::SimpleGroupDescContent) -> BuckyResult { let ret = Self { + founder_id: if value.has_founder_id() { + ProtobufCodecHelper::decode_buf(value.take_founder_id())? + } else { + None + }, unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, admins: ProtobufCodecHelper::decode_value_list(value.admins)?, - founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, }; Ok(ret) @@ -531,7 +496,9 @@ impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { let mut ret = Self::new(); ret.unique_id = value.unique_id.to_vec()?; - ret.founder_id = value.founder_id.to_vec()?; + if let Some(founder_id) = value.founder_id.as_ref() { + ret.set_founder_id(founder_id.to_vec()?); + } ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); Ok(ret) @@ -584,16 +551,20 @@ impl TryFrom<&SimpleGroupBodyContent> for protos::SimpleGroupBodyContent { #[derive(Clone, Debug)] pub struct OrgDescContent { unique_id: UniqueId, - founder_id: ObjectId, + founder_id: Option, } impl TryFrom for OrgDescContent { type Error = BuckyError; - fn try_from(value: protos::OrgDescContent) -> BuckyResult { + fn try_from(mut value: protos::OrgDescContent) -> BuckyResult { let ret = Self { + founder_id: if value.has_founder_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_founder_id())?) + } else { + None + }, unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, - founder_id: ProtobufCodecHelper::decode_buf(value.founder_id)?, }; Ok(ret) @@ -607,7 +578,9 @@ impl TryFrom<&OrgDescContent> for protos::OrgDescContent { let mut ret = Self::new(); ret.unique_id = value.unique_id.to_vec()?; - ret.founder_id = value.founder_id.to_vec()?; + if let Some(founder_id) = value.founder_id.as_ref() { + ret.set_founder_id(founder_id.to_vec()?); + } Ok(ret) } From fffca53f9cabe0e582d591b2c373a0d695ee3edc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 10 Apr 2023 20:46:10 +0800 Subject: [PATCH 533/553] `desc-tools` for `Group` --- src/component/cyfs-base-meta/src/group.rs | 14 +- .../cyfs-base/protos/standard_objects.proto | 10 +- src/component/cyfs-base/src/codec/format.rs | 33 +- src/component/cyfs-base/src/objects/group.rs | 125 ++++++-- src/tests/group-example/src/main.rs | 2 +- src/tools/desc-tool/src/create.rs | 301 ++++++++++++------ src/tools/desc-tool/src/desc.rs | 31 +- src/tools/desc-tool/src/modify.rs | 160 ++++++++-- src/tools/desc-tool/src/show.rs | 92 +++++- src/tools/desc-tool/src/util.rs | 35 +- 10 files changed, 604 insertions(+), 199 deletions(-) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index 614056d47..34ee769e9 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -125,7 +125,19 @@ impl GroupVerifier for Group { log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } - None => ([].as_slice(), [].as_slice()), + None => { + if let Some(founder) = self.founder_id() { + if self.admins().iter().find(|m| &m.id == founder).is_none() { + let msg = format!( + "Update group({}) the founder({}) must be an administrator.", + group_id, founder + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + } + ([].as_slice(), [].as_slice()) + } }, }; diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index a363ec57a..e025fd753 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -66,9 +66,9 @@ message GroupMember { } message CommonGroupBodyContent { - string name = 1; - optional bytes icon = 2; - string description = 3; + optional string name = 1; + optional string icon = 2; + optional string description = 3; repeated GroupMember members = 4; @@ -81,7 +81,7 @@ message CommonGroupBodyContent { // simple_group message SimpleGroupDescContent { bytes unique_id = 1; - bytes founder_id = 2; + optional bytes founder_id = 2; repeated GroupMember admins = 3; } @@ -92,7 +92,7 @@ message SimpleGroupBodyContent { // org message OrgDescContent { bytes unique_id = 1; - bytes founder_id = 2; + optional bytes founder_id = 2; } message OrgBodyContent { diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index 75863c9d1..162f5066a 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -564,10 +564,19 @@ impl ObjectFormat for PeopleBodyContent { } } -// simple group +// group impl ObjectFormat for GroupDescContent { fn format_json(&self) -> serde_json::Value { - let map = serde_json::Map::new(); + let mut map = serde_json::Map::new(); + + JsonCodecHelper::encode_option_string_field( + &mut map, + "founder", + self.founder_id().as_ref(), + ); + if let GroupDescContent::SimpleGroup(simple_group) = self { + JsonCodecHelper::encode_str_array_field(&mut map, "admins", simple_group.admins()); + } map.into() } @@ -577,13 +586,25 @@ impl ObjectFormat for GroupBodyContent { fn format_json(&self) -> serde_json::Value { let mut map = serde_json::Map::new(); - JsonCodecHelper::encode_string_field(&mut map, "name", self.name()); - JsonCodecHelper::encode_str_array_field( + JsonCodecHelper::encode_option_string_field(&mut map, "name", self.name().as_ref()); + JsonCodecHelper::encode_option_string_field(&mut map, "icon", self.icon().as_ref()); + JsonCodecHelper::encode_option_string_field( &mut map, - "members", - &self.members().iter().map(|m| m.id).collect_vec(), + "description", + self.description().as_ref(), ); + + if let GroupBodyContent::Org(org) = self { + JsonCodecHelper::encode_str_array_field(&mut map, "admins", org.admins()); + } + JsonCodecHelper::encode_str_array_field(&mut map, "members", self.members()); JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", self.ood_list()); + JsonCodecHelper::encode_option_string_field( + &mut map, + "prev_blob_id", + self.prev_blob_id().as_ref(), + ); + JsonCodecHelper::encode_string_field(&mut map, "version", &self.version()); map.into() } diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 5ddd02ae7..70c3c0342 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -2,6 +2,7 @@ use crate::codec as cyfs_base; use crate::*; use std::convert::TryFrom; +use std::str::FromStr; pub enum GroupMemberScope { Admin, @@ -15,6 +16,15 @@ pub enum GroupDescContent { Org(OrgDescContent), } +impl GroupDescContent { + pub fn founder_id(&self) -> &Option { + match self { + GroupDescContent::SimpleGroup(desc) => &desc.founder_id, + GroupDescContent::Org(desc) => &desc.founder_id, + } + } +} + #[derive(Clone, Debug, RawEncode, RawDecode)] pub enum GroupBodyContent { SimpleGroup(SimpleGroupBodyContent), @@ -39,16 +49,16 @@ impl BodyContent for GroupBodyContent { } impl GroupBodyContent { - pub fn name(&self) -> &str { - self.common().name.as_str() + pub fn name(&self) -> &Option { + &self.common().name } - pub fn icon(&self) -> &Option { + pub fn icon(&self) -> &Option { &self.common().icon } - pub fn description(&self) -> &str { - self.common().description.as_str() + pub fn description(&self) -> &Option { + &self.common().description } pub fn members(&self) -> &Vec { @@ -146,27 +156,27 @@ impl Group { } } - pub fn name(&self) -> &str { - self.common().name.as_str() + pub fn name(&self) -> &Option { + &self.common().name } - pub fn set_name(&mut self, name: String) { + pub fn set_name(&mut self, name: Option) { self.common_mut().name = name; } - pub fn icon(&self) -> &Option { + pub fn icon(&self) -> &Option { &self.common().icon } - pub fn set_icon(&mut self, icon: Option) { + pub fn set_icon(&mut self, icon: Option) { self.common_mut().icon = icon; } - pub fn description(&self) -> &str { - self.common().description.as_str() + pub fn description(&self) -> &Option { + &self.common().description } - pub fn set_description(&mut self, description: String) { + pub fn set_description(&mut self, description: Option) { self.common_mut().description = description; } @@ -344,6 +354,9 @@ pub struct GroupMember { } impl GroupMember { + pub fn new(id: ObjectId, title: String) -> Self { + GroupMember { id, title } + } pub fn from_member_id(id: ObjectId) -> GroupMember { GroupMember { id, @@ -378,11 +391,41 @@ impl TryFrom<&GroupMember> for protos::GroupMember { } } +impl FromStr for GroupMember { + type Err = BuckyError; + + fn from_str(s: &str) -> Result { + let mut fields = s.split(":"); + + let id = if let Some(id) = fields.next() { + PeopleId::from_str(id)? + } else { + return Err(BuckyError::new( + BuckyErrorCode::InvalidFormat, + "need peopleid of member.", + )); + }; + + let title = fields.next().unwrap_or(""); + + Ok(Self { + id: id.object_id().clone(), + title: title.to_string(), + }) + } +} + +impl ToString for GroupMember { + fn to_string(&self) -> String { + format!("{}:{}", self.id, self.title) + } +} + #[derive(Clone, Debug, Default)] struct CommonGroupBodyContent { - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, members: Vec, @@ -394,9 +437,9 @@ struct CommonGroupBodyContent { impl CommonGroupBodyContent { fn new( - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, members: Vec, ood_list: Vec, ) -> Self { @@ -417,13 +460,21 @@ impl TryFrom for CommonGroupBodyContent { fn try_from(mut value: protos::CommonGroupBodyContent) -> BuckyResult { let ret = Self { - name: value.take_name(), + name: if value.has_name() { + Some(value.take_name()) + } else { + None + }, icon: if value.has_icon() { - Some(ProtobufCodecHelper::decode_buf(value.take_icon())?) + Some(value.take_icon()) + } else { + None + }, + description: if value.has_description() { + Some(value.take_description()) } else { None }, - description: value.take_description(), members: ProtobufCodecHelper::decode_value_list(value.take_members())?, ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, version: value.version, @@ -444,11 +495,15 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { fn try_from(value: &CommonGroupBodyContent) -> BuckyResult { let mut ret = Self::new(); - ret.name = value.name.clone(); - if let Some(icon) = &value.icon { - ret.set_icon(icon.to_vec()?); + if let Some(name) = value.name.as_ref() { + ret.set_name(name.clone()); + } + if let Some(icon) = value.icon.as_ref() { + ret.set_icon(icon.clone()); + } + if let Some(description) = value.description.as_ref() { + ret.set_description(description.clone()); } - ret.description = value.description.clone(); ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( @@ -471,6 +526,12 @@ pub struct SimpleGroupDescContent { admins: Vec, } +impl SimpleGroupDescContent { + pub fn admins(&self) -> &Vec { + &self.admins + } +} + impl TryFrom for SimpleGroupDescContent { type Error = BuckyError; @@ -512,9 +573,9 @@ pub struct SimpleGroupBodyContent { impl SimpleGroupBodyContent { fn new( - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, members: Vec, ood_list: Vec, ) -> Self { @@ -594,9 +655,9 @@ pub struct OrgBodyContent { impl OrgBodyContent { fn new( - name: String, - icon: Option, - description: String, + name: Option, + icon: Option, + description: Option, admins: Vec, members: Vec, ood_list: Vec, diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 8186031b8..bc8b5fded 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -174,7 +174,7 @@ mod Common { ) -> Group { log::info!("create group"); - let mut group = Group::new_org(founder.desc().object_id(), Area::default()).build(); + let mut group = Group::new_org(Some(founder.desc().object_id()), Area::default()).build(); group.check_org_body_content_mut().set_admins( admins .iter() diff --git a/src/tools/desc-tool/src/create.rs b/src/tools/desc-tool/src/create.rs index 2e9b8e842..0671520f5 100644 --- a/src/tools/desc-tool/src/create.rs +++ b/src/tools/desc-tool/src/create.rs @@ -1,17 +1,28 @@ -use clap::{ArgMatches, App, SubCommand, Arg}; use crate::desc; -use crate::util::{get_objids_from_matches, get_deviceids_from_matches}; -use std::path::{Path}; +use crate::desc::create_people_desc; +use crate::util::{ + get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches, +}; +use clap::{App, Arg, ArgMatches, SubCommand}; +use cyfs_base::{ + sign_and_set_named_object_desc, Area, DeviceCategory, FileEncoder, + NamedObject, ObjectDesc, ObjectId, RsaCPUObjectSigner, SignatureSource, + SIGNATURE_SOURCE_REFINDEX_OWNER, SIGNATURE_SOURCE_REFINDEX_SELF, BuckyResult, +}; use log::*; -use cyfs_base::{Area, FileEncoder, NamedObject, ObjectDesc, AnyNamedObject, FileDecoder, PublicKeyRef, DeviceCategory, ObjectId, RsaCPUObjectSigner, sign_and_set_named_object_desc, SignatureSource, SIGNATURE_SOURCE_REFINDEX_SELF, SIGNATURE_SOURCE_REFINDEX_OWNER}; -use std::str::FromStr; use std::io::Write; -use crate::desc::create_people_desc; - +use std::path::Path; +use std::str::FromStr; pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { - let id_file_arg = Arg::with_name("id_file").long("idfile").takes_value(true).help("write object id to file"); - let save_path = Arg::with_name("save_path").long("savepath").takes_value(true).help("save file path"); + let id_file_arg = Arg::with_name("id_file") + .long("idfile") + .takes_value(true) + .help("write object id to file"); + let save_path = Arg::with_name("save_path") + .long("savepath") + .takes_value(true) + .help("save file path"); SubCommand::with_name("create").about("create desc") .subcommand(SubCommand::with_name("people").about("create people desc and sec") .arg(Arg::with_name("owner").long("owner").short("o").takes_value(true) @@ -24,15 +35,25 @@ pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { .arg(Arg::with_name("area").long("area").short("a").takes_value(true) .help("Object area info, if not set,will calc base ip. format [county:carrier:city:inner]")) .arg(id_file_arg.clone()).arg(save_path.clone())) - .subcommand(SubCommand::with_name("sgroup").about("create sgroup desc") - .arg(Arg::with_name("threshold").long("threshold").default_value("1").required(true) - .help("threshold in simple group")) + .subcommand(SubCommand::with_name("group").about("create group desc") + .arg(Arg::with_name("founder").long("founder").short("f") + .help("founder of group")) + .arg(Arg::with_name("admins").required(true).long("admins").short("A").value_delimiter(";") + .help("admins in group. format [peopleid:title]")) .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";") - .help("members in simple group")) + .help("members in group. format [peopleid:title]")) .arg(Arg::with_name("ood_list").long("oodlist").short("l").value_delimiter(";") .help("oods in group")) - .arg(Arg::with_name("owners").long("owners").short("o").value_delimiter(";") - .help("group owners, must have desc file in same path")) + .arg(Arg::with_name("name").long("name").short("n") + .help("name of group")) + .arg(Arg::with_name("icon").long("icon").short("I") + .help("icon of group")) + .arg(Arg::with_name("description").long("description").short("d") + .help("description of group")) + .arg(Arg::with_name("area").required(true).long("area").short("a").takes_value(true) + .help("Object area info. format [county:carrier:city:inner]")) + .arg(Arg::with_name("org").long("org").short("O").takes_value(false) + .help("create a group as organization that administrators is changable.")) .arg(id_file_arg.clone()).arg(save_path.clone())) .subcommand(SubCommand::with_name("device").about("create device desc and sec") .arg(Arg::with_name("area").long("area").short("a").takes_value(true) @@ -71,14 +92,23 @@ fn write_id_file(matches: &ArgMatches, id: &ObjectId) { } fn get_area(matches: &ArgMatches) -> Option { - matches.value_of("area").map(|str_area| { - match Area::from_str(str_area) { + matches + .value_of("area") + .map(|str_area| match Area::from_str(str_area) { Ok(area) => area, Err(_) => { error!("decode area from {} fail, use default", str_area); Area::default() - }, - } + } + }) +} + +fn get_area_no_default(matches: &ArgMatches) -> BuckyResult> { + matches.value_of("area").map_or(Ok(None), |str_area| { + Area::from_str(str_area).map(|a| Some(a)).map_err(|e| { + error!("decode area from {} fail", str_area); + e + }) }) } @@ -88,17 +118,17 @@ fn get_key_bits(matches: &ArgMatches) -> usize { "rsa2048" => 2048, "rsa3072" => 3072, "secp" => 1, - _ => 0 + _ => 0, } } pub async fn create_desc(matches: &ArgMatches<'_>) { match matches.subcommand() { ("device", Some(matches)) => { - let owner = matches.value_of("owner").map(|str| { - ObjectId::from_str(str).unwrap() - }); - let sn_list = get_deviceids_from_matches(matches,"snlist").unwrap_or(vec![]); + let owner = matches + .value_of("owner") + .map(|str| ObjectId::from_str(str).unwrap()); + let sn_list = get_deviceids_from_matches(matches, "snlist").unwrap_or(vec![]); let eps = matches.values_of_lossy("eps").unwrap_or(vec![]); let str_unique_id = matches.value_of("deviceid").unwrap(); @@ -116,79 +146,41 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { "pc" => DeviceCategory::PC, "server" => DeviceCategory::Server, "browser" => DeviceCategory::Browser, - _ => {unreachable!()} + _ => { + unreachable!() + } }; let area = get_area(matches); let save_path = matches.value_of("save_path").unwrap_or("").to_owned(); - if let Some((device, _)) = desc::create_device_desc(area, category, key_bits, str_unique_id, owner, eps, sn_list, Some(save_path)) { + if let Some((device, _)) = desc::create_device_desc( + area, + category, + key_bits, + str_unique_id, + owner, + eps, + sn_list, + Some(save_path), + ) { write_id_file(matches, &device.desc().calculate_id()); } return; } - ("sgroup", Some(matches)) => { - // TODO - // match matches.value_of("threshold").unwrap().parse::() { - // Ok(threshold) => { - // let owners = if let Some(strs) = matches.values_of_lossy("owners") { - // let mut owners = vec![]; - // for str in &strs { - // if let Ok((obj, _)) = AnyNamedObject::decode_from_file(&Path::new(str).with_extension("desc"), &mut vec![]) { - // if let Some(pk) = obj.public_key() { - // match pk { - // PublicKeyRef::Single(pk) => {owners.push(pk.clone())} - // PublicKeyRef::MN((_, pks)) => { - // owners.append(&mut pks.clone()) - // } - // } - // } else { - // warn!("desc {} not have pubkey, ignore", str); - // } - // } else { - // error!("decode desc file {} fail", str); - // } - // } - // owners - // } else { - // vec![] - // }; - - // if threshold as usize > owners.len() { - // error!("threshold must small owners count, detail info use --help"); - // return; - // } - - // let group_desc = desc::create_simple_group_desc(threshold - // , owners - // , get_objids_from_matches(matches, "members") - // , get_deviceids_from_matches(matches, "ood_list")); - - // let groupid = group_desc.desc().calculate_id(); - // let desc_file = Path::new(matches.value_of("save_path").unwrap_or("")).join(&groupid.to_string()).with_extension("desc"); - // if let Err(e) = group_desc.encode_to_file(&desc_file, true) { - // error!("write imple group desc file failed, err {}", e); - // } else { - // info!("write simple group desc file succ to {}", desc_file.display()); - // write_id_file(matches, &groupid); - // }; - // }, - // Err(_e) => { - // error!("threshold must number, detail info use --help"); - // return; - // } - // } - } + ("group", Some(matches)) => create_group_desc(matches).await, ("people", Some(matches)) => { - let owner_id = matches.value_of("owner").map(|str| { - ObjectId::from_str(str).unwrap() - }); + let owner_id = matches + .value_of("owner") + .map(|str| ObjectId::from_str(str).unwrap()); let ood_list = get_deviceids_from_matches(matches, "ood_list").unwrap_or(vec![]); let key_bits = get_key_bits(matches); let area = get_area(matches); let (people, secret) = create_people_desc(area, key_bits, owner_id, ood_list); let objid = people.desc().calculate_id(); - let file_path = Path::new(matches.value_of("save_path").unwrap_or("")).join(&objid.to_string()).with_extension("desc"); + let file_path = Path::new(matches.value_of("save_path").unwrap_or("")) + .join(&objid.to_string()) + .with_extension("desc"); if let Err(e) = people.encode_to_file(&file_path, true) { error!("write people file failed, err {}", e); } else { @@ -209,24 +201,66 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { let people_id = people.desc().calculate_id(); // 再创建ood,使用people为owner - let (mut ood_desc, ood_sec) = desc::create_device_desc(area.clone(), DeviceCategory::OOD, key_bits, "ood", Some(people_id.clone()) - , vec![], vec![], None).unwrap(); + let (mut ood_desc, ood_sec) = desc::create_device_desc( + area.clone(), + DeviceCategory::OOD, + key_bits, + "ood", + Some(people_id.clone()), + vec![], + vec![], + None, + ) + .unwrap(); // 修改people的ood_list people.ood_list_mut().push(ood_desc.desc().device_id()); // 再创建client,使用people为owner - let (mut client_desc, client_sec) = desc::create_device_desc(area, DeviceCategory::PC, key_bits, "client", Some(people_id.clone()) - , vec![], vec![], None).unwrap(); + let (mut client_desc, client_sec) = desc::create_device_desc( + area, + DeviceCategory::PC, + key_bits, + "client", + Some(people_id.clone()), + vec![], + vec![], + None, + ) + .unwrap(); let signer = RsaCPUObjectSigner::new(people_sec.public(), people_sec.clone()); // 给desc签名 - sign_and_set_named_object_desc(&signer, &mut people, &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF)).await.unwrap(); - sign_and_set_named_object_desc(&signer, &mut ood_desc, &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER)).await.unwrap(); - sign_and_set_named_object_desc(&signer, &mut client_desc, &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER)).await.unwrap(); + sign_and_set_named_object_desc( + &signer, + &mut people, + &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_SELF), + ) + .await + .unwrap(); + sign_and_set_named_object_desc( + &signer, + &mut ood_desc, + &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); + sign_and_set_named_object_desc( + &signer, + &mut client_desc, + &SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER), + ) + .await + .unwrap(); let file_path = Path::new(matches.value_of("save_path").unwrap_or("")); // 存储这些对象 let mut postfix = String::from(""); - if Path::new(&file_path.join(format!("device{}", &postfix)).with_extension("desc")).exists() { + if Path::new( + &file_path + .join(format!("device{}", &postfix)) + .with_extension("desc"), + ) + .exists() + { postfix = chrono::Local::now().format("-%F-%H-%M-%S").to_string(); } let people_file = file_path.join(format!("people{}", &postfix)); @@ -255,11 +289,94 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { if let Err(e) = client_sec.encode_to_file(&client_file.with_extension("sec"), false) { error!("write client sec failed, err {}", e); } - } v @ _ => { error!("not support create type {}", v.0); return; } } -} \ No newline at end of file +} + +pub async fn create_group_desc(matches: &ArgMatches<'_>) { + let admins = match get_group_members_from_matches(matches, "admins") { + Ok(admins) => { + if admins.len() == 0 { + log::error!("empty admins."); + return; + } + admins + } + Err(e) => { + log::error!("invalid admins: {}", e.msg()); + return; + } + }; + + let area = match get_area_no_default(matches) { + Ok(area) => match area { + Some(area) => area, + None => { + log::error!("area is expected, detail info use --help"); + return; + } + }, + Err(_) => return, + }; + + let founder = match matches.value_of("founder") { + Some(str) => match ObjectId::from_str(str) { + Ok(id) => Some(id), + Err(_) => { + log::error!("invalid founder: {}", str); + return; + } + }, + None => None, + }; + + let members = match get_group_members_from_matches(matches, "members") { + Ok(members) => members, + Err(e) => { + log::error!("invalid members: {}", e.msg()); + return; + } + }; + + let ood_list = get_deviceids_from_matches(matches, "ood_list").unwrap_or(vec![]); + if ood_list.len() == 0 { + log::error!("no valid ood found."); + return; + } + + let name = matches.value_of("name").map(|s| s.into()); + let icon = matches.value_of("icon").map(|s| s.into()); + let description = matches.value_of("description").map(|s| s.into()); + let is_org = matches.is_present("org"); + + let group_desc = desc::create_group_desc( + founder, + admins, + members, + ood_list, + area, + name, + icon, + description, + is_org, + ); + + let groupid = group_desc.desc().calculate_id(); + let desc_file = Path::new(matches.value_of("save_path").unwrap_or("")) + .join(&groupid.to_string()) + .with_extension("desc"); + if let Err(e) = group_desc.encode_to_file(&desc_file, true) { + error!("write group desc file failed, err {}", e); + } else { + info!( + "write group({}) desc file succ to {}", + groupid, + desc_file.display() + ); + write_id_file(matches, &groupid); + }; +} diff --git a/src/tools/desc-tool/src/desc.rs b/src/tools/desc-tool/src/desc.rs index 58b6a250e..42b971d19 100644 --- a/src/tools/desc-tool/src/desc.rs +++ b/src/tools/desc-tool/src/desc.rs @@ -3,19 +3,30 @@ use log::*; use std::path::Path; use std::str::FromStr; -pub fn create_simple_group_desc( - founder_id: ObjectId, +pub fn create_group_desc( + founder_id: Option, admins: Vec, - conclusion_limit: Option, + members: Vec, + oods: Vec, area: Area, + name: Option, + icon: Option, + description: Option, + is_org: bool, ) -> Group { - let area_info = Area::default(); - Group::new_simple_group(founder_id, admins, conclusion_limit, area).build() -} - -pub fn create_org_desc(founder_id: ObjectId, area: Area) -> Group { - let area_info = Area::default(); - Group::new_org(founder_id, area).build() + let mut group = if is_org { + let mut group = Group::new_org(founder_id, area).build(); + group.check_org_body_content_mut().set_admins(admins); + group + } else { + Group::new_simple_group(founder_id, admins, area).build() + }; + group.set_members(members); + group.set_ood_list(oods); + group.set_name(name); + group.set_icon(icon); + group.set_description(description); + group } pub fn create_people_desc( diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index 8f97b3f8a..cec413f4c 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -1,8 +1,9 @@ use clap::{App, SubCommand, Arg, ArgMatches}; -use crate::util::{get_objids_from_matches, get_eps_from_matches, get_deviceids_from_matches}; +use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches}; use log::*; -use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc}; +use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId}; use cyfs_core::{CoreObjectType, DecApp, DecAppObj, AppList, AppStatus, AppListObj, AppStatusObj, DecAppId}; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::str::FromStr; @@ -11,11 +12,17 @@ pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { .arg(Arg::with_name("desc").required(true).index(1).help("desc file to modify")) .arg(Arg::with_name("sn").short("s").long("sn").value_delimiter(";").help("new sn list")) .arg(Arg::with_name("eps").long("eps").short("e").value_delimiter(";").help("new endpoint list")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("members set to simple group")) - .arg(Arg::with_name("add_members").long("add").short("a").value_delimiter(";").help("members append to simple group")) - .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people")) - .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people")) - .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("people name")) + .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("administrators set to group")) + .arg(Arg::with_name("add_admins").long("add_admin").short("aA").value_delimiter(";").help("administrators append to group")) + .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("members set to group")) + .arg(Arg::with_name("add_members").long("add_member").short("am").value_delimiter(";").help("members append to group")) + .arg(Arg::with_name("description").short("d").long("description").takes_value(true).help("description of group")) + .arg(Arg::with_name("version").short("v").long("version").takes_value(true).help("version of group")) + .arg(Arg::with_name("prev_blob_id").short("p").long("prev").takes_value(true).help("prev-blob-id of group")) + .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people or group")) + .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people or group")) + .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("name of people or group")) + .arg(Arg::with_name("icon").short("I").long("icon").takes_value(true).help("icon of people or group")) .arg(Arg::with_name("source").long("source").value_delimiter(";").help("add source to app, {ver}:{id}")) .arg(Arg::with_name("app_id").long("appid").takes_value(true).help("app id add to app list")) .arg(Arg::with_name("app_ver").long("appver").takes_value(true).help("app ver add to app list")) @@ -42,23 +49,9 @@ pub fn modify_desc(matches: &ArgMatches) { info!("modify success"); }, StandardObject::Group(mut g) => { - // TODO - // let content = g.body_mut().as_mut().unwrap().content_mut(); - // if let Some(members) = get_objids_from_matches(matches, "members") { - // content.members_mut().clone_from(&members); - // } - - // if let Some(members) = get_objids_from_matches(matches, "add_members") { - // for member in members { - // if !content.members_mut().contains(&member) { - // content.members_mut().push(member); - // } else { - // info!("obj {} already in group, skip.", &member); - // } - // } - // } - - // g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + if modify_group_desc(&mut g, matches).is_ok() { + g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + } } StandardObject::People(mut p) => { let content = p.body_mut().as_mut().unwrap().content_mut(); @@ -71,7 +64,7 @@ pub fn modify_desc(matches: &ArgMatches) { if !content.ood_list_mut().contains(&ood) { content.ood_list_mut().push(ood); } else { - info!("obj {} already in group, skip.", &ood); + info!("obj {} already exist, skip.", &ood); } } } @@ -80,6 +73,15 @@ pub fn modify_desc(matches: &ArgMatches) { content.set_name(name.to_owned()); } + if let Some(icon) = matches.value_of("icon") { + match FileId::from_str(icon) { + Ok(icon) => content.set_icon(icon), + Err(_) => { + warn!("invalid icon {}", icon); + }, + } + } + p.encode_to_file(path.as_ref(), false).expect("write desc file err"); } _ => { @@ -127,4 +129,112 @@ pub fn modify_desc(matches: &ArgMatches) { error!("read desc from file {} failed, err {}", path, e); }, } +} + +fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> { + let group_id = group.desc().object_id(); + + match get_group_members_from_matches(matches, "members") { + Ok(members) => { + group.set_members(members); + }, + Err(err) => { + log::error!("update group({}) failed for invalid member.", group_id); + return Err(err); + } + } + + match get_group_members_from_matches(matches, "add_members") { + Ok(additional_members) => { + let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); + additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); + group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + }, + Err(err) => { + log::error!("update group({}) failed for invalid member.", group_id); + return Err(err); + } + } + + match get_group_members_from_matches(matches, "admins") { + Ok(admins) => { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + org.set_admins(admins); + }, + Err(err) => { + log::error!("update group({}) failed for invalid administrator.", group_id); + return Err(err); + } + } + + match get_group_members_from_matches(matches, "add_admins") { + Ok(additional_admins) => { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); + additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); + org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + }, + Err(err) => { + log::error!("update group({}) failed for invalid administrator.", group_id); + return Err(err); + } + } + + match get_deviceids_from_matches(matches, "ood_lists") { + Some(oods) => { + group.set_ood_list(oods); + }, + None => { + group.set_ood_list(vec![]); + } + } + if let Some(additional_oods) = get_deviceids_from_matches(matches, "add_oods") { + let mut oods = HashSet::::from_iter(group.ood_list().iter().map(|id| id.clone())); + additional_oods.into_iter().for_each(|id| {oods.insert(id);}); + group.set_ood_list(oods.into_iter().collect()); + } + + if let Some(description) = matches.value_of("description") { + group.set_description(Some(description.to_string())); + } + + if let Some(icon) = matches.value_of("icon") { + group.set_icon(Some(icon.to_string())); + } + + if let Some(version) = matches.value_of("version") { + let version = match version.parse::() { + Ok(v) => v, + Err(e) => { + let msg = format!("update group({}) failed for invalid version {}, err: {:?}", group_id, version, e); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + group.set_version(version); + } + + if let Some(prev_blob_id) = matches.value_of("prev_blob_id") { + let prev_blob_id = match ObjectId::from_str(prev_blob_id) { + Ok(prev_blob_id) => prev_blob_id, + Err(e) => { + let msg = format!("update group({}) failed for invalid prev-blob-id {}", group_id, prev_blob_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); + } + }; + group.set_prev_blob_id(Some(prev_blob_id)); + } + + Ok(()) } \ No newline at end of file diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index 3db58180d..5125ee948 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -1,5 +1,9 @@ use clap::{App, Arg, ArgMatches, SubCommand}; -use cyfs_base::{AnyNamedObject, ChunkList, Dir, DirBodyContent, File, FileDecoder, InnerNode, NDNObjectInfo, NamedObject, ObjectDesc, RawEncode, RawFrom, SignatureSource, SingleKeyObjectDesc, StandardObject, AreaObjectDesc}; +use cyfs_base::{ + AnyNamedObject, AreaObjectDesc, ChunkList, Dir, DirBodyContent, File, FileDecoder, Group, + InnerNode, NDNObjectInfo, NamedObject, ObjectDesc, RawEncode, RawFrom, SignatureSource, + SingleKeyObjectDesc, StandardObject, +}; use cyfs_core::{AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj}; use std::convert::TryFrom; use std::path::Path; @@ -41,13 +45,19 @@ pub fn show_desc_subcommand<'a, 'b>() -> App<'a, 'b> { Arg::with_name("show_members") .short("m") .long("member") - .help("show members in simple group"), + .help("show members in group"), + ) + .arg( + Arg::with_name("show_admins") + .short("A") + .long("admins") + .help("show administrators in group"), ) .arg( Arg::with_name("show_oodlist") .short("l") .long("ood_list") - .help("show ood_list in people"), + .help("show ood_list in people or group"), ) .arg( Arg::with_name("all") @@ -159,6 +169,66 @@ fn show_dir(dir: &Dir, matches: &ArgMatches) { } } +fn show_group(group: &Group, matches: &ArgMatches) { + println!("desc type: Group"); + let is_all = matches.is_present("all"); + + if is_all { + println!("name: {}", group.name().as_ref().map_or("", |n| n.as_str())); + println!( + "founder: {}", + group.founder_id().map_or("".to_string(), |f| f.to_string()) + ); + println!("icon: {}", group.icon().as_ref().map_or("", |icon| icon.as_str())); + println!( + "description: {}", + group.description().as_ref().map_or("", |d| d.as_str()) + ); + println!( + "area: {}", + group.desc().area().as_ref().map_or("None".to_string(), |a| a.to_string()) + ); + println!("version: {}", group.version()); + println!( + "prev-blob-id: {}", + group + .prev_blob_id() + .map_or("None".to_string(), |prev| prev.to_string()) + ); + } + + if is_all || matches.is_present("show_admins") { + print!( + "administrators({}): [", + if group.is_org() { + "mutable" + } else { + "immutable" + } + ); + for member in group.admins() { + print!("{}, ", member.to_string()); + } + println!("]"); + } + + if is_all || matches.is_present("show_members") { + print!("members: ["); + for member in group.members() { + print!("{}, ", member.to_string()); + } + println!("]"); + } + + if is_all || matches.is_present("show_oodlist") { + print!("ood_list: ["); + for ood in group.ood_list() { + print!("{}, ", ood); + } + println!("]"); + } +} + pub fn show_desc(matches: &ArgMatches) { let path = Path::new(matches.value_of("desc_file").unwrap()); let mut file_buf = vec![]; @@ -216,7 +286,6 @@ pub fn show_desc(matches: &ArgMatches) { if let Some(area) = p.desc().area() { println!("area: {}", area) } - } if matches.is_present("all") || matches.is_present("show_endpoint") { print!("endpoint: ["); @@ -237,7 +306,9 @@ pub fn show_desc(matches: &ArgMatches) { let pubkey = p.desc().public_key(); let mut buf = vec![]; buf.resize(pubkey.raw_measure(&None).unwrap(), 0); - pubkey.raw_encode(&mut buf, &None).expect("encode pubkey err"); + pubkey + .raw_encode(&mut buf, &None) + .expect("encode pubkey err"); println!("pubkey: {}", hex::encode(&buf)); println!("createtime: {}", p.desc().create_time()); println!("device catelogy: {}", p.category().unwrap()) @@ -251,16 +322,7 @@ pub fn show_desc(matches: &ArgMatches) { ua.desc().content().right() ); } - StandardObject::Group(g) => { - println!("desc type: Group"); - if matches.is_present("all") || matches.is_present("show_members") { - print!("members: ["); - for owner in g.body().as_ref().unwrap().content().members() { - print!("{}, ", owner.id); - } - println!("]"); - } - } + StandardObject::Group(g) => show_group(g, matches), StandardObject::File(f) => { show_file(f, matches); } diff --git a/src/tools/desc-tool/src/util.rs b/src/tools/desc-tool/src/util.rs index 6111220dd..c25854018 100644 --- a/src/tools/desc-tool/src/util.rs +++ b/src/tools/desc-tool/src/util.rs @@ -1,20 +1,18 @@ use clap::ArgMatches; +use cyfs_base::{DeviceId, Endpoint, GroupMember, ObjectId, BuckyResult}; use log::*; -use std::str::FromStr; -use cyfs_base::{ObjectId, Endpoint, DeviceId}; use std::convert::TryFrom; +use std::str::FromStr; pub fn get_objids_from_matches(matches: &ArgMatches, name: &str) -> Option> { if let Some(strs) = matches.values_of_lossy(name) { let mut ret = vec![]; for str in &strs { match ObjectId::from_str(str) { - Ok(obj) => { - ret.push(obj) - }, + Ok(obj) => ret.push(obj), Err(_) => { error!("{} not valid objid, ignore", str); - }, + } } } Some(ret) @@ -24,7 +22,7 @@ pub fn get_objids_from_matches(matches: &ArgMatches, name: &str) -> Option Option> { - get_objids_from_matches(matches, name).map(|objs|{ + get_objids_from_matches(matches, name).map(|objs| { let mut ret = vec![]; for obj in &objs { if let Ok(device_id) = DeviceId::try_from(obj) { @@ -42,16 +40,29 @@ pub fn get_eps_from_matches(matches: &ArgMatches, name: &str) -> Option { - ret.push(obj) - }, + Ok(obj) => ret.push(obj), Err(_) => { error!("{} not valid endpoint, ignore", str); - }, + } } } Some(ret) } else { None } -} \ No newline at end of file +} + +pub fn get_group_members_from_matches( + matches: &ArgMatches, + name: &str, +) -> BuckyResult> { + if let Some(strs) = matches.values_of_lossy(name) { + let mut ret = vec![]; + for str in &strs { + ret.push(GroupMember::from_str(str)?); + } + Ok(ret) + } else { + Ok(vec![]) + } +} From 26daa3c4527b265d738c557f12b17e9c161f5753 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 11 Apr 2023 17:30:12 +0800 Subject: [PATCH 534/553] `desc-tool` for `Group`: debug --- src/tools/desc-tool/src/create.rs | 32 +++++----- src/tools/desc-tool/src/modify.rs | 97 ++++++++++++++++++++----------- src/tools/desc-tool/src/show.rs | 6 +- src/tools/desc-tool/src/util.rs | 6 +- 4 files changed, 88 insertions(+), 53 deletions(-) diff --git a/src/tools/desc-tool/src/create.rs b/src/tools/desc-tool/src/create.rs index 0671520f5..b00612d7a 100644 --- a/src/tools/desc-tool/src/create.rs +++ b/src/tools/desc-tool/src/create.rs @@ -1,7 +1,7 @@ use crate::desc; use crate::desc::create_people_desc; use crate::util::{ - get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches, + get_deviceids_from_matches, get_group_members_from_matches, }; use clap::{App, Arg, ArgMatches, SubCommand}; use cyfs_base::{ @@ -14,6 +14,8 @@ use std::io::Write; use std::path::Path; use std::str::FromStr; +// .\desc-tool.exe create group -F=5r4MYfFfTakY1h6vdEuMurpkawk4MZpB5RmY9CFqSj99 -A=5r4MYfFfTakY1h6vdEuMurpkawk4MZpB5RmY9CFqSj99:;5r4MYfFPPRDNNcJdvve4XVx3FE355PUDpqaA5Mm9UcFh:;5r4MYfFAiXjbEkHZvc1NtHgJkZ4A7LJQcrY7cJeMz5YB:;5r4MYfFKmpMT2u2P13p3bLC6KtGEVsp42X85h5e2onhZ:; -M=5r4MYfF5r9cUfL9JemVXwLWJjufXETYSjfXqEsR3Qwn5:;5r4MYfF8ZaksbXfnZbdjiYJuJv8U4FfvyBgdHq7RiPhY:;5r4MYfFQxUB7okJMvia5yGksrkMBzPrUrwCFgja4Djv3:;5r4MYfFXjPJ9BBYvvdP5QHudAWLNrMzuzZpNpr45pYEc:;5r4MYfFXuCNgbhRPaqtUKsNvNH1RNGF5prFXg7UqiWDS:;5r4MYfFJHxPCYqwLWrHQ24jjv3ZvCbK4dPhBCNn8r3aE:;5r4MYfFXAtLvsW52oCRRAALEt7rEJB7qUdRDEEKAgPJJ:;5r4MYfFdFYt8ytAw9noVjg1aXfeQvHWpaChax73wWKwJ:;5r4MYfFbDWG8jibePJhSoL25mv6tv6ZMDaMZHRzKVEEB:; -l=5aSixgN8tVt1SAM4xBfc1dYvdrU7d5fVeZrzNFpx8FiB;5aSixgMxgNuMQFcG41fW1CN7MTsKMqEuVjW16BnJWrGW;5aSixgN64mtdhmNvKZ681P3iPZbnQPyQsezTFNB2HSdx;5aSixgNS8ij1mkjjNe2UWHVgVYFhr4dJF5BuxxpTb1m8; -n="group" -I="icon" -d="description" -a=0:0:0:0 -O --savepath="./" --idfile="./group.id.txt" + pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { let id_file_arg = Arg::with_name("id_file") .long("idfile") @@ -36,19 +38,19 @@ pub fn create_subcommand<'a, 'b>() -> App<'a, 'b> { .help("Object area info, if not set,will calc base ip. format [county:carrier:city:inner]")) .arg(id_file_arg.clone()).arg(save_path.clone())) .subcommand(SubCommand::with_name("group").about("create group desc") - .arg(Arg::with_name("founder").long("founder").short("f") + .arg(Arg::with_name("founder").long("founder").short("F").takes_value(true) .help("founder of group")) .arg(Arg::with_name("admins").required(true).long("admins").short("A").value_delimiter(";") - .help("admins in group. format [peopleid:title]")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";") - .help("members in group. format [peopleid:title]")) + .help("admins in group. format [PeopleId:title]")) + .arg(Arg::with_name("members").long("members").short("M").value_delimiter(";") + .help("members in group. format [PeopleId:title]")) .arg(Arg::with_name("ood_list").long("oodlist").short("l").value_delimiter(";") .help("oods in group")) - .arg(Arg::with_name("name").long("name").short("n") + .arg(Arg::with_name("name").long("name").short("n").takes_value(true) .help("name of group")) - .arg(Arg::with_name("icon").long("icon").short("I") + .arg(Arg::with_name("icon").long("icon").short("I").takes_value(true) .help("icon of group")) - .arg(Arg::with_name("description").long("description").short("d") + .arg(Arg::with_name("description").long("description").short("d").takes_value(true) .help("description of group")) .arg(Arg::with_name("area").required(true).long("area").short("a").takes_value(true) .help("Object area info. format [county:carrier:city:inner]")) @@ -300,11 +302,13 @@ pub async fn create_desc(matches: &ArgMatches<'_>) { pub async fn create_group_desc(matches: &ArgMatches<'_>) { let admins = match get_group_members_from_matches(matches, "admins") { Ok(admins) => { - if admins.len() == 0 { - log::error!("empty admins."); - return; + match admins { + Some(admins) if admins.len() > 0 => admins, + _ => { + log::error!("empty admins."); + return; + } } - admins } Err(e) => { log::error!("invalid admins: {}", e.msg()); @@ -335,7 +339,7 @@ pub async fn create_group_desc(matches: &ArgMatches<'_>) { }; let members = match get_group_members_from_matches(matches, "members") { - Ok(members) => members, + Ok(members) => members.unwrap_or(vec![]), Err(e) => { log::error!("invalid members: {}", e.msg()); return; @@ -370,7 +374,7 @@ pub async fn create_group_desc(matches: &ArgMatches<'_>) { .join(&groupid.to_string()) .with_extension("desc"); if let Err(e) = group_desc.encode_to_file(&desc_file, true) { - error!("write group desc file failed, err {}", e); + error!("write group desc file({:?}) failed, err {}", desc_file, e); } else { info!( "write group({}) desc file succ to {}", diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index cec413f4c..d86672a0a 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -1,7 +1,7 @@ use clap::{App, SubCommand, Arg, ArgMatches}; -use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches}; +use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches}; use log::*; -use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId}; +use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId, bucky_time_now}; use cyfs_core::{CoreObjectType, DecApp, DecAppObj, AppList, AppStatus, AppListObj, AppStatusObj, DecAppId}; use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; @@ -12,13 +12,15 @@ pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { .arg(Arg::with_name("desc").required(true).index(1).help("desc file to modify")) .arg(Arg::with_name("sn").short("s").long("sn").value_delimiter(";").help("new sn list")) .arg(Arg::with_name("eps").long("eps").short("e").value_delimiter(";").help("new endpoint list")) - .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("administrators set to group")) - .arg(Arg::with_name("add_admins").long("add_admin").short("aA").value_delimiter(";").help("administrators append to group")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("members set to group")) - .arg(Arg::with_name("add_members").long("add_member").short("am").value_delimiter(";").help("members append to group")) + .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("set administrators to group. format [PeopleId:title]")) + .arg(Arg::with_name("add_admins").long("add_admin").value_delimiter(";").help("append administrators to group. format [PeopleId:title]")) + .arg(Arg::with_name("remove_admins").long("rm_admin").value_delimiter(";").help("remove administrators from group. format [PeopleId]")) + .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("set members to group. format [PeopleId:title]")) + .arg(Arg::with_name("add_members").long("add_member").value_delimiter(";").help("append members to group. format [PeopleId:title]")) + .arg(Arg::with_name("remove_members").long("rm_member").value_delimiter(";").help("remove members from group. format [PeopleId]")) .arg(Arg::with_name("description").short("d").long("description").takes_value(true).help("description of group")) .arg(Arg::with_name("version").short("v").long("version").takes_value(true).help("version of group")) - .arg(Arg::with_name("prev_blob_id").short("p").long("prev").takes_value(true).help("prev-blob-id of group")) + .arg(Arg::with_name("prev_blob_id").long("prev_blob").takes_value(true).help("prev-blob-id of group")) .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people or group")) .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people or group")) .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("name of people or group")) @@ -51,6 +53,7 @@ pub fn modify_desc(matches: &ArgMatches) { StandardObject::Group(mut g) => { if modify_group_desc(&mut g, matches).is_ok() { g.encode_to_file(path.as_ref(), false).expect("write desc file err"); + info!("modify success"); } } StandardObject::People(mut p) => { @@ -136,7 +139,9 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "members") { Ok(members) => { - group.set_members(members); + if let Some(members) = members { + group.set_members(members); + } }, Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); @@ -146,25 +151,35 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "add_members") { Ok(additional_members) => { - let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); - additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); - group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + if let Some(additional_members) = additional_members { + let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); + additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); + group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + } }, Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); return Err(err); } } + + if let Some(remove_members) = get_objids_from_matches(matches, "remove_members") { + let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); + remove_members.iter().for_each(|m| {members.remove(m);}); + group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + } match get_group_members_from_matches(matches, "admins") { Ok(admins) => { - if group.is_simple_group() { - let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); - log::error!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + if let Some(admins) = admins { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + org.set_admins(admins); } - let org = group.check_org_body_content_mut(); - org.set_admins(admins); }, Err(err) => { log::error!("update group({}) failed for invalid administrator.", group_id); @@ -174,15 +189,17 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "add_admins") { Ok(additional_admins) => { - if group.is_simple_group() { - let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); - log::error!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + if let Some(additional_admins) = additional_admins { + if group.is_simple_group() { + let msg = format!("update group({}) failed for the administrators of simple-group is immutable.", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); + } + let org = group.check_org_body_content_mut(); + let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); + additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); + org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); } - let org = group.check_org_body_content_mut(); - let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); - additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); - org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); }, Err(err) => { log::error!("update group({}) failed for invalid administrator.", group_id); @@ -190,13 +207,15 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> } } - match get_deviceids_from_matches(matches, "ood_lists") { - Some(oods) => { - group.set_ood_list(oods); - }, - None => { - group.set_ood_list(vec![]); - } + if let Some(remove_members) = get_objids_from_matches(matches, "remove_admins") { + let org = group.check_org_body_content_mut(); + let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); + remove_members.iter().for_each(|m| {admins.remove(m);}); + org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + } + + if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { + group.set_ood_list(oods); } if let Some(additional_oods) = get_deviceids_from_matches(matches, "add_oods") { let mut oods = HashSet::::from_iter(group.ood_list().iter().map(|id| id.clone())); @@ -212,6 +231,10 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> group.set_icon(Some(icon.to_string())); } + if let Some(name) = matches.value_of("name") { + group.set_name(Some(name.to_string())); + } + if let Some(version) = matches.value_of("version") { let version = match version.parse::() { Ok(v) => v, @@ -227,7 +250,7 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> if let Some(prev_blob_id) = matches.value_of("prev_blob_id") { let prev_blob_id = match ObjectId::from_str(prev_blob_id) { Ok(prev_blob_id) => prev_blob_id, - Err(e) => { + Err(_) => { let msg = format!("update group({}) failed for invalid prev-blob-id {}", group_id, prev_blob_id); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); @@ -236,5 +259,13 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> group.set_prev_blob_id(Some(prev_blob_id)); } + if group.admins().is_empty() { + let msg = format!("update group({}) failed for no administrators", group_id); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); + } + + group.body_mut().as_mut().unwrap().set_update_time(bucky_time_now()); + Ok(()) } \ No newline at end of file diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index 5125ee948..d9376b401 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -207,7 +207,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { } ); for member in group.admins() { - print!("{}, ", member.to_string()); + print!("{};", member.to_string()); } println!("]"); } @@ -215,7 +215,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_members") { print!("members: ["); for member in group.members() { - print!("{}, ", member.to_string()); + print!("{};", member.to_string()); } println!("]"); } @@ -223,7 +223,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_oodlist") { print!("ood_list: ["); for ood in group.ood_list() { - print!("{}, ", ood); + print!("{};", ood); } println!("]"); } diff --git a/src/tools/desc-tool/src/util.rs b/src/tools/desc-tool/src/util.rs index c25854018..44d4d9a9c 100644 --- a/src/tools/desc-tool/src/util.rs +++ b/src/tools/desc-tool/src/util.rs @@ -55,14 +55,14 @@ pub fn get_eps_from_matches(matches: &ArgMatches, name: &str) -> Option BuckyResult> { +) -> BuckyResult>> { if let Some(strs) = matches.values_of_lossy(name) { let mut ret = vec![]; for str in &strs { ret.push(GroupMember::from_str(str)?); } - Ok(ret) + Ok(Some(ret)) } else { - Ok(vec![]) + Ok(None) } } From 654febe9b5dcb8c6744705913433c8c12e4a9856 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 11 Apr 2023 19:16:45 +0800 Subject: [PATCH 535/553] `desc-tool` read signer from `.desc` --- src/tools/desc-tool/src/sign.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/desc-tool/src/sign.rs b/src/tools/desc-tool/src/sign.rs index d245a74a9..9f57a5654 100644 --- a/src/tools/desc-tool/src/sign.rs +++ b/src/tools/desc-tool/src/sign.rs @@ -109,6 +109,11 @@ pub async fn sign_desc(matches: &ArgMatches<'_>) { }) } else if let Ok(index) = str.parse::() { SignatureSource::RefIndex(index) + } else if let Ok((obj, _)) = AnyNamedObject::decode_from_file(str.as_ref(), &mut vec![]) { + SignatureSource::Object(ObjectLink { + obj_id: obj.object_id(), + obj_owner: None, + }) } else { SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER) } From bf6304327421c5419bd1b79587c482cc6b9e045d Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 11 Apr 2023 21:02:18 +0800 Subject: [PATCH 536/553] Sort members by id for encode --- src/component/cyfs-base-meta/src/group.rs | 45 +- .../cyfs-base/protos/standard_objects.proto | 8 +- src/component/cyfs-base/src/codec/format.rs | 29 +- src/component/cyfs-base/src/objects/group.rs | 163 ++++--- .../cyfs-stack/src/resolver/device_manager.rs | 4 +- src/tools/desc-tool/src/modify.rs | 424 ++++++++++++------ src/tools/desc-tool/src/show.rs | 4 +- 7 files changed, 463 insertions(+), 214 deletions(-) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index 34ee769e9..aa986a9b0 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -114,7 +114,22 @@ impl GroupVerifier for Group { return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } - (latest_group.admins(), latest_group.members()) + ( + HashSet::::from_iter( + latest_group + .admins() + .keys() + .filter(|m| m.obj_type_code() == ObjectTypeCode::People) + .map(|m| *m), + ), + HashSet::::from_iter( + latest_group + .members() + .keys() + .filter(|m| m.obj_type_code() == ObjectTypeCode::People) + .map(|m| *m), + ), + ) } None => match self.prev_blob_id() { Some(prev_blob_id) => { @@ -127,7 +142,7 @@ impl GroupVerifier for Group { } None => { if let Some(founder) = self.founder_id() { - if self.admins().iter().find(|m| &m.id == founder).is_none() { + if self.admins().values().find(|m| &m.id == founder).is_none() { let msg = format!( "Update group({}) the founder({}) must be an administrator.", group_id, founder @@ -136,7 +151,7 @@ impl GroupVerifier for Group { return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } } - ([].as_slice(), [].as_slice()) + (HashSet::new(), HashSet::new()) } }, }; @@ -144,33 +159,21 @@ impl GroupVerifier for Group { // admins: > 1/2 // new members: all - let last_admins = HashSet::::from_iter( - last_admins - .iter() - .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) - .map(|m| m.id), - ); - let last_members = HashSet::::from_iter( - last_members - .iter() - .filter(|m| m.id.obj_type_code() == ObjectTypeCode::People) - .map(|m| m.id), - ); let add_admins = HashSet::::from_iter( self.admins() - .iter() + .keys() .filter(|m| { - m.id.obj_type_code() == ObjectTypeCode::People && !last_admins.contains(&m.id) + m.obj_type_code() == ObjectTypeCode::People && !last_admins.contains(*m) }) - .map(|m| m.id), + .map(|m| *m), ); let add_members = HashSet::::from_iter( self.members() - .iter() + .keys() .filter(|m| { - m.id.obj_type_code() == ObjectTypeCode::People && !last_members.contains(&m.id) + m.obj_type_code() == ObjectTypeCode::People && !last_members.contains(*m) }) - .map(|m| m.id), + .map(|m| *m), ); if add_admins.len() != self.admins().len() - last_admins.len() { diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index e025fd753..9395f996c 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -70,9 +70,9 @@ message CommonGroupBodyContent { optional string icon = 2; optional string description = 3; - repeated GroupMember members = 4; + repeated GroupMember members = 4; // sort by id deduplicated ascending order - repeated bytes ood_list = 5; + repeated bytes ood_list = 5; // sort by id deduplicated ascending order optional bytes prev_blob_id = 6; uint64 version = 7; @@ -82,7 +82,7 @@ message CommonGroupBodyContent { message SimpleGroupDescContent { bytes unique_id = 1; optional bytes founder_id = 2; - repeated GroupMember admins = 3; + repeated GroupMember admins = 3; // sort by id deduplicated ascending order } message SimpleGroupBodyContent { @@ -96,7 +96,7 @@ message OrgDescContent { } message OrgBodyContent { - repeated GroupMember admins = 1; + repeated GroupMember admins = 1; // sort by id deduplicated ascending order CommonGroupBodyContent common = 2; } diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index 162f5066a..54ea3638d 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -575,7 +575,15 @@ impl ObjectFormat for GroupDescContent { self.founder_id().as_ref(), ); if let GroupDescContent::SimpleGroup(simple_group) = self { - JsonCodecHelper::encode_str_array_field(&mut map, "admins", simple_group.admins()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "admins", + &simple_group + .admins() + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .collect::>(), + ); } map.into() @@ -595,9 +603,24 @@ impl ObjectFormat for GroupBodyContent { ); if let GroupBodyContent::Org(org) = self { - JsonCodecHelper::encode_str_array_field(&mut map, "admins", org.admins()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "admins", + &org.admins() + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .collect::>(), + ); } - JsonCodecHelper::encode_str_array_field(&mut map, "members", self.members()); + JsonCodecHelper::encode_str_array_field( + &mut map, + "members", + &self + .members() + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .collect::>(), + ); JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", self.ood_list()); JsonCodecHelper::encode_option_string_field( &mut map, diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 70c3c0342..57fa54356 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -1,6 +1,10 @@ +use itertools::Itertools; + use crate::codec as cyfs_base; +use crate::protos::standard_objects; use crate::*; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::str::FromStr; @@ -61,11 +65,11 @@ impl GroupBodyContent { &self.common().description } - pub fn members(&self) -> &Vec { + pub fn members(&self) -> &HashMap { &self.common().members } - pub fn members_mut(&mut self) -> &mut Vec { + pub fn members_mut(&mut self) -> &mut HashMap { &mut self.common_mut().members } @@ -121,7 +125,7 @@ impl Group { ) -> GroupBuilder { let desc_content = SimpleGroupDescContent { unique_id: UniqueId::create_with_random(), - admins, + admins: HashMap::from_iter(admins.into_iter().map(|m| (m.id, m))), founder_id, }; @@ -180,52 +184,54 @@ impl Group { self.common_mut().description = description; } - pub fn admins(&self) -> &[GroupMember] { + pub fn admins(&self) -> &HashMap { if self.is_org() { - self.check_org_body_content().admins.as_slice() + &self.check_org_body_content().admins } else { - self.check_simple_group_desc_content().admins.as_slice() + &self.check_simple_group_desc_content().admins } } - pub fn members(&self) -> &[GroupMember] { - self.common().members.as_slice() + pub fn members(&self) -> &HashMap { + &self.common().members } pub fn set_members(&mut self, members: Vec) { - self.common_mut().members = members; + self.common_mut().members = HashMap::from_iter(members.into_iter().map(|m| (m.id, m))); } - pub fn ood_list(&self) -> &[DeviceId] { - self.common().ood_list.as_slice() + pub fn ood_list(&self) -> &Vec { + &self.common().ood_list } pub fn set_ood_list(&mut self, oods: Vec) { - self.common_mut().ood_list = oods; + self.common_mut().ood_list = HashSet::::from_iter(oods.into_iter()) + .into_iter() + .sorted() + .collect(); } pub fn contain_ood(&self, ood_id: &ObjectId) -> bool { - self.ood_list() - .iter() - .find(|id| id.object_id() == ood_id) - .is_some() + match DeviceId::try_from(ood_id) { + Ok(device_id) => self.ood_list().contains(&device_id), + Err(_) => false, + } } pub fn is_same_ood_list(&self, other: &Group) -> bool { let my_oods = self.ood_list(); let other_oods = other.ood_list(); + if my_oods.len() != other_oods.len() { + return false; + } + for id in my_oods { if !other_oods.contains(id) { return false; } } - for id in other_oods { - if !my_oods.contains(id) { - return false; - } - } true } @@ -307,11 +313,11 @@ impl Group { scope: GroupMemberScope, ) -> Vec<&ObjectId> { let mut members = match scope { - GroupMemberScope::Admin => self.admins().iter().map(|m| &m.id).collect::>(), - GroupMemberScope::Member => self.members().iter().map(|m| &m.id).collect::>(), + GroupMemberScope::Admin => self.admins().keys().collect::>(), + GroupMemberScope::Member => self.members().keys().collect::>(), GroupMemberScope::All => [ - self.admins().iter().map(|m| &m.id).collect::>(), - self.members().iter().map(|m| &m.id).collect::>(), + self.admins().keys().collect::>(), + self.members().keys().collect::>(), ] .concat(), }; @@ -325,16 +331,16 @@ impl Group { } pub fn ood_list_with_distance(&self, target: &ObjectId) -> Vec<&ObjectId> { - let mut oods = self + let oods = self .ood_list() .iter() .map(|id| id.object_id()) + .sorted_unstable_by(|l, r| { + let dl = l.distance_of(target); + let dr = r.distance_of(target); + dl.cmp(&dr) + }) .collect::>(); - oods.sort_unstable_by(|l, r| { - let dl = l.distance_of(target); - let dr = r.distance_of(target); - dl.cmp(&dr) - }); oods } @@ -415,7 +421,7 @@ impl FromStr for GroupMember { } } -impl ToString for GroupMember { +impl ToString for &GroupMember { fn to_string(&self) -> String { format!("{}:{}", self.id, self.title) } @@ -427,7 +433,7 @@ struct CommonGroupBodyContent { icon: Option, description: Option, - members: Vec, + members: HashMap, ood_list: Vec, @@ -447,8 +453,11 @@ impl CommonGroupBodyContent { name, icon, description, - members, - ood_list, + members: HashMap::from_iter(members.into_iter().map(|m| (m.id, m))), + ood_list: HashSet::::from_iter(ood_list.into_iter()) + .into_iter() + .sorted() + .collect::>(), version: 0, prev_blob_id: None, } @@ -459,6 +468,9 @@ impl TryFrom for CommonGroupBodyContent { type Error = BuckyError; fn try_from(mut value: protos::CommonGroupBodyContent) -> BuckyResult { + let mut ood_list = ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?; + ood_list.sort(); + let ret = Self { name: if value.has_name() { Some(value.take_name()) @@ -475,8 +487,16 @@ impl TryFrom for CommonGroupBodyContent { } else { None }, - members: ProtobufCodecHelper::decode_value_list(value.take_members())?, - ood_list: ProtobufCodecHelper::decode_buf_list(value.take_ood_list())?, + members: + HashMap::from_iter( + ProtobufCodecHelper::decode_value_list::< + GroupMember, + standard_objects::GroupMember, + >(value.take_members())? + .into_iter() + .map(|m| (m.id, m)), + ), + ood_list, version: value.version, prev_blob_id: if value.has_prev_blob_id() { Some(ProtobufCodecHelper::decode_buf(value.take_prev_blob_id())?) @@ -505,10 +525,21 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { ret.set_description(description.clone()); } - ret.set_members(ProtobufCodecHelper::encode_nested_list(&value.members)?); - ret.set_ood_list(ProtobufCodecHelper::encode_buf_list( - value.ood_list.as_slice(), - )?); + let members = value + .members + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .map(|m| m.clone()) + .collect::>(); + ret.set_members(ProtobufCodecHelper::encode_nested_list(&members)?); + + let oods = value + .ood_list + .iter() + .sorted() + .map(|id| id.clone()) + .collect::>(); + ret.set_ood_list(ProtobufCodecHelper::encode_buf_list(oods.as_slice())?); ret.version = value.version; if let Some(prev_blob_id) = &value.prev_blob_id { @@ -523,11 +554,11 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { pub struct SimpleGroupDescContent { unique_id: UniqueId, founder_id: Option, - admins: Vec, + admins: HashMap, } impl SimpleGroupDescContent { - pub fn admins(&self) -> &Vec { + pub fn admins(&self) -> &HashMap { &self.admins } } @@ -543,7 +574,15 @@ impl TryFrom for SimpleGroupDescContent { None }, unique_id: ProtobufCodecHelper::decode_buf(value.unique_id)?, - admins: ProtobufCodecHelper::decode_value_list(value.admins)?, + admins: + HashMap::from_iter( + ProtobufCodecHelper::decode_value_list::< + GroupMember, + standard_objects::GroupMember, + >(value.admins)? + .into_iter() + .map(|m| (m.id, m)), + ), }; Ok(ret) @@ -560,7 +599,14 @@ impl TryFrom<&SimpleGroupDescContent> for protos::SimpleGroupDescContent { if let Some(founder_id) = value.founder_id.as_ref() { ret.set_founder_id(founder_id.to_vec()?); } - ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); + + let admins = value + .admins + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .map(|m| m.clone()) + .collect::>(); + ret.set_admins(ProtobufCodecHelper::encode_nested_list(&admins)?); Ok(ret) } @@ -649,7 +695,7 @@ impl TryFrom<&OrgDescContent> for protos::OrgDescContent { #[derive(Clone, Debug, Default)] pub struct OrgBodyContent { - admins: Vec, + admins: HashMap, common: CommonGroupBodyContent, } @@ -664,16 +710,16 @@ impl OrgBodyContent { ) -> Self { Self { common: CommonGroupBodyContent::new(name, icon, description, members, ood_list), - admins, + admins: HashMap::from_iter(admins.into_iter().map(|m| (m.id, m))), } } - pub fn admins(&self) -> &Vec { + pub fn admins(&self) -> &HashMap { &self.admins } pub fn set_admins(&mut self, admins: Vec) { - self.admins = admins; + self.admins = HashMap::from_iter(admins.into_iter().map(|m| (m.id, m))); } } @@ -682,7 +728,15 @@ impl TryFrom for OrgBodyContent { fn try_from(mut value: protos::OrgBodyContent) -> BuckyResult { let ret = Self { - admins: ProtobufCodecHelper::decode_value_list(value.take_admins())?, + admins: + HashMap::from_iter( + ProtobufCodecHelper::decode_value_list::< + GroupMember, + standard_objects::GroupMember, + >(value.take_admins())? + .into_iter() + .map(|m| (m.id, m)), + ), common: ProtobufCodecHelper::decode_value(value.take_common())?, }; @@ -696,7 +750,14 @@ impl TryFrom<&OrgBodyContent> for protos::OrgBodyContent { fn try_from(value: &OrgBodyContent) -> BuckyResult { let mut ret = Self::new(); - ret.set_admins(ProtobufCodecHelper::encode_nested_list(&value.admins)?); + let admins = value + .admins + .values() + .sorted_by(|l, r| l.id.cmp(&r.id)) + .map(|m| m.clone()) + .collect::>(); + + ret.set_admins(ProtobufCodecHelper::encode_nested_list(&admins)?); ret.set_common(ProtobufCodecHelper::encode_nested_item(&value.common)?); Ok(ret) diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 7deeb0083..93652f59c 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -141,8 +141,8 @@ impl DeviceInfoManagerImpl { let group = object.as_group(); let sign_object_ids = HashSet::::from_iter( [ - group.admins().iter().map(|m| m.id).collect::>(), - group.members().iter().map(|m| m.id).collect::>(), + group.admins().iter().map(|m| m.1.id).collect::>(), + group.members().iter().map(|m| m.1.id).collect::>(), ] .concat() .into_iter(), diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index d86672a0a..256d9f9d7 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -1,136 +1,267 @@ -use clap::{App, SubCommand, Arg, ArgMatches}; -use crate::util::{get_eps_from_matches, get_deviceids_from_matches, get_group_members_from_matches, get_objids_from_matches}; +use crate::util::{ + get_deviceids_from_matches, get_eps_from_matches, get_group_members_from_matches, + get_objids_from_matches, +}; +use clap::{App, Arg, ArgMatches, SubCommand}; +use cyfs_base::{ + bucky_time_now, AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, DeviceId, FileDecoder, + FileEncoder, FileId, Group, GroupMember, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + StandardObject, +}; +use cyfs_core::{ + AppList, AppListObj, AppStatus, AppStatusObj, CoreObjectType, DecApp, DecAppId, DecAppObj, +}; use log::*; -use cyfs_base::{StandardObject, FileDecoder, FileEncoder, NamedObject, AnyNamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, FileId, Group, BuckyError, GroupMember, BuckyErrorCode, BuckyResult, DeviceId, bucky_time_now}; -use cyfs_core::{CoreObjectType, DecApp, DecAppObj, AppList, AppStatus, AppListObj, AppStatusObj, DecAppId}; use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::str::FromStr; pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("modify").about("modify desc") - .arg(Arg::with_name("desc").required(true).index(1).help("desc file to modify")) - .arg(Arg::with_name("sn").short("s").long("sn").value_delimiter(";").help("new sn list")) - .arg(Arg::with_name("eps").long("eps").short("e").value_delimiter(";").help("new endpoint list")) - .arg(Arg::with_name("admins").long("admins").short("A").value_delimiter(";").help("set administrators to group. format [PeopleId:title]")) - .arg(Arg::with_name("add_admins").long("add_admin").value_delimiter(";").help("append administrators to group. format [PeopleId:title]")) - .arg(Arg::with_name("remove_admins").long("rm_admin").value_delimiter(";").help("remove administrators from group. format [PeopleId]")) - .arg(Arg::with_name("members").long("members").short("m").value_delimiter(";").help("set members to group. format [PeopleId:title]")) - .arg(Arg::with_name("add_members").long("add_member").value_delimiter(";").help("append members to group. format [PeopleId:title]")) - .arg(Arg::with_name("remove_members").long("rm_member").value_delimiter(";").help("remove members from group. format [PeopleId]")) - .arg(Arg::with_name("description").short("d").long("description").takes_value(true).help("description of group")) - .arg(Arg::with_name("version").short("v").long("version").takes_value(true).help("version of group")) - .arg(Arg::with_name("prev_blob_id").long("prev_blob").takes_value(true).help("prev-blob-id of group")) - .arg(Arg::with_name("add_oods").long("add_ood").short("o").value_delimiter(";").help("device id append to people or group")) - .arg(Arg::with_name("ood_lists").long("ood_lists").short("l").value_delimiter(";").help("device id set to people or group")) - .arg(Arg::with_name("name").short("n").long("name").takes_value(true).help("name of people or group")) - .arg(Arg::with_name("icon").short("I").long("icon").takes_value(true).help("icon of people or group")) - .arg(Arg::with_name("source").long("source").value_delimiter(";").help("add source to app, {ver}:{id}")) - .arg(Arg::with_name("app_id").long("appid").takes_value(true).help("app id add to app list")) - .arg(Arg::with_name("app_ver").long("appver").takes_value(true).help("app ver add to app list")) - .arg(Arg::with_name("app_status").long("appstart").help("start app, default false")) + SubCommand::with_name("modify") + .about("modify desc") + .arg( + Arg::with_name("desc") + .required(true) + .index(1) + .help("desc file to modify"), + ) + .arg( + Arg::with_name("sn") + .short("s") + .long("sn") + .value_delimiter(";") + .help("new sn list"), + ) + .arg( + Arg::with_name("eps") + .long("eps") + .short("e") + .value_delimiter(";") + .help("new endpoint list"), + ) + .arg( + Arg::with_name("admins") + .long("admins") + .short("A") + .value_delimiter(";") + .help("set administrators to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("add_admins") + .long("add_admin") + .value_delimiter(";") + .help("append administrators to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("remove_admins") + .long("rm_admin") + .value_delimiter(";") + .help("remove administrators from group. format [PeopleId]"), + ) + .arg( + Arg::with_name("members") + .long("members") + .short("m") + .value_delimiter(";") + .help("set members to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("add_members") + .long("add_member") + .value_delimiter(";") + .help("append members to group. format [PeopleId:title]"), + ) + .arg( + Arg::with_name("remove_members") + .long("rm_member") + .value_delimiter(";") + .help("remove members from group. format [PeopleId]"), + ) + .arg( + Arg::with_name("description") + .short("d") + .long("description") + .takes_value(true) + .help("description of group"), + ) + .arg( + Arg::with_name("version") + .short("v") + .long("version") + .takes_value(true) + .help("version of group"), + ) + .arg( + Arg::with_name("prev_blob_id") + .long("prev_blob") + .takes_value(true) + .help("prev-blob-id of group"), + ) + .arg( + Arg::with_name("add_oods") + .long("add_ood") + .short("o") + .value_delimiter(";") + .help("device id append to people or group"), + ) + .arg( + Arg::with_name("ood_lists") + .long("ood_lists") + .short("l") + .value_delimiter(";") + .help("device id set to people or group"), + ) + .arg( + Arg::with_name("name") + .short("n") + .long("name") + .takes_value(true) + .help("name of people or group"), + ) + .arg( + Arg::with_name("icon") + .short("I") + .long("icon") + .takes_value(true) + .help("icon of people or group"), + ) + .arg( + Arg::with_name("source") + .long("source") + .value_delimiter(";") + .help("add source to app, {ver}:{id}"), + ) + .arg( + Arg::with_name("app_id") + .long("appid") + .takes_value(true) + .help("app id add to app list"), + ) + .arg( + Arg::with_name("app_ver") + .long("appver") + .takes_value(true) + .help("app ver add to app list"), + ) + .arg( + Arg::with_name("app_status") + .long("appstart") + .help("start app, default false"), + ) } pub fn modify_desc(matches: &ArgMatches) { let path = matches.value_of("desc").unwrap(); match AnyNamedObject::decode_from_file(path.as_ref(), &mut vec![]) { - Ok((desc, _)) => { - match desc { - AnyNamedObject::Standard(mut obj) => { - match obj { - StandardObject::Device(ref mut p) => { - if let Some(sn_list) = get_deviceids_from_matches(matches, "sn") { - p.body_mut().as_mut().unwrap().content_mut().mut_sn_list().clone_from(&sn_list); - } - - if let Some(ep_list) = get_eps_from_matches(matches, "eps") { - p.body_mut().as_mut().unwrap().content_mut().mut_endpoints().clone_from(&ep_list); - } - - p.encode_to_file(path.as_ref(), false).expect("write desc file err"); - info!("modify success"); - }, - StandardObject::Group(mut g) => { - if modify_group_desc(&mut g, matches).is_ok() { - g.encode_to_file(path.as_ref(), false).expect("write desc file err"); - info!("modify success"); - } - } - StandardObject::People(mut p) => { - let content = p.body_mut().as_mut().unwrap().content_mut(); - if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { - content.ood_list_mut().clone_from(&oods); - } + Ok((desc, _)) => match desc { + AnyNamedObject::Standard(mut obj) => match obj { + StandardObject::Device(ref mut p) => { + if let Some(sn_list) = get_deviceids_from_matches(matches, "sn") { + p.body_mut() + .as_mut() + .unwrap() + .content_mut() + .mut_sn_list() + .clone_from(&sn_list); + } - if let Some(oods) = get_deviceids_from_matches(matches, "add_oods") { - for ood in oods { - if !content.ood_list_mut().contains(&ood) { - content.ood_list_mut().push(ood); - } else { - info!("obj {} already exist, skip.", &ood); - } - } - } + if let Some(ep_list) = get_eps_from_matches(matches, "eps") { + p.body_mut() + .as_mut() + .unwrap() + .content_mut() + .mut_endpoints() + .clone_from(&ep_list); + } - if let Some(name) = matches.value_of("name") { - content.set_name(name.to_owned()); - } + p.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + info!("modify success"); + } + StandardObject::Group(mut g) => { + if modify_group_desc(&mut g, matches).is_ok() { + g.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + info!("modify success"); + } + } + StandardObject::People(mut p) => { + let content = p.body_mut().as_mut().unwrap().content_mut(); + if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { + content.ood_list_mut().clone_from(&oods); + } - if let Some(icon) = matches.value_of("icon") { - match FileId::from_str(icon) { - Ok(icon) => content.set_icon(icon), - Err(_) => { - warn!("invalid icon {}", icon); - }, - } + if let Some(oods) = get_deviceids_from_matches(matches, "add_oods") { + for ood in oods { + if !content.ood_list_mut().contains(&ood) { + content.ood_list_mut().push(ood); + } else { + info!("obj {} already exist, skip.", &ood); } - - p.encode_to_file(path.as_ref(), false).expect("write desc file err"); - } - _ => { - error!("unsupport desc type"); } } - } - AnyNamedObject::Core(obj) => { - match CoreObjectType::from(obj.desc().obj_type()) { - CoreObjectType::DecApp => { - let mut app = DecApp::try_from(obj).unwrap(); - if let Some(values) = matches.values_of_lossy("source") { - for value in &values { - let sources: Vec<&str> = value.split(":").collect(); - app.set_source(sources[0].to_owned(), ObjectId::from_str(sources[1]).unwrap(), None); - } - } - app.encode_to_file(path.as_ref(), false).expect("write desc file err"); - }, - CoreObjectType::AppList => { - let mut list = AppList::try_from(obj).unwrap(); - let owner = list.desc().owner().unwrap(); - if let Some(id_str) = matches.value_of("app_id") { - let dec_id = DecAppId::from_str(id_str).unwrap(); - let version = matches.value_of("app_ver").unwrap().to_owned(); - let app_status = matches.is_present("app_status"); - let status = AppStatus::create(owner, dec_id, version, app_status); + if let Some(name) = matches.value_of("name") { + content.set_name(name.to_owned()); + } - list.put(status); - } else { - list.clear(); + if let Some(icon) = matches.value_of("icon") { + match FileId::from_str(icon) { + Ok(icon) => content.set_icon(icon), + Err(_) => { + warn!("invalid icon {}", icon); } + } + } - list.encode_to_file(path.as_ref(), false).expect("write desc file err"); + p.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + } + _ => { + error!("unsupport desc type"); + } + }, + AnyNamedObject::Core(obj) => match CoreObjectType::from(obj.desc().obj_type()) { + CoreObjectType::DecApp => { + let mut app = DecApp::try_from(obj).unwrap(); + if let Some(values) = matches.values_of_lossy("source") { + for value in &values { + let sources: Vec<&str> = value.split(":").collect(); + app.set_source( + sources[0].to_owned(), + ObjectId::from_str(sources[1]).unwrap(), + None, + ); } - _ => {} } + + app.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); } - AnyNamedObject::DECApp(_) => {} - } + CoreObjectType::AppList => { + let mut list = AppList::try_from(obj).unwrap(); + let owner = list.desc().owner().unwrap(); + if let Some(id_str) = matches.value_of("app_id") { + let dec_id = DecAppId::from_str(id_str).unwrap(); + let version = matches.value_of("app_ver").unwrap().to_owned(); + let app_status = matches.is_present("app_status"); + let status = AppStatus::create(owner, dec_id, version, app_status); + list.put(status); + } else { + list.clear(); + } + + list.encode_to_file(path.as_ref(), false) + .expect("write desc file err"); + } + _ => {} + }, + AnyNamedObject::DECApp(_) => {} }, Err(e) => { error!("read desc from file {} failed, err {}", path, e); - }, + } } } @@ -142,7 +273,7 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> if let Some(members) = members { group.set_members(members); } - }, + } Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); return Err(err); @@ -152,11 +283,13 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> match get_group_members_from_matches(matches, "add_members") { Ok(additional_members) => { if let Some(additional_members) = additional_members { - let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); - additional_members.into_iter().for_each(|m| {members.insert(m.id, m.title);}); - group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut members = group.members().clone(); + additional_members.into_iter().for_each(|m| { + members.insert(m.id, m); + }); + group.set_members(members.into_iter().map(|(_, m)| m).collect()); } - }, + } Err(err) => { log::error!("update group({}) failed for invalid member.", group_id); return Err(err); @@ -164,11 +297,13 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> } if let Some(remove_members) = get_objids_from_matches(matches, "remove_members") { - let mut members = HashMap::::from_iter(group.members().iter().map(|m| (m.id, m.title.clone()))); - remove_members.iter().for_each(|m| {members.remove(m);}); - group.set_members(members.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut members = group.members().clone(); + remove_members.iter().for_each(|m| { + members.remove(m); + }); + group.set_members(members.into_iter().map(|(_, m)| m).collect()); } - + match get_group_members_from_matches(matches, "admins") { Ok(admins) => { if let Some(admins) = admins { @@ -178,11 +313,14 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } let org = group.check_org_body_content_mut(); - org.set_admins(admins); + org.set_admins(admins); } - }, + } Err(err) => { - log::error!("update group({}) failed for invalid administrator.", group_id); + log::error!( + "update group({}) failed for invalid administrator.", + group_id + ); return Err(err); } } @@ -196,22 +334,34 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } let org = group.check_org_body_content_mut(); - let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); - additional_admins.into_iter().for_each(|m| {admins.insert(m.id, m.title);}); - org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut admins = org.admins().clone(); + additional_admins.into_iter().for_each(|m| { + admins.insert(m.id, m); + }); + org.set_admins(admins.into_iter().map(|(_, m)| m).collect()); } - }, + } Err(err) => { - log::error!("update group({}) failed for invalid administrator.", group_id); + log::error!( + "update group({}) failed for invalid administrator.", + group_id + ); return Err(err); } } if let Some(remove_members) = get_objids_from_matches(matches, "remove_admins") { let org = group.check_org_body_content_mut(); - let mut admins = HashMap::::from_iter(org.admins().iter().map(|m| (m.id, m.title.clone()))); - remove_members.iter().for_each(|m| {admins.remove(m);}); - org.set_admins(admins.into_iter().map(|(id, title)| GroupMember::new(id, title)).collect()); + let mut admins = org.admins().clone(); + remove_members.iter().for_each(|m| { + admins.remove(m); + }); + org.set_admins( + admins + .into_iter() + .map(|(_, m)| m) + .collect(), + ); } if let Some(oods) = get_deviceids_from_matches(matches, "ood_lists") { @@ -219,7 +369,9 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> } if let Some(additional_oods) = get_deviceids_from_matches(matches, "add_oods") { let mut oods = HashSet::::from_iter(group.ood_list().iter().map(|id| id.clone())); - additional_oods.into_iter().for_each(|id| {oods.insert(id);}); + additional_oods.into_iter().for_each(|id| { + oods.insert(id); + }); group.set_ood_list(oods.into_iter().collect()); } @@ -239,7 +391,10 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> let version = match version.parse::() { Ok(v) => v, Err(e) => { - let msg = format!("update group({}) failed for invalid version {}, err: {:?}", group_id, version, e); + let msg = format!( + "update group({}) failed for invalid version {}, err: {:?}", + group_id, version, e + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); } @@ -251,7 +406,10 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> let prev_blob_id = match ObjectId::from_str(prev_blob_id) { Ok(prev_blob_id) => prev_blob_id, Err(_) => { - let msg = format!("update group({}) failed for invalid prev-blob-id {}", group_id, prev_blob_id); + let msg = format!( + "update group({}) failed for invalid prev-blob-id {}", + group_id, prev_blob_id + ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); } @@ -262,10 +420,14 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> if group.admins().is_empty() { let msg = format!("update group({}) failed for no administrators", group_id); log::error!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); + return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); } - group.body_mut().as_mut().unwrap().set_update_time(bucky_time_now()); + group + .body_mut() + .as_mut() + .unwrap() + .set_update_time(bucky_time_now()); Ok(()) -} \ No newline at end of file +} diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index d9376b401..6014a8f38 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -206,7 +206,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { "immutable" } ); - for member in group.admins() { + for (_, member) in group.admins() { print!("{};", member.to_string()); } println!("]"); @@ -214,7 +214,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_members") { print!("members: ["); - for member in group.members() { + for (_, member) in group.members() { print!("{};", member.to_string()); } println!("]"); From c8de6793575fea63f2b24707f85bae518f9c5c65 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 12 Apr 2023 18:58:31 +0800 Subject: [PATCH 537/553] Remove unused export --- src/component/cyfs-group-lib/src/group_manager.rs | 2 +- src/component/cyfs-group-lib/src/lib.rs | 1 - src/tools/desc-tool/src/sign.rs | 12 ++++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/component/cyfs-group-lib/src/group_manager.rs b/src/component/cyfs-group-lib/src/group_manager.rs index c15200386..f48af84ea 100644 --- a/src/component/cyfs-group-lib/src/group_manager.rs +++ b/src/component/cyfs-group-lib/src/group_manager.rs @@ -345,7 +345,7 @@ impl GroupManager { }) } - async fn on_commited(&self, mut cmd: GroupCommandCommited) -> BuckyResult<()> { + async fn on_commited(&self, cmd: GroupCommandCommited) -> BuckyResult<()> { let rpath = cmd.block.rpath(); let service = self .find_or_restart_service( diff --git a/src/component/cyfs-group-lib/src/lib.rs b/src/component/cyfs-group-lib/src/lib.rs index 519a64040..1b130ece2 100644 --- a/src/component/cyfs-group-lib/src/lib.rs +++ b/src/component/cyfs-group-lib/src/lib.rs @@ -16,7 +16,6 @@ pub use input_request::*; pub use objects::*; pub use output_request::*; pub use processor::*; -pub(crate) use request::*; pub use request_codec::*; pub use requestor::*; pub use rpath_client::*; diff --git a/src/tools/desc-tool/src/sign.rs b/src/tools/desc-tool/src/sign.rs index 9f57a5654..05589fa1b 100644 --- a/src/tools/desc-tool/src/sign.rs +++ b/src/tools/desc-tool/src/sign.rs @@ -13,6 +13,8 @@ use cyfs_base::{ use log::*; use std::str::FromStr; +// .\desc-tool sign ${desc-path} -s=${signer-secret-path} -t=${signer-desc-path} -dba + pub fn sign_subcommand<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("sign") .about("sign desc") @@ -109,11 +111,13 @@ pub async fn sign_desc(matches: &ArgMatches<'_>) { }) } else if let Ok(index) = str.parse::() { SignatureSource::RefIndex(index) - } else if let Ok((obj, _)) = AnyNamedObject::decode_from_file(str.as_ref(), &mut vec![]) { + } else if let Ok((obj, _)) = + AnyNamedObject::decode_from_file(str.as_ref(), &mut vec![]) + { SignatureSource::Object(ObjectLink { obj_id: obj.object_id(), obj_owner: None, - }) + }) } else { SignatureSource::RefIndex(SIGNATURE_SOURCE_REFINDEX_OWNER) } @@ -191,6 +195,10 @@ pub async fn sign_desc(matches: &ArgMatches<'_>) { if signed { obj.encode_to_file(matches.value_of("desc").unwrap().as_ref(), true) .unwrap(); + + info!("signature success."); + } else { + error!("signature failed!"); } } else { error!("invalid desc file"); From 638ebe6bb81544f77989c0b2164baebf5ff9cdee Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 13 Apr 2023 21:24:51 +0800 Subject: [PATCH 538/553] `ObjectShell` for `Group` --- src/component/cyfs-base-meta/src/group.rs | 32 +- .../cyfs-base/protos/standard_objects.proto | 2 +- src/component/cyfs-base/src/codec/format.rs | 4 +- src/component/cyfs-base/src/objects/group.rs | 24 +- .../cyfs-core/protos/core_objects.proto | 5 +- .../cyfs-core/src/group/group_blob.rs | 44 --- .../src/group/group_consensus_block.rs | 18 +- .../cyfs-core/src/group/group_shell.rs | 13 + src/component/cyfs-core/src/group/mod.rs | 4 +- src/component/cyfs-core/src/storage/mod.rs | 4 +- .../cyfs-core/src/storage/object_shell.rs | 280 ++++++++++++++++++ .../cyfs-core/src/storage/storage.rs | 64 +++- .../src/objects/group_update_proposal.rs | 52 ++-- .../src/consensus/hotstuff/hotstuff.rs | 32 +- .../src/consensus/vote/committee.rs | 40 +-- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 4 +- .../src/dec_state/dec_state_synchronizer.rs | 18 +- .../cyfs-group/src/dec_state/state_pusher.rs | 14 +- .../cyfs-group/src/network/non_driver.rs | 14 +- .../cyfs-group/src/statepath/design.md | 2 +- .../src/statepath/group_statepath.rs | 12 +- .../cyfs-group/src/storage/group_storage.rs | 20 +- src/tests/group-example/src/main.rs | 30 ++ src/tools/cyfs-meta-client/src/main.rs | 7 +- src/tools/desc-tool/src/modify.rs | 32 +- src/tools/desc-tool/src/show.rs | 22 +- 26 files changed, 580 insertions(+), 213 deletions(-) delete mode 100644 src/component/cyfs-core/src/group/group_blob.rs create mode 100644 src/component/cyfs-core/src/group/group_shell.rs create mode 100644 src/component/cyfs-core/src/storage/object_shell.rs diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index aa986a9b0..73cefa34b 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -2,10 +2,10 @@ use std::collections::HashSet; use cyfs_base::{ BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, - ObjectTypeCode, People, PeopleId, RawConvertTo, RsaCPUObjectVerifier, Signature, + ObjectTypeCode, People, PeopleId, RawEncode, RsaCPUObjectVerifier, Signature, SingleKeyObjectDesc, Verifier, }; -use cyfs_core::GroupBlob; +use cyfs_core::{GroupShell, ObjectShell}; async fn verify_signature( signs: Option<&Vec>, @@ -44,7 +44,7 @@ async fn verify_group_signature( ) -> BuckyResult<()> { let people = member_querier.get_people(people_id).await?; let verifier = RsaCPUObjectVerifier::new(people.desc().public_key().clone()); - let desc_buf = group.desc().to_vec()?; + let desc_buf = group.desc().raw_hash_value()?; verify_signature( group.signs().desc_signs(), desc_buf.as_slice(), @@ -52,7 +52,7 @@ async fn verify_group_signature( people_id, ) .await?; - let body_buf = group.body().to_vec()?; + let body_buf = group.body().as_ref().unwrap().raw_hash_value()?; verify_signature( group.signs().body_signs(), body_buf.as_slice(), @@ -104,12 +104,12 @@ impl GroupVerifier for Group { return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } - let latest_group_blob = latest_group.to_blob(); - let latest_group_blob_id = latest_group_blob.desc().object_id(); + let latest_group_shell = latest_group.to_shell(); + let latest_group_shell_id = latest_group_shell.shell_id(); if self.version() != latest_group.version() + 1 - || self.prev_blob_id() != &Some(latest_group_blob_id) + || self.prev_shell_id() != &Some(latest_group_shell_id) { - let msg = format!("Attempt to update group({}) from unknown version({}/{:?}), latest version: {}/{}.", group_id, self.version() - 1, self.prev_blob_id(), latest_group.version(), latest_group_blob_id); + let msg = format!("Attempt to update group({}) from unknown version({}-1/{:?}), latest version: {}/{}.", group_id, self.version(), self.prev_shell_id(), latest_group.version(), latest_group_shell_id); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } @@ -131,11 +131,11 @@ impl GroupVerifier for Group { ), ) } - None => match self.prev_blob_id() { - Some(prev_blob_id) => { + None => match self.prev_shell_id() { + Some(prev_shell_id) => { let msg = format!( - "The latest group({}) is necessary for update. prev_blob_id: {}", - group_id, prev_blob_id + "The latest group({}) is necessary for update. prev_shell_id: {}", + group_id, prev_shell_id ); log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); @@ -185,7 +185,7 @@ impl GroupVerifier for Group { return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); } - if add_members.len() != self.members().len() - add_members.len() { + if add_members.len() != self.members().len() - last_members.len() { let msg = format!( "Update group({}) with duplicate members or invalid members.", group_id @@ -218,7 +218,7 @@ impl GroupVerifier for Group { let (last_admin_signs, add_member_signs) = check_peoples.split_at(last_admins.len()); let last_admin_sign_count = last_admin_signs.iter().filter(|s| s.is_ok()).count(); - if last_admin_sign_count <= last_admins.len() / 2 { + if last_admins.len() > 0 && last_admin_sign_count <= last_admins.len() / 2 { let msg = format!( "Update group({}) failed for signatures from admins in latest version is not enough: expected {}, got {}.", group_id, @@ -245,9 +245,9 @@ impl GroupVerifier for Group { "Update group({}) verify ok, from {:?}/{:?}, to {}/{}", group_id, latest_group.map(|group| group.version()), - self.prev_blob_id(), + self.prev_shell_id(), self.version(), - self.to_blob().desc().object_id() + self.to_shell().shell_id() ); Ok(()) } diff --git a/src/component/cyfs-base/protos/standard_objects.proto b/src/component/cyfs-base/protos/standard_objects.proto index 9395f996c..99e1e22e6 100644 --- a/src/component/cyfs-base/protos/standard_objects.proto +++ b/src/component/cyfs-base/protos/standard_objects.proto @@ -74,7 +74,7 @@ message CommonGroupBodyContent { repeated bytes ood_list = 5; // sort by id deduplicated ascending order - optional bytes prev_blob_id = 6; + optional bytes prev_shell_id = 6; uint64 version = 7; } diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index 54ea3638d..a13a032fb 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -624,8 +624,8 @@ impl ObjectFormat for GroupBodyContent { JsonCodecHelper::encode_str_array_field(&mut map, "ood_list", self.ood_list()); JsonCodecHelper::encode_option_string_field( &mut map, - "prev_blob_id", - self.prev_blob_id().as_ref(), + "prev_shell_id", + self.prev_shell_id().as_ref(), ); JsonCodecHelper::encode_string_field(&mut map, "version", &self.version()); diff --git a/src/component/cyfs-base/src/objects/group.rs b/src/component/cyfs-base/src/objects/group.rs index 57fa54356..2e5649025 100644 --- a/src/component/cyfs-base/src/objects/group.rs +++ b/src/component/cyfs-base/src/objects/group.rs @@ -85,8 +85,8 @@ impl GroupBodyContent { self.common().version } - pub fn prev_blob_id(&self) -> &Option { - &self.common().prev_blob_id + pub fn prev_shell_id(&self) -> &Option { + &self.common().prev_shell_id } fn common(&self) -> &CommonGroupBodyContent { @@ -243,12 +243,12 @@ impl Group { self.common_mut().version = version; } - pub fn prev_blob_id(&self) -> &Option { - &self.common().prev_blob_id + pub fn prev_shell_id(&self) -> &Option { + &self.common().prev_shell_id } - pub fn set_prev_blob_id(&mut self, prev_blob_id: Option) { - self.common_mut().prev_blob_id = prev_blob_id; + pub fn set_prev_shell_id(&mut self, prev_shell_id: Option) { + self.common_mut().prev_shell_id = prev_shell_id; } pub fn is_simple_group(&self) -> bool { @@ -438,7 +438,7 @@ struct CommonGroupBodyContent { ood_list: Vec, version: u64, - prev_blob_id: Option, + prev_shell_id: Option, } impl CommonGroupBodyContent { @@ -459,7 +459,7 @@ impl CommonGroupBodyContent { .sorted() .collect::>(), version: 0, - prev_blob_id: None, + prev_shell_id: None, } } } @@ -498,8 +498,8 @@ impl TryFrom for CommonGroupBodyContent { ), ood_list, version: value.version, - prev_blob_id: if value.has_prev_blob_id() { - Some(ProtobufCodecHelper::decode_buf(value.take_prev_blob_id())?) + prev_shell_id: if value.has_prev_shell_id() { + Some(ProtobufCodecHelper::decode_buf(value.take_prev_shell_id())?) } else { None }, @@ -542,8 +542,8 @@ impl TryFrom<&CommonGroupBodyContent> for protos::CommonGroupBodyContent { ret.set_ood_list(ProtobufCodecHelper::encode_buf_list(oods.as_slice())?); ret.version = value.version; - if let Some(prev_blob_id) = &value.prev_blob_id { - ret.set_prev_blob_id(prev_blob_id.to_vec()?); + if let Some(prev_shell_id) = &value.prev_shell_id { + ret.set_prev_shell_id(prev_shell_id.to_vec()?); } Ok(ret) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index d49009e4c..881d20a99 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -7,7 +7,8 @@ message StorageDescContent { } message StorageBodyContent { - bytes value = 1; + bytes value = 1; // match with the hash in `Desc` + optional bytes freedom_attachment = 2; // content without hash, you can update it with the same hash in `Desc`; } // TextObject @@ -417,7 +418,7 @@ message GroupConsensusBlockDescContent { bytes meta_block_id = 5; uint64 round = 7; - bytes group_blob_id = 8; + bytes group_shell_id = 8; } message GroupConsensusBlockBodyContent { diff --git a/src/component/cyfs-core/src/group/group_blob.rs b/src/component/cyfs-core/src/group/group_blob.rs deleted file mode 100644 index 90829215d..000000000 --- a/src/component/cyfs-core/src/group/group_blob.rs +++ /dev/null @@ -1,44 +0,0 @@ -use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, RawDecode, RawEncode, -}; - -use crate::{Storage, StorageObj}; - -pub trait GroupBlob: Sized { - fn to_blob(&self) -> Storage; - - fn from_blob(blob: &Storage) -> BuckyResult; - - fn blob_storage_id(&self) -> String; -} - -impl GroupBlob for Group { - fn to_blob(&self) -> Storage { - let len = self.raw_measure(&None).unwrap(); - let mut buf = vec![0u8; len]; - let remain = self.raw_encode(buf.as_mut_slice(), &None).unwrap(); - assert_eq!(remain.len(), 0); - Storage::create_with_hash(self.blob_storage_id().as_str(), buf) - } - - fn from_blob(blob: &Storage) -> BuckyResult { - let group_buf = blob.value(); - let (group, remain) = Group::raw_decode(group_buf.as_slice())?; - assert_eq!(remain.len(), 0); - - let expected_id = group.blob_storage_id(); - - if blob.id() != expected_id { - return Err(BuckyError::new( - BuckyErrorCode::Unmatch, - format!("unknown storage, expect {}, got {}", expected_id, blob.id()), - )); - } - - Ok(group) - } - - fn blob_storage_id(&self) -> String { - format!("group@{}@{}", self.desc().object_id(), self.version()) - } -} diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 4b4bf4f9a..dc1834687 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -16,7 +16,7 @@ pub struct GroupConsensusBlockDescContent { height: u64, meta_block_id: ObjectId, round: u64, - group_blob_id: ObjectId, + group_shell_id: ObjectId, } impl DescContent for GroupConsensusBlockDescContent { @@ -55,8 +55,8 @@ impl GroupConsensusBlockDescContent { self.round } - pub fn group_blob_id(&self) -> &ObjectId { - &self.group_blob_id + pub fn group_shell_id(&self) -> &ObjectId { + &self.group_shell_id } } @@ -242,7 +242,7 @@ pub trait GroupConsensusBlockObject { height: u64, meta_block_id: ObjectId, round: u64, - group_blob_id: ObjectId, + group_shell_id: ObjectId, qc: Option, tc: Option, owner: ObjectId, @@ -259,7 +259,7 @@ pub trait GroupConsensusBlockObject { fn named_object(&self) -> &NamedObjectBase; fn named_object_mut(&mut self) -> &mut NamedObjectBase; fn round(&self) -> u64; - fn group_blob_id(&self) -> &ObjectId; + fn group_shell_id(&self) -> &ObjectId; fn qc(&self) -> &Option; fn tc(&self) -> &Option; } @@ -272,7 +272,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { height: u64, meta_block_id: ObjectId, round: u64, - group_blob_id: ObjectId, + group_shell_id: ObjectId, qc: Option, tc: Option, owner: ObjectId, @@ -287,7 +287,7 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { meta_block_id, body_hash: body.hash(), round, - group_blob_id, + group_shell_id, }; let block = GroupConsensusBlockBuilder::new(desc, body) @@ -371,9 +371,9 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { desc.round } - fn group_blob_id(&self) -> &ObjectId { + fn group_shell_id(&self) -> &ObjectId { let desc = self.0.desc().content(); - &desc.group_blob_id + &desc.group_shell_id } fn qc(&self) -> &Option { diff --git a/src/component/cyfs-core/src/group/group_shell.rs b/src/component/cyfs-core/src/group/group_shell.rs new file mode 100644 index 000000000..9281768d1 --- /dev/null +++ b/src/component/cyfs-core/src/group/group_shell.rs @@ -0,0 +1,13 @@ +use cyfs_base::{Group, GroupType}; + +use crate::{ObjectShell, OBJECT_SHELL_ALL_FREEDOM}; + +pub trait GroupShell: Sized { + fn to_shell(&self) -> ObjectShell; +} + +impl GroupShell for Group { + fn to_shell(&self) -> ObjectShell { + ObjectShell::::from_object(self.clone(), OBJECT_SHELL_ALL_FREEDOM) + } +} diff --git a/src/component/cyfs-core/src/group/mod.rs b/src/component/cyfs-core/src/group/mod.rs index 0fa271b8c..1f94656e9 100644 --- a/src/component/cyfs-core/src/group/mod.rs +++ b/src/component/cyfs-core/src/group/mod.rs @@ -4,12 +4,12 @@ mod group_proposal; mod group_quorum_certificate; mod group_rpath; // mod group_update_group_proposal_param; -mod group_blob; +mod group_shell; pub use group_consensus_block::*; pub use group_proposal::*; // pub use group_proposal_decide_param::*; -pub use group_blob::*; pub use group_quorum_certificate::*; pub use group_rpath::*; // pub use group_update_group_proposal_param::*; +pub use group_shell::*; diff --git a/src/component/cyfs-core/src/storage/mod.rs b/src/component/cyfs-core/src/storage/mod.rs index 649a8946f..d4b260682 100644 --- a/src/component/cyfs-core/src/storage/mod.rs +++ b/src/component/cyfs-core/src/storage/mod.rs @@ -1,3 +1,5 @@ +mod object_shell; mod storage; -pub use storage::*; \ No newline at end of file +pub use object_shell::*; +pub use storage::*; diff --git a/src/component/cyfs-core/src/storage/object_shell.rs b/src/component/cyfs-core/src/storage/object_shell.rs new file mode 100644 index 000000000..130d54ecc --- /dev/null +++ b/src/component/cyfs-core/src/storage/object_shell.rs @@ -0,0 +1,280 @@ +use std::marker::PhantomData; + +use cyfs_base::{ + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, + ObjectType, RawDecode, RawEncode, Signature, +}; + +use crate::{Storage, StorageObj}; + +const OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE: u8 = 0b_1; +const OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE: u8 = 0b_10; +const OBJECT_SHELL_FLAGS_FREEDOM_NONCE: u8 = 0b_100; +const OBJECT_SHELL_FLAGS_EXT: u8 = 0b_10000000; + +#[derive(Copy, Clone)] +pub struct ObjectShellFlags { + flags: u8, +} + +pub const OBJECT_SHELL_ALL_FREEDOM: ObjectShellFlags = ObjectShellFlags { + flags: OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE + | OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE + | OBJECT_SHELL_FLAGS_FREEDOM_NONCE, +}; + +impl ObjectShellFlags { + fn is_desc_sign_freedom(&self) -> bool { + self.flags & OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE != 0 + } + + fn is_body_sign_freedom(&self) -> bool { + self.flags & OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE != 0 + } + + fn is_nonce_freedom(&self) -> bool { + self.flags & OBJECT_SHELL_FLAGS_FREEDOM_NONCE != 0 + } +} + +pub struct ObjectShellFlagsBuilder { + flags: u8, +} + +impl ObjectShellFlagsBuilder { + pub fn new() -> Self { + Self { flags: 0 } + } + + pub fn build(&self) -> ObjectShellFlags { + ObjectShellFlags { flags: self.flags } + } + + pub fn freedom_desc_signature(&mut self) -> &mut Self { + self.flags |= OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE; + self + } + + pub fn freedom_body_signature(&mut self) -> &mut Self { + self.flags |= OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE; + self + } + + pub fn freedom_nonce(&mut self) -> &mut Self { + self.flags |= OBJECT_SHELL_FLAGS_FREEDOM_NONCE; + self + } +} + +pub struct ObjectShell { + raw: O, + flags: ObjectShellFlags, + phantom: PhantomData, +} + +impl ObjectShell +where + O: NamedObject + RawEncode + for<'local> RawDecode<'local> + Clone, // TODO: how to support other parameter against `O` for `NamedObject` + OT: ObjectType, + OT::ContentType: BodyContent, +{ + pub fn from_storage(storage: &Storage) -> BuckyResult { + if storage.check_hash() != Some(true) { + return Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "Hash does not match with raw object", + )); + } + + let value = storage.value().as_slice(); + if value.len() == 0 { + return Err(BuckyError::new( + BuckyErrorCode::OutOfLimit, + "empty for object shell", + )); + } + + let (freedom_flags, unfreedom) = value.split_at(1); + + let freedom_flags = ObjectShellFlags { + flags: *freedom_flags.get(0).unwrap(), + }; + + let (mut raw, remain) = O::raw_decode(unfreedom)?; + assert_eq!(remain.len(), 0); + + match storage.freedom_attachment().as_ref() { + Some(freedom) if freedom.len() > 0 => { + let (exist_field_flags, freedom) = freedom.split_at(1); + let exist_field_flags = ObjectShellFlags { + flags: *exist_field_flags.get(0).unwrap(), + }; + + let mut buf = freedom; + + if freedom_flags.is_desc_sign_freedom() && exist_field_flags.is_desc_sign_freedom() + { + let (signs, remain) = Vec::::raw_decode(buf)?; + buf = remain; + for sign in signs { + raw.signs_mut().push_desc_sign(sign); + } + } + + if freedom_flags.is_body_sign_freedom() && exist_field_flags.is_body_sign_freedom() + { + let (signs, remain) = Vec::::raw_decode(buf)?; + buf = remain; + for sign in signs { + raw.signs_mut().push_body_sign(sign); + } + } + + if freedom_flags.is_nonce_freedom() && exist_field_flags.is_nonce_freedom() { + let (nonce, remain) = u128::raw_decode(buf)?; + buf = remain; + unreachable!("nonce is not supported currently for the NamedObject::set_nonce is not exported."); + // raw.set_nonce() + } + assert_eq!(buf.len(), 0); + } + _ => {} + } + + Ok(Self { + raw, + flags: freedom_flags, + phantom: PhantomData, + }) + } + + pub fn to_storage(&self) -> Storage { + let mut const_raw = self.raw.clone(); + let max_buf_size = const_raw + .raw_measure(&None) + .expect("encode measure faield for object-shell"); + + let mut freedom_buf = vec![0; max_buf_size + 1]; + let mut exist_freedom_field_flags = ObjectShellFlagsBuilder::new(); + let (freedom_flag_buf, mut freedom_remain) = freedom_buf.split_at_mut(1); + + if self.flags.is_desc_sign_freedom() { + let desc_signs = const_raw.signs_mut().desc_signs(); + if let Some(signs) = desc_signs { + if signs.len() > 0 { + freedom_remain = signs + .raw_encode(freedom_remain, &None) + .expect("encode desc signature for object-shell failed."); + exist_freedom_field_flags.freedom_desc_signature(); + } + } + const_raw.signs_mut().clear_desc_signs(); + } + + if self.flags.is_body_sign_freedom() { + let body_signs = const_raw.signs_mut().body_signs(); + if let Some(signs) = body_signs { + if signs.len() > 0 { + freedom_remain = signs + .raw_encode(freedom_remain, &None) + .expect("encode body signature for object-shell failed."); + exist_freedom_field_flags.freedom_body_signature(); + } + } + const_raw.signs_mut().clear_body_signs(); + } + + if self.flags.is_nonce_freedom() { + let nonce = const_raw.nonce(); + if let Some(nonce) = nonce.as_ref() { + freedom_remain = nonce + .raw_encode(freedom_remain, &None) + .expect("encode nonce for object-shell failed."); + exist_freedom_field_flags.freedom_nonce(); + } + unreachable!( + "nonce is not supported currently for the NamedObject::set_nonce is not exported." + ); + // const_raw.set_nonce(None); + } + + let freedom_attachment = if freedom_remain.len() < max_buf_size { + *freedom_flag_buf.get_mut(0).unwrap() = exist_freedom_field_flags.flags; + let len = max_buf_size + 1 - freedom_remain.len(); + unsafe { + freedom_buf.set_len(len); + } + Some(freedom_buf) + } else { + None + }; + + let mut value = vec![0; max_buf_size + 1]; + *value.get_mut(0).unwrap() = self.flags.flags; + let remain = const_raw + .raw_encode(&mut value.as_mut_slice()[1..], &None) + .unwrap(); + let len = max_buf_size + 1 - remain.len(); + unsafe { + value.set_len(len); + } + + Storage::create_with_hash_and_freedom( + self.raw.desc().object_id().to_string().as_str(), + value, + freedom_attachment, + ) + } + + pub fn shell_id(&self) -> ObjectId { + self.to_storage().storage_id().object_id().clone() + } + + pub fn from_object(raw: O, flags: ObjectShellFlags) -> Self { + Self { + raw, + flags, + phantom: PhantomData, + } + } + + pub fn as_ref(&self) -> &O { + &self.raw + } + + pub fn as_mut(&mut self) -> &mut O { + // update the raw object + &mut self.raw + } +} + +impl RawEncode for ObjectShell +where + O: NamedObject + RawEncode + for<'de> RawDecode<'de> + Clone, + OT: ObjectType, + OT::ContentType: BodyContent, +{ + fn raw_measure(&self, purpose: &Option) -> BuckyResult { + self.to_storage().raw_measure(purpose) + } + + fn raw_encode<'a>( + &self, + buf: &'a mut [u8], + purpose: &Option, + ) -> BuckyResult<&'a mut [u8]> { + self.to_storage().raw_encode(buf, purpose) + } +} + +impl<'de, O, OT> RawDecode<'de> for ObjectShell +where + O: NamedObject + RawEncode + for<'local> RawDecode<'local> + Clone, + OT: ObjectType, + OT::ContentType: BodyContent, +{ + fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { + let (storage, remain) = Storage::raw_decode(buf)?; + Self::from_storage(&storage).map(|o| (o, remain)) + } +} diff --git a/src/component/cyfs-core/src/storage/storage.rs b/src/component/cyfs-core/src/storage/storage.rs index aab24b403..b0700b796 100644 --- a/src/component/cyfs-core/src/storage/storage.rs +++ b/src/component/cyfs-core/src/storage/storage.rs @@ -28,6 +28,7 @@ impl DescContent for StorageDescContent { #[cyfs_protobuf_type(crate::codec::protos::StorageBodyContent)] pub struct StorageBodyContent { pub(crate) value: Vec, + freedom_attachment: Option>, } impl BodyContent for StorageBodyContent { @@ -46,6 +47,11 @@ pub type Storage = NamedObjectBase; pub trait StorageObj { fn create(id: &str, value: Vec) -> Self; fn create_with_hash(id: &str, value: Vec) -> Self; + fn create_with_hash_and_freedom( + id: &str, + value: Vec, + freedom_attachment: Option>, + ) -> Self; fn id(&self) -> &str; fn hash(&self) -> &Option; @@ -56,12 +62,21 @@ pub trait StorageObj { fn update_value(&mut self, value: Vec) -> bool; fn into_value(self) -> Vec; + fn freedom_attachment(&self) -> &Option>; + fn freedom_attachment_mut(&mut self) -> &mut Option>; + fn into_value_freedom(self) -> (Vec, Option>); + fn storage_id(&self) -> StorageId; + + fn check_hash(&self) -> Option; } impl StorageObj for Storage { fn create(id: &str, value: Vec) -> Self { - let body = StorageBodyContent { value }; + let body = StorageBodyContent { + value, + freedom_attachment: None, + }; let desc = StorageDescContent { id: id.to_owned(), hash: None, @@ -74,10 +89,27 @@ impl StorageObj for Storage { id: id.to_owned(), hash: Some(hash_data(&value)), }; - let body = StorageBodyContent { value }; + let body = StorageBodyContent { + value, + freedom_attachment: None, + }; StorageBuilder::new(desc, body).no_create_time().build() } + fn create_with_hash_and_freedom( + id: &str, + value: Vec, + freedom_attachment: Option>, + ) -> Self { + let mut obj = Self::create_with_hash(id, value); + obj.body_mut() + .as_mut() + .unwrap() + .content_mut() + .freedom_attachment = freedom_attachment; + obj + } + fn id(&self) -> &str { &self.desc().content().id } @@ -128,9 +160,37 @@ impl StorageObj for Storage { true } + fn freedom_attachment(&self) -> &Option> { + &self.body().as_ref().unwrap().content().freedom_attachment + } + + fn freedom_attachment_mut(&mut self) -> &mut Option> { + &mut self + .body_mut() + .as_mut() + .unwrap() + .content_mut() + .freedom_attachment + } + + fn into_value_freedom(mut self) -> (Vec, Option>) { + let body = &mut self.body_mut().as_mut().unwrap().content_mut(); + let mut value = vec![]; + let mut attachment = None; + std::mem::swap(&mut value, &mut body.value); + std::mem::swap(&mut attachment, &mut body.freedom_attachment); + (value, attachment) + } + fn storage_id(&self) -> StorageId { self.desc().calculate_id().try_into().unwrap() } + + fn check_hash(&self) -> Option { + self.desc().content().hash.as_ref().map(|hash| { + hash == &hash_data(self.body().as_ref().unwrap().content().value.as_slice()) + }) + } } #[cfg(test)] diff --git a/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs index 4f79316b6..9a90478b1 100644 --- a/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs +++ b/src/component/cyfs-group-lib/src/objects/group_update_proposal.rs @@ -12,13 +12,13 @@ use crate::{GROUP_METHOD_UPDATE, STATEPATH_GROUP_DEC_ID, STATEPATH_GROUP_DEC_RPA pub struct GroupUpdateProposal { proposal: GroupProposal, target_dec_id: Vec, - from_blob_id: Option, + from_shell_id: Option, to_group: Group, } impl GroupUpdateProposal { pub fn create( - from_group_blob_id: Option, + from_group_shell_id: Option, to_group: Group, owner: ObjectId, target_dec_id: Vec, @@ -27,7 +27,7 @@ impl GroupUpdateProposal { effective_ending: Option, ) -> GroupUpdateProposalBuilder { GroupUpdateProposalBuilder::create( - from_group_blob_id, + from_group_shell_id, to_group, owner, target_dec_id, @@ -64,8 +64,8 @@ impl GroupUpdateProposal { self.target_dec_id.as_slice() } - pub fn from_blob_id(&self) -> &Option { - &self.from_blob_id + pub fn from_shell_id(&self) -> &Option { + &self.from_shell_id } pub fn to_group(&self) -> &Group { @@ -124,24 +124,24 @@ impl TryFrom for GroupUpdateProposal { } let payload = value.payload().as_ref().unwrap(); - let (group_blob, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); + let (group_shell, remain) = ChunkMeta::raw_decode(payload.as_slice()).unwrap(); assert_eq!(remain.len(), 0); - let to_group = Group::try_from(&group_blob)?; + let to_group = Group::try_from(&group_shell)?; - let to_blob_id = - task::block_on(async { group_blob.to_chunk().await.unwrap().calculate_id() }); - if &to_blob_id.object_id() != param.to_blob_id() { + let to_shell_id = + task::block_on(async { group_shell.to_chunk().await.unwrap().calculate_id() }); + if &to_shell_id.object_id() != param.to_shell_id() { return Err(BuckyError::new( BuckyErrorCode::InvalidFormat, - "the chunk in GroupUpdateProposal.body is not match with the to_blob_id in desc.param", + "the chunk in GroupUpdateProposal.body is not match with the to_shell_id in desc.param", )); } let ret = Self { proposal: value, target_dec_id: Vec::from(param.target_dec_id()), - from_blob_id: param.from_blob_id().clone(), + from_shell_id: param.from_shell_id().clone(), to_group, }; @@ -152,13 +152,13 @@ impl TryFrom for GroupUpdateProposal { pub struct GroupUpdateProposalBuilder { proposal: GroupProposalBuilder, target_dec_id: Vec, - from_blob_id: Option, + from_shell_id: Option, to_group: Option, } impl GroupUpdateProposalBuilder { pub fn create( - from_group_blob_id: Option, + from_group_shell_id: Option, to_group: Group, owner: ObjectId, target_dec_id: Vec, @@ -166,20 +166,20 @@ impl GroupUpdateProposalBuilder { effective_begining: Option, effective_ending: Option, ) -> Self { - let group_blob = ChunkMeta::from(&to_group); - let group_blob_vec = { - let len = group_blob.raw_measure(&None).unwrap(); + let group_shell = ChunkMeta::from(&to_group); + let group_shell_vec = { + let len = group_shell.raw_measure(&None).unwrap(); let mut buf = vec![0u8; len]; - let remain = group_blob.raw_encode(buf.as_mut_slice(), &None).unwrap(); + let remain = group_shell.raw_encode(buf.as_mut_slice(), &None).unwrap(); assert_eq!(remain.len(), 0); buf }; - let to_blob_id = - task::block_on(async { group_blob.to_chunk().await.unwrap().calculate_id() }); + let to_shell_id = + task::block_on(async { group_shell.to_chunk().await.unwrap().calculate_id() }); let param = - GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_blob_id.object_id()); + GroupUpdateGroupPropsalParam::new(target_dec_id.clone(), None, to_shell_id.object_id()); let param_vec = { let len = param.raw_measure(&None).unwrap(); let mut buf = vec![0u8; len]; @@ -195,7 +195,7 @@ impl GroupUpdateProposalBuilder { update_rpath, GROUP_METHOD_UPDATE.to_string(), Some(param_vec), - Some(group_blob_vec), + Some(group_shell_vec), None, owner, meta_block_id, @@ -206,7 +206,7 @@ impl GroupUpdateProposalBuilder { Self { proposal, target_dec_id, - from_blob_id: from_group_blob_id, + from_shell_id: from_group_shell_id, to_group: Some(to_group), } } @@ -236,15 +236,15 @@ impl GroupUpdateProposalBuilder { pub fn build(mut self) -> GroupUpdateProposal { let mut target_dec_id: Vec = vec![]; - let mut from_blob_id: Option = None; + let mut from_shell_id: Option = None; let to_group = self.to_group.take().unwrap(); mem::swap(&mut target_dec_id, &mut self.target_dec_id); - mem::swap(&mut from_blob_id, &mut self.from_blob_id); + mem::swap(&mut from_shell_id, &mut self.from_shell_id); GroupUpdateProposal { proposal: self.proposal.build(), target_dec_id, - from_blob_id, + from_shell_id, to_group, } } diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index c19a807fa..7ed084e1a 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,8 +11,8 @@ use cyfs_base::{ RawEncode, RsaCPUObjectSigner, SignatureSource, Signer, }; use cyfs_core::{ - GroupBlob, GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, - GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, + GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupShell, }; use cyfs_group_lib::{ExecuteResult, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; @@ -384,7 +384,7 @@ impl HotstuffRunner { { // check leader let leader_owner = self - .get_leader_owner(Some(block.group_blob_id()), block.round()) + .get_leader_owner(Some(block.group_shell_id()), block.round()) .await?; if &leader_owner != block.owner() { @@ -581,17 +581,17 @@ impl HotstuffRunner { async fn get_leader_owner( &self, - group_blob_id: Option<&ObjectId>, + group_shell_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { let leader = self .committee - .get_leader(group_blob_id, round) + .get_leader(group_shell_id, round) .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", self, - group_blob_id, round, + group_shell_id, round, err ); @@ -1143,7 +1143,7 @@ impl HotstuffRunner { ); if !only_rebuild_result_state { - match self.check_group_is_latest(block.group_blob_id()).await { + match self.check_group_is_latest(block.group_shell_id()).await { Ok(is_latest) if is_latest => {} _ => { log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for the group is not latest", @@ -2061,7 +2061,7 @@ impl HotstuffRunner { }) .collect(); - let group_blob_id = group.to_blob().desc().object_id(); + let group_shell_id = group.to_shell().shell_id(); let mut block = GroupConsensusBlock::create( self.rpath.clone(), @@ -2070,7 +2070,7 @@ impl HotstuffRunner { prev_block.as_ref().map_or(0, |b| b.height()) + 1, ObjectId::default(), // TODO: meta block id self.round, - group_blob_id, + group_shell_id, self.high_qc.clone(), tc, self.local_id, @@ -2251,11 +2251,11 @@ impl HotstuffRunner { Ok(()) } - async fn check_group_is_latest(&self, group_blob_id: &ObjectId) -> BuckyResult { + async fn check_group_is_latest(&self, group_shell_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; - let group_blob = latest_group.to_blob(); - let latest_chunk_id = group_blob.desc().object_id(); - Ok(&latest_chunk_id == group_blob_id) + let group_shell = latest_group.to_shell(); + let latest_chunk_id = group_shell.shell_id(); + Ok(&latest_chunk_id == group_shell_id) } async fn make_sure_result_state( @@ -2374,9 +2374,9 @@ impl HotstuffRunner { // Upon booting, generate the very first block (if we are the leader). // Also, schedule a timer in case we don't hear from the leader. let max_round_block = self.store.block_with_max_round(); - let group_blob_id = max_round_block.as_ref().map(|block| block.group_blob_id()); - let last_group = self.committee.get_group(group_blob_id).await; - let latest_group = match group_blob_id.as_ref() { + let group_shell_id = max_round_block.as_ref().map(|block| block.group_shell_id()); + let last_group = self.committee.get_group(group_shell_id).await; + let latest_group = match group_shell_id.as_ref() { Some(_) => self.committee.get_group(None).await, None => last_group.clone(), }; diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 6b32187a3..65caa9f51 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -10,8 +10,8 @@ use cyfs_base::{ SingleKeyObjectDesc, Verifier, }; use cyfs_core::{ - GroupBlob, GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, - GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, + GroupConsensusBlockObject, GroupShell, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; @@ -22,7 +22,7 @@ pub(crate) struct Committee { group_id: ObjectId, non_driver: NONDriverHelper, local_device_id: ObjectId, - group_cache: Arc>>, // (group_blob_id, group) + group_cache: Arc>>, // (group_shell_id, group) } impl Committee { @@ -35,16 +35,16 @@ impl Committee { } } - pub async fn get_group(&self, group_blob_id: Option<&ObjectId>) -> BuckyResult { - self.check_group(group_blob_id, None).await + pub async fn get_group(&self, group_shell_id: Option<&ObjectId>) -> BuckyResult { + self.check_group(group_shell_id, None).await } pub async fn quorum_threshold( &self, voters: &HashSet, - group_blob_id: Option<&ObjectId>, + group_shell_id: Option<&ObjectId>, ) -> BuckyResult { - let group = self.check_group(group_blob_id, None).await?; + let group = self.check_group(group_shell_id, None).await?; let voters: Vec<&ObjectId> = voters .iter() .filter(|id| { @@ -62,10 +62,10 @@ impl Committee { pub async fn get_leader( &self, - group_blob_id: Option<&ObjectId>, + group_shell_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { - let group = self.check_group(group_blob_id, None).await?; + let group = self.check_group(group_shell_id, None).await?; let i = (round % (group.ood_list().len() as u64)) as usize; Ok(group.ood_list()[i].object_id().clone()) } @@ -92,7 +92,7 @@ impl Committee { ); let group = self - .check_group(Some(block.group_blob_id()), Some(&from)) + .check_group(Some(block.group_shell_id()), Some(&from)) .await?; if !self.check_block_sign(&block, &group).await? { @@ -160,7 +160,7 @@ impl Committee { )); } - self.check_group(Some(block_desc.content().group_blob_id()), Some(&from)) + self.check_group(Some(block_desc.content().group_shell_id()), Some(&from)) .await?; log::debug!( @@ -250,7 +250,7 @@ impl Committee { let is_enough = self .quorum_threshold( &tc.votes.iter().map(|v| v.voter).collect(), - prev_block.map(|b| b.group_blob_id()), + prev_block.map(|b| b.group_shell_id()), ) .await?; @@ -314,7 +314,7 @@ impl Committee { let is_enough = self .quorum_threshold( &qc.votes.iter().map(|v| v.voter).collect(), - Some(prev_block_desc.group_blob_id()), + Some(prev_block_desc.group_shell_id()), ) .await?; @@ -346,14 +346,14 @@ impl Committee { pub async fn check_group( &self, - chunk_id: Option<&ObjectId>, + shell_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { { // read let cache = self.group_cache.read().await; - if let Some(chunk_id) = chunk_id { - if let Some(group) = cache.get(chunk_id) { + if let Some(shell_id) = shell_id { + if let Some(group) = cache.get(shell_id) { return Ok(group.clone()); } } @@ -361,12 +361,12 @@ impl Committee { let group = self .non_driver - .get_group(&self.group_id, chunk_id, from) + .get_group(&self.group_id, shell_id, from) .await?; - let group_blob = group.to_blob(); - let calc_id = group_blob.desc().object_id(); - if let Some(id) = chunk_id { + let group_shell = group.to_shell(); + let calc_id = group_shell.shell_id(); + if let Some(id) = shell_id { assert_eq!(&calc_id, id); } diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index d2128a20f..6a5852b61 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -244,7 +244,7 @@ impl QCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.0).collect(), - Some(block.group_blob_id()), + Some(block.group_shell_id()), ) .await?; if self.thresholded { @@ -315,7 +315,7 @@ impl TCMaker { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.voter).collect(), - block.map(|block| block.group_blob_id()), + block.map(|block| block.group_shell_id()), ) .await?; diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 382a67120..637124113 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -104,7 +104,7 @@ impl DecStateSynchronizer { struct DecStateSynchronizerCache { state_cache: DecStorageCache, - group_blob_id: ObjectId, + group_shell_id: ObjectId, group: Group, } @@ -112,7 +112,7 @@ struct UpdateNotifyInfo { header_block: GroupConsensusBlock, qc: HotstuffBlockQC, remotes: HashSet, - group_blob_id: ObjectId, + group_shell_id: ObjectId, group: Group, } @@ -247,7 +247,7 @@ impl DecStateSynchronizerRunner { header_block: notify_info.header_block.clone(), qc: notify_info.qc.clone(), }, - group_blob_id: notify_info.group_blob_id, + group_shell_id: notify_info.group_shell_id, group: notify_info.group.clone(), }); self.update_notifies = None; @@ -276,15 +276,15 @@ impl DecStateSynchronizerRunner { if self.state_cache.is_none() { let state_cache = self.store.cur_state().await; if let Some(state_cache) = state_cache { - let group_blob_id = state_cache.header_block.group_blob_id().clone(); + let group_shell_id = state_cache.header_block.group_shell_id().clone(); let group = self .non_driver - .get_group(self.rpath.group_id(), Some(&group_blob_id), None) + .get_group(self.rpath.group_id(), Some(&group_shell_id), None) .await; if let Ok(group) = group { self.state_cache = Some(DecStateSynchronizerCache { state_cache, - group_blob_id, + group_shell_id, group, }); } @@ -320,15 +320,15 @@ impl DecStateSynchronizerRunner { { let group = self .committee - .check_group(Some(header_block.group_blob_id()), None) + .check_group(Some(header_block.group_shell_id()), None) .await?; - let group_blob_id = header_block.group_blob_id().clone(); + let group_shell_id = header_block.group_shell_id().clone(); self.update_notifies = Some(UpdateNotifyInfo { header_block: header_block, qc: qc, remotes: HashSet::from([remote]), - group_blob_id, + group_shell_id, group, }); }; diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index acf061ae7..32325324d 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -88,7 +88,7 @@ impl StatePusher { struct HeaderBlockNotifyProgress { header_block: GroupConsensusBlock, qc_block: GroupConsensusBlock, - group_blob_id: ObjectId, + group_shell_id: ObjectId, members: Vec, total_notify_times: usize, cur_block_notify_times: usize, @@ -218,10 +218,10 @@ impl StateChanggeRunner { return; } - if block.group_blob_id() != progress.header_block.group_blob_id() { + if block.group_shell_id() != progress.header_block.group_shell_id() { let group = self .non_driver - .get_group(block.rpath().group_id(), Some(block.group_blob_id()), None) + .get_group(block.rpath().group_id(), Some(block.group_shell_id()), None) .await; if group.is_err() { return; @@ -234,7 +234,7 @@ impl StateChanggeRunner { .collect(); } - progress.group_blob_id = block.group_blob_id().clone(); + progress.group_shell_id = block.group_shell_id().clone(); progress.total_notify_times += progress.cur_block_notify_times; progress.cur_block_notify_times = 0; progress.header_block = block; @@ -243,7 +243,7 @@ impl StateChanggeRunner { None => { let group = self .non_driver - .get_group(block.rpath().group_id(), Some(block.group_blob_id()), None) + .get_group(block.rpath().group_id(), Some(block.group_shell_id()), None) .await; if group.is_err() { return; @@ -260,12 +260,12 @@ impl StateChanggeRunner { None => return, }; - let group_blob_id = block.group_blob_id().clone(); + let group_shell_id = block.group_shell_id().clone(); self.notify_progress = Some(HeaderBlockNotifyProgress { header_block: block, qc_block, - group_blob_id, + group_shell_id, members, total_notify_times, cur_block_notify_times: 0, diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 3e400ce44..700599f54 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -163,16 +163,16 @@ impl NONDriverHelper { pub async fn get_group( &self, group_id: &ObjectId, - group_blob_id: Option<&ObjectId>, + group_shell_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { - // TODO: ignore group_blob_id first - // match group_blob_id { - // Some(group_blob_id) => { - // let blob = self.get_object(group_blob_id, from).await?; - // let (group_blob, remain) = Storage::raw_decode(blob.object_raw.as_slice())?; + // TODO: ignore group_shell_id first + // match group_shell_id { + // Some(group_shell_id) => { + // let shell = self.get_object(group_shell_id, from).await?; + // let (group_shell, remain) = Storage::raw_decode(shell.object_raw.as_slice())?; // assert_eq!(remain.len(), 0); - // let group = Group::from_blob(&group_blob)?; + // let group = Group::from_shell(&group_shell)?; // if &group.desc().object_id() == group_id { // Ok(group) // } else { diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 885888d5b..68535c894 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -18,7 +18,7 @@ | | // 且不同${r-path}之间是并列的,不能嵌套 | |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-blob-->BLOB(Group) +| |--group-shell-->ObjectShell(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 0ed0abd25..981e20a67 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -3,7 +3,7 @@ use cyfs_base::{ObjectId, ObjectIdDataBuilder}; pub const STATE_PATH_SEPARATOR: &str = "/"; pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_BLOB: &str = "group-blob"; +pub const GROUP_STATE_PATH_GROUP_SHELL: &str = "group-shell"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; @@ -30,7 +30,7 @@ pub struct GroupStatePath { root: String, dec_state: String, link: String, - group_blob: String, + group_shell: String, last_vote_round: String, last_qc: String, last_tc: String, @@ -49,11 +49,11 @@ impl GroupStatePath { root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_blob: Self::join(&[ + group_shell: Self::join(&[ "", rpath.as_str(), GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_BLOB, + GROUP_STATE_PATH_GROUP_SHELL, ]), last_vote_round: Self::join(&[ "", @@ -138,8 +138,8 @@ impl GroupStatePath { self.link.as_str() } - pub fn group_blob(&self) -> &str { - self.group_blob.as_str() + pub fn group_shell(&self) -> &str { + self.group_shell.as_str() } pub fn last_vote_round(&self) -> &str { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 17756b992..4e38a9ef5 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -6,7 +6,7 @@ use cyfs_base::{ }; use cyfs_core::{ - GroupBlob, GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, GroupShell, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::GroupRPathStatus; @@ -42,7 +42,7 @@ pub struct GroupStorage { rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, - group_blob_id: ObjectId, + group_shell_id: ObjectId, cache: StorageCacheInfo, @@ -60,8 +60,8 @@ impl GroupStorage { root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { let group = non_driver.get_group(group_id, None, None).await?; - let group_blob = group.to_blob(); - let group_blob_id = group_blob.desc().object_id(); + let group_shell = group.to_shell(); + let group_shell_id = group_shell.shell_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) @@ -77,7 +77,7 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_blob_id, + group_shell_id, storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), @@ -108,8 +108,8 @@ impl GroupStorage { log::warn!("get group {} from noc failed {:?}", group_id, err); err })?; - let group_blob = group.to_blob(); - let group_blob_id = group_blob.desc().object_id(); + let group_shell = group.to_shell(); + let group_shell_id = group_shell.shell_id(); let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) @@ -139,7 +139,7 @@ impl GroupStorage { dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_blob_id, + group_shell_id, storage_engine: StorageEngineGroupState::new( dec_group_state, state_path, @@ -180,8 +180,8 @@ impl GroupStorage { &self.group } - pub fn group_blob_id(&self) -> &ObjectId { - &self.group_blob_id + pub fn group_shell_id(&self) -> &ObjectId { + &self.group_shell_id } pub fn dec_state_id(&self) -> &Option { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index bc8b5fded..8ea9e60ba 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -23,6 +23,36 @@ use crate::{ GroupDecService::MyRPathDelegate, }; +/** + * Build the group for test + * .\desc-tool create people --savepath=test-group/admins --idfile=test-group/admins/people-1.id + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/admins/people-1.sec -t=test-group/admins/people-1.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/admins/people-2.sec -t=test-group/admins/people-2.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/admins/people-3.sec -t=test-group/admins/people-3.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/admins/people-4.sec -t=test-group/admins/people-4.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-1.sec -t=test-group/members/people-1.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-2.sec -t=test-group/members/people-2.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-3.sec -t=test-group/members/people-3.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-4.sec -t=test-group/members/people-4.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-5.sec -t=test-group/members/people-5.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-6.sec -t=test-group/members/people-6.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-7.sec -t=test-group/members/people-7.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-8.sec -t=test-group/members/people-8.desc -dba + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-9.sec -t=test-group/members/people-9.desc -dba + * + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-5 -d=test-group/members/people-5.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-6 -d=test-group/members/people-6.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-7 -d=test-group/members/people-7.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-8 -d=test-group/members/people-8.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-9 -d=test-group/members/people-9.desc 1 0 + * + * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-1.desc -d=67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc 1 0 + * + * .\desc-tool show -a 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc + * + * .\desc-tool modify 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc --prev_blob= -v=1 +*/ + mod Common { use std::{ fmt::format, io::ErrorKind, net::SocketAddrV4, sync::Arc, thread::sleep, time::Duration, diff --git a/src/tools/cyfs-meta-client/src/main.rs b/src/tools/cyfs-meta-client/src/main.rs index b8cad84ed..ae9178604 100644 --- a/src/tools/cyfs-meta-client/src/main.rs +++ b/src/tools/cyfs-meta-client/src/main.rs @@ -12,7 +12,12 @@ use cyfs_meta_lib::{MetaMinerTarget, MetaClient}; use std::str::FromStr; #[async_std::main] -async fn main() ->BuckyResult<()> { +async fn main() { + let runner_fut = Box::pin(main_run()); + let _ = runner_fut.await; +} + +async fn main_run() ->BuckyResult<()> { simple_logger::SimpleLogger::new().with_level(LevelFilter::Debug).init().unwrap(); let default_target = MetaMinerTarget::default().to_string(); diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index 256d9f9d7..74173b1be 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -5,14 +5,14 @@ use crate::util::{ use clap::{App, Arg, ArgMatches, SubCommand}; use cyfs_base::{ bucky_time_now, AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, DeviceId, FileDecoder, - FileEncoder, FileId, Group, GroupMember, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, - StandardObject, + FileEncoder, FileId, Group, NamedObject, ObjectDesc, ObjectId, OwnerObjectDesc, + StandardObject, RawEncode, }; use cyfs_core::{ AppList, AppListObj, AppStatus, AppStatusObj, CoreObjectType, DecApp, DecAppId, DecAppObj, }; use log::*; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashSet}; use std::convert::TryFrom; use std::str::FromStr; @@ -92,10 +92,10 @@ pub fn modify_subcommand<'a, 'b>() -> App<'a, 'b> { .help("version of group"), ) .arg( - Arg::with_name("prev_blob_id") - .long("prev_blob") + Arg::with_name("prev_shell_id") + .long("prev_shell") .takes_value(true) - .help("prev-blob-id of group"), + .help("prev-shell-id of group"), ) .arg( Arg::with_name("add_oods") @@ -267,6 +267,7 @@ pub fn modify_desc(matches: &ArgMatches) { fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> { let group_id = group.desc().object_id(); + let body_hash = group.body().as_ref().unwrap().raw_hash_encode()?; match get_group_members_from_matches(matches, "members") { Ok(members) => { @@ -402,19 +403,19 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> group.set_version(version); } - if let Some(prev_blob_id) = matches.value_of("prev_blob_id") { - let prev_blob_id = match ObjectId::from_str(prev_blob_id) { - Ok(prev_blob_id) => prev_blob_id, + if let Some(prev_shell_id) = matches.value_of("prev_shell_id") { + let prev_shell_id = match ObjectId::from_str(prev_shell_id) { + Ok(prev_shell_id) => prev_shell_id, Err(_) => { let msg = format!( - "update group({}) failed for invalid prev-blob-id {}", - group_id, prev_blob_id + "update group({}) failed for invalid prev-shell-id {}", + group_id, prev_shell_id ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg)); } }; - group.set_prev_blob_id(Some(prev_blob_id)); + group.set_prev_shell_id(Some(prev_shell_id)); } if group.admins().is_empty() { @@ -423,11 +424,18 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> return Err(BuckyError::new(BuckyErrorCode::InvalidInput, msg)); } + if body_hash == group.body().as_ref().unwrap().raw_hash_encode()? { + log::info!("success with no change"); + return Ok(()); + } + group .body_mut() .as_mut() .unwrap() .set_update_time(bucky_time_now()); + group.signs_mut().clear_body_signs(); + Ok(()) } diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index 6014a8f38..d0e1a6426 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -4,7 +4,7 @@ use cyfs_base::{ InnerNode, NDNObjectInfo, NamedObject, ObjectDesc, RawEncode, RawFrom, SignatureSource, SingleKeyObjectDesc, StandardObject, }; -use cyfs_core::{AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj}; +use cyfs_core::{AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj, GroupShell}; use std::convert::TryFrom; use std::path::Path; @@ -179,22 +179,34 @@ fn show_group(group: &Group, matches: &ArgMatches) { "founder: {}", group.founder_id().map_or("".to_string(), |f| f.to_string()) ); - println!("icon: {}", group.icon().as_ref().map_or("", |icon| icon.as_str())); + println!( + "icon: {}", + group.icon().as_ref().map_or("", |icon| icon.as_str()) + ); println!( "description: {}", group.description().as_ref().map_or("", |d| d.as_str()) ); println!( "area: {}", - group.desc().area().as_ref().map_or("None".to_string(), |a| a.to_string()) + group + .desc() + .area() + .as_ref() + .map_or("None".to_string(), |a| a.to_string()) ); println!("version: {}", group.version()); println!( - "prev-blob-id: {}", + "prev-shell-id: {}", group - .prev_blob_id() + .prev_shell_id() .map_or("None".to_string(), |prev| prev.to_string()) ); + println!("shell-id: {}", group.to_shell().shell_id()); + println!( + "body-hash: {}", + group.body().as_ref().unwrap().raw_hash_value().unwrap() + ); } if is_all || matches.is_present("show_admins") { From 9258f5ddc12a2ffdfa63be4da9511dbdd34fb2c1 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 14 Apr 2023 15:10:31 +0800 Subject: [PATCH 539/553] Fix bugs for `ObjectShell` --- src/component/cyfs-base-meta/src/group.rs | 18 ------------------ .../cyfs-core/src/storage/object_shell.rs | 13 +++++++------ src/tools/desc-tool/Cargo.toml | 1 + src/tools/desc-tool/src/show.rs | 5 +++-- 4 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index 73cefa34b..2cc8a4535 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -176,24 +176,6 @@ impl GroupVerifier for Group { .map(|m| *m), ); - if add_admins.len() != self.admins().len() - last_admins.len() { - let msg = format!( - "Update group({}) with duplicate admins or invalid admins.", - group_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); - } - - if add_members.len() != self.members().len() - last_members.len() { - let msg = format!( - "Update group({}) with duplicate members or invalid members.", - group_id - ); - log::warn!("{}", msg); - return Err(BuckyError::new(BuckyErrorCode::Failed, msg)); - } - let additionals = add_admins .union(&add_members) .map(|id| *id) diff --git a/src/component/cyfs-core/src/storage/object_shell.rs b/src/component/cyfs-core/src/storage/object_shell.rs index 130d54ecc..509cfc1dc 100644 --- a/src/component/cyfs-core/src/storage/object_shell.rs +++ b/src/component/cyfs-core/src/storage/object_shell.rs @@ -166,9 +166,9 @@ where .raw_encode(freedom_remain, &None) .expect("encode desc signature for object-shell failed."); exist_freedom_field_flags.freedom_desc_signature(); + const_raw.signs_mut().clear_desc_signs(); } } - const_raw.signs_mut().clear_desc_signs(); } if self.flags.is_body_sign_freedom() { @@ -179,9 +179,9 @@ where .raw_encode(freedom_remain, &None) .expect("encode body signature for object-shell failed."); exist_freedom_field_flags.freedom_body_signature(); + const_raw.signs_mut().clear_body_signs(); } } - const_raw.signs_mut().clear_body_signs(); } if self.flags.is_nonce_freedom() { @@ -191,11 +191,12 @@ where .raw_encode(freedom_remain, &None) .expect("encode nonce for object-shell failed."); exist_freedom_field_flags.freedom_nonce(); + + unreachable!( + "nonce is not supported currently for the NamedObject::set_nonce is not exported." + ); + // const_raw.set_nonce(None); } - unreachable!( - "nonce is not supported currently for the NamedObject::set_nonce is not exported." - ); - // const_raw.set_nonce(None); } let freedom_attachment = if freedom_remain.len() < max_buf_size { diff --git a/src/tools/desc-tool/Cargo.toml b/src/tools/desc-tool/Cargo.toml index 1a13f5d2d..3cb0aa400 100644 --- a/src/tools/desc-tool/Cargo.toml +++ b/src/tools/desc-tool/Cargo.toml @@ -19,3 +19,4 @@ hex = "0.4" log = "0.4" simple_logger = "2.1" chrono = "0.4" +itertools = '0.10' \ No newline at end of file diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index d0e1a6426..b40ac85c2 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -5,6 +5,7 @@ use cyfs_base::{ SingleKeyObjectDesc, StandardObject, }; use cyfs_core::{AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj, GroupShell}; +use itertools::Itertools; use std::convert::TryFrom; use std::path::Path; @@ -218,7 +219,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { "immutable" } ); - for (_, member) in group.admins() { + for (_, member) in group.admins().iter().sorted_by(|l, r| l.0.cmp(r.0)) { print!("{};", member.to_string()); } println!("]"); @@ -226,7 +227,7 @@ fn show_group(group: &Group, matches: &ArgMatches) { if is_all || matches.is_present("show_members") { print!("members: ["); - for (_, member) in group.members() { + for (_, member) in group.members().iter().sorted_by(|l, r| l.0.cmp(r.0)) { print!("{};", member.to_string()); } println!("]"); From 35861f0cee4e86eb0e0f846b5228918f519618bf Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 14 Apr 2023 20:04:07 +0800 Subject: [PATCH 540/553] Verify group-zone by `MetaChain` --- src/component/cyfs-base-meta/src/group.rs | 2 +- .../cyfs-core/src/group/group_shell.rs | 12 +- .../cyfs-core/src/storage/object_shell.rs | 4 + src/component/cyfs-group/Cargo.toml | 4 +- .../src/consensus/hotstuff/hotstuff.rs | 11 +- .../src/consensus/vote/committee.rs | 2 +- .../cyfs-group/src/dec/group_manager.rs | 6 + .../cyfs-group/src/network/non_driver.rs | 61 +++++----- .../cyfs-group/src/storage/group_storage.rs | 2 +- .../cyfs-stack/src/resolver/device_manager.rs | 109 ++++-------------- .../cyfs-stack/src/resolver/obj_searcher.rs | 4 + src/tests/group-example/src/main.rs | 10 +- src/tools/desc-tool/src/show.rs | 4 +- 13 files changed, 99 insertions(+), 132 deletions(-) diff --git a/src/component/cyfs-base-meta/src/group.rs b/src/component/cyfs-base-meta/src/group.rs index 2cc8a4535..358c9141f 100644 --- a/src/component/cyfs-base-meta/src/group.rs +++ b/src/component/cyfs-base-meta/src/group.rs @@ -5,7 +5,7 @@ use cyfs_base::{ ObjectTypeCode, People, PeopleId, RawEncode, RsaCPUObjectVerifier, Signature, SingleKeyObjectDesc, Verifier, }; -use cyfs_core::{GroupShell, ObjectShell}; +use cyfs_core::ToGroupShell; async fn verify_signature( signs: Option<&Vec>, diff --git a/src/component/cyfs-core/src/group/group_shell.rs b/src/component/cyfs-core/src/group/group_shell.rs index 9281768d1..1e569d1a1 100644 --- a/src/component/cyfs-core/src/group/group_shell.rs +++ b/src/component/cyfs-core/src/group/group_shell.rs @@ -2,12 +2,14 @@ use cyfs_base::{Group, GroupType}; use crate::{ObjectShell, OBJECT_SHELL_ALL_FREEDOM}; -pub trait GroupShell: Sized { - fn to_shell(&self) -> ObjectShell; +pub type GroupShell = ObjectShell; + +pub trait ToGroupShell: Sized { + fn to_shell(&self) -> GroupShell; } -impl GroupShell for Group { - fn to_shell(&self) -> ObjectShell { - ObjectShell::::from_object(self.clone(), OBJECT_SHELL_ALL_FREEDOM) +impl ToGroupShell for Group { + fn to_shell(&self) -> GroupShell { + GroupShell::from_object(self.clone(), OBJECT_SHELL_ALL_FREEDOM) } } diff --git a/src/component/cyfs-core/src/storage/object_shell.rs b/src/component/cyfs-core/src/storage/object_shell.rs index 509cfc1dc..ffe2f3a98 100644 --- a/src/component/cyfs-core/src/storage/object_shell.rs +++ b/src/component/cyfs-core/src/storage/object_shell.rs @@ -247,6 +247,10 @@ where // update the raw object &mut self.raw } + + pub fn into_object(self) -> O { + self.raw + } } impl RawEncode for ObjectShell diff --git a/src/component/cyfs-group/Cargo.toml b/src/component/cyfs-group/Cargo.toml index 7a28cf89b..f31e91017 100644 --- a/src/component/cyfs-group/Cargo.toml +++ b/src/component/cyfs-group/Cargo.toml @@ -32,4 +32,6 @@ cyfs-core = { path = '../../component/cyfs-core', version = '0.6' } cyfs-bdt = { path = '../../component/cyfs-bdt', version = '0.7' } cyfs-debug = { path = "../../component/cyfs-debug" } cyfs-lib = { path = '../../component/cyfs-lib' } -cyfs-group-lib = { path = '../../component/cyfs-group-lib' } \ No newline at end of file +cyfs-group-lib = { path = '../../component/cyfs-group-lib' } +cyfs-meta-lib = { path = "../../component/cyfs-meta-lib" } +cyfs-base-meta = { path = "../../component/cyfs-base-meta" } \ No newline at end of file diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 7ed084e1a..198355f8b 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -11,8 +11,8 @@ use cyfs_base::{ RawEncode, RsaCPUObjectSigner, SignatureSource, Signer, }; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, - GroupProposal, GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, GroupShell, + GroupConsensusBlock, GroupConsensusBlockObject, GroupConsensusBlockProposal, GroupProposal, + GroupProposalObject, GroupRPath, HotstuffBlockQC, HotstuffTimeout, ToGroupShell, }; use cyfs_group_lib::{ExecuteResult, HotstuffBlockQCVote, HotstuffTimeoutVote}; use cyfs_lib::NONObjectInfo; @@ -958,6 +958,7 @@ impl HotstuffRunner { qc_round ); + self.update_max_quorum_round(qc_round); self.advance_round(qc_round).await; self.update_high_qc(qc); } @@ -1443,6 +1444,8 @@ impl HotstuffRunner { self.process_qc(&Some(qc)).await; + self.update_max_quorum_height(prev_block.height()); + let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader for vote-qc({}/{}/{:?}) with round {} failed {:?}", @@ -2254,8 +2257,8 @@ impl HotstuffRunner { async fn check_group_is_latest(&self, group_shell_id: &ObjectId) -> BuckyResult { let latest_group = self.committee.get_group(None).await?; let group_shell = latest_group.to_shell(); - let latest_chunk_id = group_shell.shell_id(); - Ok(&latest_chunk_id == group_shell_id) + let latest_shell_id = group_shell.shell_id(); + Ok(&latest_shell_id == group_shell_id) } async fn make_sure_result_state( diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 65caa9f51..9d64e9672 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -11,7 +11,7 @@ use cyfs_base::{ }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, - GroupConsensusBlockObject, GroupShell, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlockObject, ToGroupShell, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index f7e874cff..25d8aa591 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -9,6 +9,7 @@ use cyfs_bdt::{DatagramTunnelGuard, StackGuard}; use cyfs_core::{DecAppId, GroupConsensusBlock, GroupConsensusBlockObject, GroupRPath}; use cyfs_group_lib::{GroupCommand, GroupCommandNewRPath}; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_meta_lib::{MetaClient, MetaMinerTarget}; use crate::{ storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, @@ -34,6 +35,7 @@ struct LocalInfo { datagram: DatagramTunnelGuard, bdt_stack: StackGuard, global_state_mgr: GlobalStateManagerRawProcessorRef, + meta_client: Arc, } #[derive(Clone)] @@ -48,6 +50,7 @@ impl GroupManager { ) -> BuckyResult { let datagram = bdt_stack.datagram_manager().bind(NET_PROTOCOL_VPORT)?; let local_device_id = bdt_stack.local_device_id().object_id().clone(); + let metaclient = MetaClient::new_target(MetaMinerTarget::default()); let local_info = LocalInfo { signer: Arc::new(signer), @@ -55,6 +58,7 @@ impl GroupManager { datagram: datagram.clone(), bdt_stack, global_state_mgr, + meta_client: Arc::new(metaclient), }; let raw = GroupRPathMgrRaw { @@ -109,6 +113,7 @@ impl GroupManager { let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new( local_info.non_driver.clone(), + local_info.meta_client.clone(), dec_id.clone(), local_device_id.object_id().clone(), ); @@ -392,6 +397,7 @@ impl GroupManager { let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new( local_info.non_driver.clone(), + local_info.meta_client.clone(), dec_id.clone(), local_device_id.object_id().clone(), ); diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 700599f54..764ef1e4f 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -7,10 +7,13 @@ use cyfs_base::{ TypelessCoreObject, }; +use cyfs_base_meta::SavedMetaObject; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, + GroupShell, }; use cyfs_lib::NONObjectInfo; +use cyfs_meta_lib::MetaClient; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -39,11 +42,13 @@ pub(crate) struct NONDriverHelper { dec_id: ObjectId, cache: NONObjectCache, local_device_id: ObjectId, + meta_client: Arc, } impl NONDriverHelper { pub fn new( driver: Arc>, + meta_client: Arc, dec_id: ObjectId, local_device_id: ObjectId, ) -> Self { @@ -52,6 +57,7 @@ impl NONDriverHelper { dec_id, cache: NONObjectCache::new(), local_device_id, + meta_client, } } @@ -166,32 +172,35 @@ impl NONDriverHelper { group_shell_id: Option<&ObjectId>, from: Option<&ObjectId>, ) -> BuckyResult { - // TODO: ignore group_shell_id first - // match group_shell_id { - // Some(group_shell_id) => { - // let shell = self.get_object(group_shell_id, from).await?; - // let (group_shell, remain) = Storage::raw_decode(shell.object_raw.as_slice())?; - // assert_eq!(remain.len(), 0); - // let group = Group::from_shell(&group_shell)?; - // if &group.desc().object_id() == group_id { - // Ok(group) - // } else { - // Err(BuckyError::new(BuckyErrorCode::Unmatch, "groupid")) - // } - // } - // None => { - // // TODO: latest version from metachain - // let group = self.get_object(group_id, from).await?; - // let (group, remain) = Group::raw_decode(group.object_raw.as_slice())?; - // assert_eq!(remain.len(), 0); - // Ok(group) - // } - // } - - let group = self.get_object(group_id, from).await?; - let (group, remain) = Group::raw_decode(group.object_raw.as_slice())?; - assert_eq!(remain.len(), 0); - Ok(group) + match group_shell_id { + Some(group_shell_id) => { + let shell = self.get_object(group_shell_id, from).await?; + let (group_shell, remain) = GroupShell::raw_decode(shell.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + let group = group_shell.into_object(); + let group_id_from_shell = group.desc().object_id(); + if &group_id_from_shell == group_id { + Ok(group) + } else { + let msg = format!( + "groupid({}) from GroupShell unmatch with the original group({})", + group_id_from_shell, group_id + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) + } + } + None => { + let group = self.meta_client.get_desc(group_id).await?; + if let SavedMetaObject::Group(group) = group { + Ok(group) + } else { + let msg = format!("Object({}) from MetaChain is not a group", group_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) + } + } + } } pub async fn get_ood(&self, people_id: &PeopleId) -> BuckyResult { diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 4e38a9ef5..6966b4d56 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -6,7 +6,7 @@ use cyfs_base::{ }; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, GroupShell, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, ToGroupShell, HotstuffBlockQC, HotstuffTimeout, }; use cyfs_group_lib::GroupRPathStatus; diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index 93652f59c..4fc2856d6 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -5,7 +5,6 @@ use cyfs_bdt::DeviceCache; use cyfs_lib::*; use async_trait::async_trait; -use std::collections::HashSet; use std::collections::{hash_map::Entry, HashMap}; use std::sync::{Arc, RwLock}; @@ -128,97 +127,33 @@ impl DeviceInfoManagerImpl { object_id: &ObjectId, object: &Arc, ) -> BuckyResult<()> { - // TODO: 先验证所有成员签名,但这跟Group的变更策略有关,最终可能要跟链上比对才能验证,因为如果Group变更只需要部分成员签名,这将导致Group上只携带部分成员的签名 - if object_id.obj_type_code() != ObjectTypeCode::Group { + // TODO: use object from `MetaChain` temporarily + let group = self + .obj_searcher + .search_ex(None, object_id, ObjectSearcherFlags::meta_only()) + .await?; + + let (group, _) = Group::raw_decode(group.object_raw.as_slice())?; + let group_id_meta = group.desc().object_id(); + if &group_id_meta != object_id { let msg = format!( - "verify object own's body sign by owner failed for expect group, id = {}", - object_id + "group({}) from MetaChain is unmatch with needed({}).", + group_id_meta, object_id ); - warn!("{}", msg); + log::warn!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } - - let group = object.as_group(); - let sign_object_ids = HashSet::::from_iter( - [ - group.admins().iter().map(|m| m.1.id).collect::>(), - group.members().iter().map(|m| m.1.id).collect::>(), - ] - .concat() - .into_iter(), - ); - - // all singatures - let results = futures::future::join_all( - sign_object_ids - .into_iter() - .map(|id| self.verify_with_object(object_id.clone(), object.clone(), id)), - ) - .await; - - results - .into_iter() - .find(|r| r.is_err()) - .map_or(Ok(()), |r| r) - } - - async fn verify_with_object( - &self, - object_id: ObjectId, - object: Arc, - signer_id: ObjectId, - ) -> BuckyResult<()> { - let mut signer_obj = self - .obj_searcher - .search_ex(None, &signer_id, ObjectSearcherFlags::full()) - .await - .map_err(|err| { - error!( - "verify object(group) own's body sign find signer failed! id={}, err={:?}", - object_id, err - ); - err - })?; - - let singer_obj_any = signer_obj.object.take(); - let req = VerifyObjectInnerRequest { - sign_type: VerifySignType::Both, - object: ObjectInfo { - object_id: object_id.clone(), - object: object.clone(), - }, - sign_object: VerifyObjectType::Object(NONSlimObjectInfo::new( - signer_id, - Some(signer_obj.object_raw), - singer_obj_any, - )), - }; - - match self.obj_verifier.verify_object_inner(req).await { - Ok(ret) => { - if ret.valid { - info!( - "verify object(group) own's body sign success! id={}", - object_id, - ); - Ok(()) - } else { - let msg = format!( - "verify object(group) own's body sign unmatch! id={}", - object_id, - ); - error!("{}", msg); - Err(BuckyError::new(BuckyErrorCode::InvalidSignature, msg)) - } - } - Err(e) => { - error!( - "verify object(group) own's body sign by owner error! id={}, {}", - object_id, e - ); - Err(e) - } + let body_hash_meta = group.body().as_ref().unwrap().raw_hash_value()?; + let body_hash = object.body_hash()?; + if Some(body_hash_meta) != body_hash { + let msg = format!( + "group({}) body-hash({}) from MetaChain is unmatch with needed({:?}).", + object_id, body_hash_meta, body_hash + ); + log::warn!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); } + Ok(()) } async fn verfiy_owner(&self, device_id: &DeviceId, device: Option<&Device>) -> BuckyResult<()> { diff --git a/src/component/cyfs-stack/src/resolver/obj_searcher.rs b/src/component/cyfs-stack/src/resolver/obj_searcher.rs index 394679625..45c2278e7 100644 --- a/src/component/cyfs-stack/src/resolver/obj_searcher.rs +++ b/src/component/cyfs-stack/src/resolver/obj_searcher.rs @@ -28,6 +28,10 @@ impl ObjectSearcherFlags { pub fn local_and_meta() -> u32 { OBJECT_SEARCH_FLAG_META | OBJECT_SEARCH_FLAG_NOC } + + pub fn meta_only() -> u32 { + OBJECT_SEARCH_FLAG_META + } } #[async_trait] diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 8ea9e60ba..b224d06f1 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -45,11 +45,11 @@ use crate::{ * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-7 -d=test-group/members/people-7.desc 1 0 * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-8 -d=test-group/members/people-8.desc 1 0 * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-9 -d=test-group/members/people-9.desc 1 0 - * + * * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-1.desc -d=67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc 1 0 - * + * * .\desc-tool show -a 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc - * + * * .\desc-tool modify 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc --prev_blob= -v=1 */ @@ -1249,7 +1249,7 @@ async fn main_run() { log::info!("proposals will be prepared."); - let PROPOSAL_COUNT = 200usize; + let PROPOSAL_COUNT = 20000usize; for i in 1..PROPOSAL_COUNT { let (_, stack) = member_stacks.get(i % member_stacks.len()).unwrap(); let group_mgr = member_group_mgrs.get(i % member_group_mgrs.len()).unwrap(); @@ -1316,7 +1316,7 @@ async fn main_run() { ); }); - if i % 28 == 0 { + if i % 1 == 0 { async_std::task::sleep(Duration::from_millis(4000)).await; log::info!("will push new proposals, i: {}", i); } diff --git a/src/tools/desc-tool/src/show.rs b/src/tools/desc-tool/src/show.rs index b40ac85c2..00c609e7a 100644 --- a/src/tools/desc-tool/src/show.rs +++ b/src/tools/desc-tool/src/show.rs @@ -4,7 +4,9 @@ use cyfs_base::{ InnerNode, NDNObjectInfo, NamedObject, ObjectDesc, RawEncode, RawFrom, SignatureSource, SingleKeyObjectDesc, StandardObject, }; -use cyfs_core::{AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj, GroupShell}; +use cyfs_core::{ + AppList, AppListObj, AppStatusObj, CoreObjectType, DecApp, DecAppObj, ToGroupShell, +}; use itertools::Itertools; use std::convert::TryFrom; use std::path::Path; From 0a37078010ae68a4d2efd27ac82814915cc4331c Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 15 Apr 2023 20:37:04 +0800 Subject: [PATCH 541/553] Hold lifespan of the history versions of group in `ObjectShell` on `GroupState` --- .../src/consensus/hotstuff/hotstuff.rs | 3 + .../src/consensus/vote/committee.rs | 15 +- .../cyfs-group/src/dec/group_manager.rs | 78 ++++- .../cyfs-group/src/dec/rpath_client.rs | 13 +- .../cyfs-group/src/dec/rpath_service.rs | 9 +- .../src/dec_state/dec_state_synchronizer.rs | 9 +- .../cyfs-group/src/dec_state/state_pusher.rs | 23 +- .../cyfs-group/src/network/non_driver.rs | 45 +-- .../cyfs-group/src/statepath/design.md | 5 +- .../src/statepath/group_shell_statepath.rs | 39 +++ .../src/statepath/group_statepath.rs | 19 +- src/component/cyfs-group/src/statepath/mod.rs | 2 + .../cyfs-group/src/storage/group_shell_mgr.rs | 331 ++++++++++++++++++ .../cyfs-group/src/storage/group_storage.rs | 34 +- src/component/cyfs-group/src/storage/mod.rs | 2 + .../cyfs-stack/src/forward/forward.rs | 7 +- src/tests/group-example/src/main.rs | 28 +- 17 files changed, 538 insertions(+), 124 deletions(-) create mode 100644 src/component/cyfs-group/src/statepath/group_shell_statepath.rs create mode 100644 src/component/cyfs-group/src/storage/group_shell_mgr.rs diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 198355f8b..e12e04da7 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -23,6 +23,7 @@ use crate::{ consensus::synchronizer::Synchronizer, dec_state::{CallReplyNotifier, CallReplyWaiter, StatePusher}, helper::Timer, + storage::GroupShellManager, Committee, GroupObjectMapProcessor, GroupStorage, HotstuffMessage, PendingProposalConsumer, RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, GROUP_DEFAULT_CONSENSUS_INTERVAL, HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, @@ -58,6 +59,7 @@ impl Hotstuff { signer: Arc, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, proposal_consumer: PendingProposalConsumer, event_notifier: RPathEventNotifier, rpath: GroupRPath, @@ -70,6 +72,7 @@ impl Hotstuff { network_sender.clone(), rpath.clone(), non_driver.clone(), + shell_mgr, ); let mut runner = HotstuffRunner::new( diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 9d64e9672..d0a59bb3e 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -11,25 +11,32 @@ use cyfs_base::{ }; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockDesc, GroupConsensusBlockDescContent, - GroupConsensusBlockObject, ToGroupShell, HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlockObject, HotstuffBlockQC, HotstuffTimeout, ToGroupShell, }; use cyfs_group_lib::{HotstuffBlockQCVote, HotstuffTimeoutVote}; -use crate::network::NONDriverHelper; +use crate::{network::NONDriverHelper, storage::GroupShellManager}; #[derive(Clone)] pub(crate) struct Committee { group_id: ObjectId, non_driver: NONDriverHelper, + shell_mgr: GroupShellManager, local_device_id: ObjectId, group_cache: Arc>>, // (group_shell_id, group) } impl Committee { - pub fn new(group_id: ObjectId, non_driver: NONDriverHelper, local_device_id: ObjectId) -> Self { + pub fn new( + group_id: ObjectId, + non_driver: NONDriverHelper, + shell_mgr: GroupShellManager, + local_device_id: ObjectId, + ) -> Self { Committee { group_id, non_driver, + shell_mgr, group_cache: Arc::new(RwLock::new(HashMap::new())), local_device_id, } @@ -360,7 +367,7 @@ impl Committee { } let group = self - .non_driver + .shell_mgr .get_group(&self.group_id, shell_id, from) .await?; diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 25d8aa591..fc5a08986 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -12,8 +12,9 @@ use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use cyfs_meta_lib::{MetaClient, MetaMinerTarget}; use crate::{ - storage::GroupStorage, HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, - RPathClient, RPathEventNotifier, RPathService, NET_PROTOCOL_VPORT, + storage::{GroupShellManager, GroupStorage}, + HotstuffMessage, HotstuffPackage, NONDriver, NONDriverHelper, RPathClient, RPathEventNotifier, + RPathService, NET_PROTOCOL_VPORT, }; type ServiceByRPath = HashMap; @@ -27,6 +28,7 @@ type ClientByGroup = HashMap; struct GroupRPathMgrRaw { service_by_group: ServiceByGroup, client_by_group: ClientByGroup, + shell_mgr: HashMap, } struct LocalInfo { @@ -64,6 +66,7 @@ impl GroupManager { let raw = GroupRPathMgrRaw { service_by_group: ServiceByGroup::default(), client_by_group: ClientByGroup::default(), + shell_mgr: HashMap::default(), }; let mgr = Self(Arc::new((local_info, RwLock::new(raw)))); @@ -113,7 +116,6 @@ impl GroupManager { let state_mgr = local_info.global_state_mgr.clone(); let non_driver = NONDriverHelper::new( local_info.non_driver.clone(), - local_info.meta_client.clone(), dec_id.clone(), local_device_id.object_id().clone(), ); @@ -139,11 +141,15 @@ impl GroupManager { let state_proccessor = state_mgr .load_root_state(local_device_id.object_id(), Some(local_id), true) .await?; + let shell_mgr = self + .check_group_shell_mgr(group_id, non_driver.clone(), None) + .await?; let client = RPathClient::load( local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), state_proccessor.unwrap(), non_driver, + shell_mgr, network_sender, ) .await?; @@ -397,7 +403,6 @@ impl GroupManager { let signer = local_info.signer.clone(); let non_driver = NONDriverHelper::new( local_info.non_driver.clone(), - local_info.meta_client.clone(), dec_id.clone(), local_device_id.object_id().clone(), ); @@ -471,6 +476,9 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { + let shell_mgr = self + .check_group_shell_mgr(group_id, non_driver.clone(), remote) + .await?; let service = RPathService::load( local_id, local_device_id.object_id().clone(), @@ -479,6 +487,7 @@ impl GroupManager { RPathEventNotifier::new(non_driver.clone()), network_sender, non_driver, + shell_mgr, store, ) .await?; @@ -524,4 +533,65 @@ impl GroupManager { assert!(result.is_none()); Ok(()) } + + async fn check_group_shell_mgr( + &self, + group_id: &ObjectId, + non_driver: NONDriverHelper, + remote: Option<&ObjectId>, + ) -> BuckyResult { + { + let raw = self.read().await; + if let Some(shell_mgr) = raw.shell_mgr.get(group_id) { + return Ok(shell_mgr.clone()); + } + } + + let local_info = self.local_info(); + let ret = GroupShellManager::load( + group_id, + non_driver.clone(), + local_info.meta_client.clone(), + local_info.bdt_stack.local_device_id().object_id().clone(), + &local_info.global_state_mgr.clone(), + ) + .await; + + let shell_mgr = match ret { + Ok(shell_mgr) => shell_mgr, + Err(err) => { + if err.code() == BuckyErrorCode::NotFound { + log::debug!( + "shells of group({}) not found, will create automatically.", + group_id + ); + GroupShellManager::create( + group_id, + non_driver.clone(), + local_info.meta_client.clone(), + local_info.bdt_stack.local_device_id().object_id().clone(), + &local_info.global_state_mgr.clone(), + remote, + ) + .await? + } else { + log::error!("load shells of group({}) failed, err {:?}", group_id, err); + return Err(err); + } + } + }; + + { + let mut raw = self.write().await; + let shell_mgr = match raw.shell_mgr.get(group_id) { + Some(shell_mgr) => shell_mgr.clone(), + None => { + raw.shell_mgr.insert(group_id.clone(), shell_mgr.clone()); + shell_mgr + } + }; + + Ok(shell_mgr) + } + } } diff --git a/src/component/cyfs-group/src/dec/rpath_client.rs b/src/component/cyfs-group/src/dec/rpath_client.rs index 43fb8e559..45aa57dd4 100644 --- a/src/component/cyfs-group/src/dec/rpath_client.rs +++ b/src/component/cyfs-group/src/dec/rpath_client.rs @@ -10,7 +10,7 @@ use rand::Rng; use crate::{ dec_state::{DecStateRequestor, DecStateSynchronizer}, - storage::DecStorage, + storage::{DecStorage, GroupShellManager}, Committee, HotstuffMessage, CLIENT_POLL_TIMEOUT, }; @@ -18,6 +18,7 @@ struct RPathClientRaw { rpath: GroupRPath, local_device_id: ObjectId, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, network_sender: crate::network::Sender, state_sync: DecStateSynchronizer, state_requestor: DecStateRequestor, @@ -32,12 +33,14 @@ impl RPathClient { rpath: GroupRPath, state_processor: GlobalStateRawProcessorRef, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, network_sender: crate::network::Sender, ) -> BuckyResult { let dec_store = DecStorage::load(state_processor).await?; let committee = Committee::new( rpath.group_id().clone(), non_driver.clone(), + shell_mgr.clone(), local_device_id, ); @@ -46,6 +49,7 @@ impl RPathClient { rpath.clone(), committee.clone(), non_driver.clone(), + shell_mgr.clone(), dec_store.clone(), ); @@ -65,6 +69,7 @@ impl RPathClient { local_device_id, state_sync, state_requestor, + shell_mgr, }; Ok(Self(Arc::new(raw))) @@ -83,7 +88,7 @@ impl RPathClient { // TODO: signature let group = self .0 - .non_driver + .shell_mgr .get_group(proposal.rpath().group_id(), None, None) .await?; let oods = group.ood_list_with_distance(&self.0.local_device_id); @@ -148,7 +153,7 @@ impl RPathClient { pub async fn refresh_state(&self) -> BuckyResult<()> { let group = self .0 - .non_driver + .shell_mgr .get_group(&self.0.rpath.group_id(), None, None) .await?; @@ -166,7 +171,7 @@ impl RPathClient { pub async fn get_by_path(&self, sub_path: &str) -> BuckyResult> { let group = self .0 - .non_driver + .shell_mgr .get_group(self.0.rpath.group_id(), None, None) .await?; diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index a43f99b99..eb743355f 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -8,8 +8,10 @@ use cyfs_core::{GroupProposal, GroupRPath}; use cyfs_lib::NONObjectInfo; use crate::{ - network::NONDriverHelper, storage::GroupStorage, Committee, Hotstuff, HotstuffMessage, - PendingProposalHandler, PendingProposalMgr, RPathEventNotifier, + network::NONDriverHelper, + storage::{GroupShellManager, GroupStorage}, + Committee, Hotstuff, HotstuffMessage, PendingProposalHandler, PendingProposalMgr, + RPathEventNotifier, }; struct RPathServiceRaw { @@ -33,12 +35,14 @@ impl RPathService { event_notifier: RPathEventNotifier, network_sender: crate::network::Sender, non_driver: NONDriverHelper, + shell_mgr: GroupShellManager, store: GroupStorage, ) -> BuckyResult { let (pending_proposal_handle, pending_proposal_consumer) = PendingProposalMgr::new(); let committee = Committee::new( rpath.group_id().clone(), non_driver.clone(), + shell_mgr.clone(), local_device_id, ); let hotstuff = Hotstuff::new( @@ -49,6 +53,7 @@ impl RPathService { signer, network_sender.clone(), non_driver.clone(), + shell_mgr, pending_proposal_consumer, event_notifier, rpath.clone(), diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index 637124113..f3f15ea8a 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -9,7 +9,7 @@ use futures::FutureExt; use crate::{ network::NONDriverHelper, - storage::{DecStorage, DecStorageCache}, + storage::{DecStorage, DecStorageCache, GroupShellManager}, Committee, CHANNEL_CAPACITY, }; @@ -39,6 +39,7 @@ impl DecStateSynchronizer { rpath: GroupRPath, committee: Committee, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, store: DecStorage, ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); @@ -52,6 +53,7 @@ impl DecStateSynchronizer { rx, store, non_driver, + shell_mgr, notifier.clone(), ); @@ -129,6 +131,7 @@ struct DecStateSynchronizerRunner { update_notifies: Option, non_driver: NONDriverHelper, + shell_mgr: GroupShellManager, proposal_result_notifier: CallReplyNotifier>>, } @@ -147,6 +150,7 @@ impl DecStateSynchronizerRunner { )>, store: DecStorage, non_driver: NONDriverHelper, + shell_mgr: GroupShellManager, proposal_result_notifier: CallReplyNotifier>>, ) -> Self { Self { @@ -161,6 +165,7 @@ impl DecStateSynchronizerRunner { non_driver, proposal_result_notifier, committee, + shell_mgr, } } @@ -278,7 +283,7 @@ impl DecStateSynchronizerRunner { if let Some(state_cache) = state_cache { let group_shell_id = state_cache.header_block.group_shell_id().clone(); let group = self - .non_driver + .shell_mgr .get_group(self.rpath.group_id(), Some(&group_shell_id), None) .await; if let Ok(group) = group { diff --git a/src/component/cyfs-group/src/dec_state/state_pusher.rs b/src/component/cyfs-group/src/dec_state/state_pusher.rs index 32325324d..6d9d62a60 100644 --- a/src/component/cyfs-group/src/dec_state/state_pusher.rs +++ b/src/component/cyfs-group/src/dec_state/state_pusher.rs @@ -9,7 +9,9 @@ use cyfs_core::{GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, G use cyfs_lib::NONObjectInfo; use futures::FutureExt; -use crate::{HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND}; +use crate::{ + storage::GroupShellManager, HotstuffMessage, CHANNEL_CAPACITY, STATE_NOTIFY_COUNT_PER_ROUND, +}; enum StatePushMessage { ProposalResult(GroupProposal, BuckyError), @@ -30,11 +32,19 @@ impl StatePusher { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, ) -> Self { let (tx, rx) = async_std::channel::bounded(CHANNEL_CAPACITY); - let mut runner = - StateChanggeRunner::new(local_id, network_sender, rpath, non_driver, tx.clone(), rx); + let mut runner = StateChanggeRunner::new( + local_id, + network_sender, + rpath, + non_driver, + shell_mgr, + tx.clone(), + rx, + ); async_std::task::spawn(async move { runner.run().await }); @@ -99,6 +109,7 @@ struct StateChanggeRunner { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, tx_notifier: async_std::channel::Sender, rx_notifier: async_std::channel::Receiver, delay_notify_times: usize, @@ -113,6 +124,7 @@ impl StateChanggeRunner { network_sender: crate::network::Sender, rpath: GroupRPath, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, tx_notifier: async_std::channel::Sender, rx_notifier: async_std::channel::Receiver, ) -> Self { @@ -127,6 +139,7 @@ impl StateChanggeRunner { notify_progress: None, local_id, request_last_state_remotes: HashSet::new(), + shell_mgr, } } @@ -220,7 +233,7 @@ impl StateChanggeRunner { if block.group_shell_id() != progress.header_block.group_shell_id() { let group = self - .non_driver + .shell_mgr .get_group(block.rpath().group_id(), Some(block.group_shell_id()), None) .await; if group.is_err() { @@ -242,7 +255,7 @@ impl StateChanggeRunner { } None => { let group = self - .non_driver + .shell_mgr .get_group(block.rpath().group_id(), Some(block.group_shell_id()), None) .await; if group.is_err() { diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 764ef1e4f..4fb20f79b 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -2,18 +2,15 @@ use std::{collections::HashMap, sync::Arc, time::Instant}; use async_std::sync::RwLock; use cyfs_base::{ - AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, Group, NamedObject, + AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, Device, DeviceId, NamedObject, ObjectDesc, ObjectId, ObjectTypeCode, People, PeopleId, RawConvertTo, RawDecode, RawFrom, TypelessCoreObject, }; -use cyfs_base_meta::SavedMetaObject; use cyfs_core::{ GroupConsensusBlock, GroupConsensusBlockObject, GroupProposal, GroupQuorumCertificate, - GroupShell, }; use cyfs_lib::NONObjectInfo; -use cyfs_meta_lib::MetaClient; use crate::{MEMORY_CACHE_DURATION, MEMORY_CACHE_SIZE}; @@ -42,13 +39,11 @@ pub(crate) struct NONDriverHelper { dec_id: ObjectId, cache: NONObjectCache, local_device_id: ObjectId, - meta_client: Arc, } impl NONDriverHelper { pub fn new( driver: Arc>, - meta_client: Arc, dec_id: ObjectId, local_device_id: ObjectId, ) -> Self { @@ -57,7 +52,6 @@ impl NONDriverHelper { dec_id, cache: NONObjectCache::new(), local_device_id, - meta_client, } } @@ -166,43 +160,6 @@ impl NONDriverHelper { Ok(block) } - pub async fn get_group( - &self, - group_id: &ObjectId, - group_shell_id: Option<&ObjectId>, - from: Option<&ObjectId>, - ) -> BuckyResult { - match group_shell_id { - Some(group_shell_id) => { - let shell = self.get_object(group_shell_id, from).await?; - let (group_shell, remain) = GroupShell::raw_decode(shell.object_raw.as_slice())?; - assert_eq!(remain.len(), 0); - let group = group_shell.into_object(); - let group_id_from_shell = group.desc().object_id(); - if &group_id_from_shell == group_id { - Ok(group) - } else { - let msg = format!( - "groupid({}) from GroupShell unmatch with the original group({})", - group_id_from_shell, group_id - ); - log::warn!("{}", msg); - Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) - } - } - None => { - let group = self.meta_client.get_desc(group_id).await?; - if let SavedMetaObject::Group(group) = group { - Ok(group) - } else { - let msg = format!("Object({}) from MetaChain is not a group", group_id); - log::warn!("{}", msg); - Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) - } - } - } - } - pub async fn get_ood(&self, people_id: &PeopleId) -> BuckyResult { let people = self .get_object(people_id.object_id(), Some(people_id.object_id())) diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 68535c894..967f61b48 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -8,6 +8,10 @@ | |--option-->GroupOption | |--${group-id} +| |--${DecId("shells", ${group-id})} +| | |--.shells +| | |--.latest-->GroupShell // latest version +| | |--${group.version}-->GroupShell // add shells for history versions of group | |--${dec-id} | |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 | | // APP控制的实体状态,通常是个map-id @@ -18,7 +22,6 @@ | | // 且不同${r-path}之间是并列的,不能嵌套 | |--.link // 区块链结构,记录状态变更链条 | |--${r-path} -| |--group-shell-->ObjectShell(Group) | |--users | | |--${user-id} | | |--xxx diff --git a/src/component/cyfs-group/src/statepath/group_shell_statepath.rs b/src/component/cyfs-group/src/statepath/group_shell_statepath.rs new file mode 100644 index 000000000..f529af9b8 --- /dev/null +++ b/src/component/cyfs-group/src/statepath/group_shell_statepath.rs @@ -0,0 +1,39 @@ +const STATE_PATH_SEPARATOR: &str = "/"; +pub const GROUP_STATE_PATH_SHELLS: &str = ".shells"; +pub const GROUP_STATE_PATH_LATEST: &str = ".latest"; + +pub struct GroupShellStatePath { + root: &'static str, + shells: String, + latest: String, +} + +impl GroupShellStatePath { + pub fn new() -> Self { + Self { + root: STATE_PATH_SEPARATOR, + shells: Self::join(&["", GROUP_STATE_PATH_SHELLS]), + latest: Self::join(&["", GROUP_STATE_PATH_SHELLS, GROUP_STATE_PATH_LATEST]), + } + } + + pub fn join(fields: &[&str]) -> String { + fields.join(STATE_PATH_SEPARATOR) + } + + pub fn root(&self) -> &str { + self.root + } + + pub fn shells(&self) -> &str { + self.shells.as_str() + } + + pub fn latest(&self) -> &str { + self.latest.as_str() + } + + pub fn version(&self, version: u64) -> String { + Self::join(&[self.shells.as_str(), version.to_string().as_str()]) + } +} diff --git a/src/component/cyfs-group/src/statepath/group_statepath.rs b/src/component/cyfs-group/src/statepath/group_statepath.rs index 981e20a67..86e51d816 100644 --- a/src/component/cyfs-group/src/statepath/group_statepath.rs +++ b/src/component/cyfs-group/src/statepath/group_statepath.rs @@ -1,9 +1,8 @@ -use cyfs_base::{ObjectId, ObjectIdDataBuilder}; +use cyfs_base::ObjectId; pub const STATE_PATH_SEPARATOR: &str = "/"; pub const GROUP_STATE_PATH_DEC_STATE: &str = ".dec-state"; pub const GROUP_STATE_PATH_LINK: &str = ".link"; -pub const GROUP_STATE_PATH_GROUP_SHELL: &str = "group-shell"; pub const GROUP_STATE_PATH_LAST_VOTE_ROUNDS: &str = "last-vote-round"; pub const GROUP_STATE_PATH_LAST_QC: &str = "last-qc"; pub const GROUP_STATE_PATH_LAST_TC: &str = "last-tc"; @@ -20,17 +19,11 @@ pub const GROUP_STATE_PATH_ADDING: &str = "adding"; pub const STATEPATH_GROUP_DEC_RPATH: &str = ".update"; pub const STATEPATH_GROUP_DEC_LATEST_VERSION: &str = "latest-version"; -lazy_static::lazy_static! { - pub static ref STATEPATH_GROUP_DEC_ID: ObjectId = ObjectIdDataBuilder::new().data(".group".as_bytes()).build().unwrap(); - pub static ref STATEPATH_GROUP_DEC_ID_STR: String = STATEPATH_GROUP_DEC_ID.to_string(); -} - pub struct GroupStatePath { rpath: String, root: String, dec_state: String, link: String, - group_shell: String, last_vote_round: String, last_qc: String, last_tc: String, @@ -49,12 +42,6 @@ impl GroupStatePath { root: Self::join(&["", rpath.as_str()]), dec_state: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_DEC_STATE]), link: Self::join(&["", rpath.as_str(), GROUP_STATE_PATH_LINK]), - group_shell: Self::join(&[ - "", - rpath.as_str(), - GROUP_STATE_PATH_LINK, - GROUP_STATE_PATH_GROUP_SHELL, - ]), last_vote_round: Self::join(&[ "", rpath.as_str(), @@ -138,10 +125,6 @@ impl GroupStatePath { self.link.as_str() } - pub fn group_shell(&self) -> &str { - self.group_shell.as_str() - } - pub fn last_vote_round(&self) -> &str { self.last_vote_round.as_str() } diff --git a/src/component/cyfs-group/src/statepath/mod.rs b/src/component/cyfs-group/src/statepath/mod.rs index 8c56d3d82..7ff8c583f 100644 --- a/src/component/cyfs-group/src/statepath/mod.rs +++ b/src/component/cyfs-group/src/statepath/mod.rs @@ -1,5 +1,7 @@ mod dec_statepath; mod group_statepath; +mod group_shell_statepath; pub(crate) use dec_statepath::*; +pub(crate) use group_shell_statepath::*; pub(crate) use group_statepath::*; diff --git a/src/component/cyfs-group/src/storage/group_shell_mgr.rs b/src/component/cyfs-group/src/storage/group_shell_mgr.rs new file mode 100644 index 000000000..72dc6fb9a --- /dev/null +++ b/src/component/cyfs-group/src/storage/group_shell_mgr.rs @@ -0,0 +1,331 @@ +use std::{collections::HashMap, sync::Arc}; + +use async_std::sync::RwLock; +use cyfs_base::{ + BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, + ObjectMapRootManagerRef, OpEnvPathAccess, RawConvertTo, RawDecode, +}; +use cyfs_base_meta::SavedMetaObject; +use cyfs_core::{DecApp, DecAppObj, GroupShell, ToGroupShell}; +use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; +use cyfs_meta_lib::MetaClient; + +use crate::{GroupShellStatePath, NONDriverHelper}; + +const ACCESS: Option = None; + +struct GroupShellCache { + latest_shell_id: ObjectId, + groups_by_shell: HashMap>, + groups_by_version: HashMap>, +} + +struct GroupShellManagerRaw { + cache: RwLock, + shell_state: ObjectMapRootManagerRef, + state_path: GroupShellStatePath, + meta_client: Arc, + non_driver: NONDriverHelper, +} + +#[derive(Clone)] +pub struct GroupShellManager(Arc); + +impl GroupShellManager { + pub(crate) async fn create( + group_id: &ObjectId, + non_driver: NONDriverHelper, + meta_client: Arc, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, + remote: Option<&ObjectId>, + ) -> BuckyResult { + let (group, shell_id) = + Self::get_group_impl(&non_driver, &meta_client, group_id, None, remote, None).await?; + + let shell_dec_id = Self::shell_dec_id(group_id); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group-shell state failed."); + + let shell_state = group_state + .get_dec_root_manager(&shell_dec_id, true) + .await?; + + let group_version = group.version(); + let group = Arc::new(group); + let raw = GroupShellManagerRaw { + cache: RwLock::new(GroupShellCache { + latest_shell_id: shell_id, + groups_by_shell: HashMap::from([(shell_id.clone(), group.clone())]), + groups_by_version: HashMap::from([(group.version(), group)]), + }), + shell_state, + meta_client, + non_driver, + state_path: GroupShellStatePath::new(), + }; + + let ret = Self(Arc::new(raw)); + Self::mount_shell( + &ret.0.shell_state, + &ret.0.state_path, + &shell_id, + group_version, + &None, + true, + ) + .await?; + + Ok(ret) + } + + pub(crate) async fn load( + group_id: &ObjectId, + non_driver: NONDriverHelper, + meta_client: Arc, + local_device_id: ObjectId, + root_state_mgr: &GlobalStateManagerRawProcessorRef, + ) -> BuckyResult { + let shell_dec_id = Self::shell_dec_id(group_id); + + let group_state = root_state_mgr + .load_root_state(group_id, Some(group_id.clone()), true) + .await? + .expect("create group-shell state failed."); + + let shell_state = group_state + .get_dec_root_manager(&shell_dec_id, true) + .await?; + + // load from cache + let state_path = GroupShellStatePath::new(); + + let op_env = shell_state.create_op_env(ACCESS)?; + let latest_shell_id = op_env.get_by_path(state_path.latest()).await?; + op_env.abort()?; + + let latest_shell_id = match latest_shell_id { + Some(latest_shell_id) => latest_shell_id, + None => { + return Err(BuckyError::new( + BuckyErrorCode::NotFound, + format!("group({}) state for shell is not exist.", group_id), + )) + } + }; + + let (group, latest_shell_id) = match Self::get_group_impl( + &non_driver, + &meta_client, + group_id, + Some(&latest_shell_id), + None, + None, + ) + .await + { + Ok(cache) => cache, + Err(err) => { + log::error!( + "get group({}) with shell({}) mounted to cache failed {:?}, will research it.", + group_id, + latest_shell_id, + err + ); + let (group, shell_id) = + Self::get_group_impl(&non_driver, &meta_client, group_id, None, None, None) + .await?; + + Self::mount_shell( + &shell_state, + &state_path, + &shell_id, + group.version(), + &Some(latest_shell_id), + true, + ) + .await?; + + (group, shell_id) + } + }; + + let group = Arc::new(group); + let raw = GroupShellManagerRaw { + cache: RwLock::new(GroupShellCache { + latest_shell_id, + groups_by_shell: HashMap::from([(latest_shell_id.clone(), group.clone())]), + groups_by_version: HashMap::from([(group.version(), group)]), + }), + shell_state, + meta_client, + non_driver, + state_path: GroupShellStatePath::new(), + }; + + let ret = Self(Arc::new(raw)); + + Ok(ret) + } + + pub fn group(&self) -> Group { + async_std::task::block_on(async move { + let cache = self.0.cache.read().await; + let group = cache + .groups_by_shell + .get(&cache.latest_shell_id) + .expect("lastest group must be exists."); + group.as_ref().clone() + }) + } + + pub async fn get_group( + &self, + group_id: &ObjectId, + group_shell_id: Option<&ObjectId>, + from: Option<&ObjectId>, + ) -> BuckyResult { + let latest_shell_id = { + let cache = self.0.cache.read().await; + if let Some(shell_id) = group_shell_id.as_ref() { + let group = cache.groups_by_shell.get(*shell_id); + if let Some(group) = group { + return Ok(group.as_ref().clone()); + } + } + cache.latest_shell_id + }; + + let (group, shell_id) = Self::get_group_impl( + &self.0.non_driver, + &self.0.meta_client, + group_id, + group_shell_id, + from, + Some(&latest_shell_id), + ) + .await?; + + Self::mount_shell( + &self.0.shell_state, + &self.0.state_path, + &shell_id, + group.version(), + &Some(latest_shell_id), + group_shell_id.is_none(), + ) + .await?; + + { + let mut cache = self.0.cache.write().await; + let cached_group = Arc::new(group.clone()); + if cache + .groups_by_shell + .insert(shell_id, cached_group.clone()) + .is_none() + { + cache + .groups_by_version + .insert(group.version(), cached_group.clone()); + } + } + + Ok(group) + } + + async fn mount_shell( + shell_state: &ObjectMapRootManagerRef, + state_path: &GroupShellStatePath, + shell_id: &ObjectId, + version: u64, + prev_latest_shell_id: &Option, + is_latest: bool, + ) -> BuckyResult<()> { + let op_env = shell_state.create_op_env(ACCESS)?; + + let version_path = state_path.version(version); + op_env + .set_with_path(version_path.as_str(), shell_id, &None, true) + .await?; + + if is_latest { + match prev_latest_shell_id { + Some(prev_latest_shell_id) => { + if prev_latest_shell_id != shell_id { + op_env + .set_with_path( + state_path.latest(), + shell_id, + &Some(*prev_latest_shell_id), + false, + ) + .await?; + } + } + None => { + op_env + .insert_with_path(state_path.latest(), shell_id) + .await?; + } + } + } + + op_env.commit().await.map(|_| ()) + } + + async fn get_group_impl( + non_driver: &NONDriverHelper, + meta_client: &MetaClient, + group_id: &ObjectId, + group_shell_id: Option<&ObjectId>, + from: Option<&ObjectId>, + latest_group_shell_id: Option<&ObjectId>, + ) -> BuckyResult<(Group, ObjectId)> { + match group_shell_id { + Some(group_shell_id) => { + let shell = non_driver.get_object(group_shell_id, from).await?; + let (group_shell, remain) = GroupShell::raw_decode(shell.object_raw.as_slice())?; + assert_eq!(remain.len(), 0); + let group = group_shell.into_object(); + let body_hash = group.body().as_ref().unwrap().calculate_hash()?; + // TODO: 用`body_hash`从链上验证其合法性 + let group_id_from_shell = group.desc().object_id(); + if &group_id_from_shell == group_id { + Ok((group, group_shell_id.clone())) + } else { + let msg = format!( + "groupid({}) from GroupShell unmatch with the original group({})", + group_id_from_shell, group_id + ); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) + } + } + None => { + let group = meta_client.get_desc(group_id).await?; + if let SavedMetaObject::Group(group) = group { + let group_shell = group.to_shell(); + let shell_id = group_shell.shell_id(); + if latest_group_shell_id != Some(&shell_id) { + // put to noc + let shell_obj = NONObjectInfo::new(shell_id, group_shell.to_vec()?, None); + non_driver.put_object(shell_obj).await?; + } + + Ok((group, shell_id)) + } else { + let msg = format!("Object({}) from MetaChain is not a group", group_id); + log::warn!("{}", msg); + Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)) + } + } + } + } + + fn shell_dec_id(group_id: &ObjectId) -> ObjectId { + DecApp::generate_id(group_id.clone(), "shell") + } +} diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 6966b4d56..f272f95c3 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -1,13 +1,13 @@ use std::collections::{HashMap, HashSet}; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, ObjectMap, + BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, ObjectMap, ObjectMapOpEnvMemoryCache, ObjectTypeCode, RawConvertTo, RawDecode, }; use cyfs_core::{ - GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, ToGroupShell, - HotstuffBlockQC, HotstuffTimeout, + GroupConsensusBlock, GroupConsensusBlockObject, GroupQuorumCertificate, HotstuffBlockQC, + HotstuffTimeout, }; use cyfs_group_lib::GroupRPathStatus; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; @@ -36,13 +36,11 @@ pub enum BlockLinkState { } pub struct GroupStorage { - group: Group, group_id: ObjectId, dec_id: ObjectId, rpath: String, local_device_id: ObjectId, non_driver: NONDriverHelper, - group_shell_id: ObjectId, cache: StorageCacheInfo, @@ -59,10 +57,6 @@ impl GroupStorage { local_device_id: ObjectId, root_state_mgr: &GlobalStateManagerRawProcessorRef, ) -> BuckyResult { - let group = non_driver.get_group(group_id, None, None).await?; - let group_shell = group.to_shell(); - let group_shell_id = group_shell.shell_id(); - let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) .await? @@ -72,12 +66,10 @@ impl GroupStorage { let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { - group, group_id: group_id.clone(), dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_shell_id, storage_engine: StorageEngineGroupState::new( dec_group_state, GroupStatePath::new(rpath.to_string()), @@ -101,16 +93,6 @@ impl GroupStorage { // 用hash加载chunk // 从chunk解析group - let group = non_driver - .get_group(group_id, None, None) - .await - .map_err(|err| { - log::warn!("get group {} from noc failed {:?}", group_id, err); - err - })?; - let group_shell = group.to_shell(); - let group_shell_id = group_shell.shell_id(); - let group_state = root_state_mgr .load_root_state(group_id, Some(group_id.clone()), true) .await @@ -134,12 +116,10 @@ impl GroupStorage { let object_map_processor = GroupObjectMapProcessorGroupState::new(&dec_group_state); Ok(Self { - group, group_id: group_id.clone(), dec_id: dec_id.clone(), rpath: rpath.to_string(), non_driver, - group_shell_id, storage_engine: StorageEngineGroupState::new( dec_group_state, state_path, @@ -176,14 +156,6 @@ impl GroupStorage { &self.cache.pre_commits } - pub fn group(&self) -> &Group { - &self.group - } - - pub fn group_shell_id(&self) -> &ObjectId { - &self.group_shell_id - } - pub fn dec_state_id(&self) -> &Option { &self.cache.dec_state_id } diff --git a/src/component/cyfs-group/src/storage/mod.rs b/src/component/cyfs-group/src/storage/mod.rs index d4440419e..f64a9311d 100644 --- a/src/component/cyfs-group/src/storage/mod.rs +++ b/src/component/cyfs-group/src/storage/mod.rs @@ -1,7 +1,9 @@ mod dec_storage; mod engine; +mod group_shell_mgr; mod group_storage; pub use dec_storage::*; use engine::*; +pub use group_shell_mgr::*; pub use group_storage::*; diff --git a/src/component/cyfs-stack/src/forward/forward.rs b/src/component/cyfs-stack/src/forward/forward.rs index 2208defbe..dab4a0613 100644 --- a/src/component/cyfs-stack/src/forward/forward.rs +++ b/src/component/cyfs-stack/src/forward/forward.rs @@ -1,8 +1,8 @@ use crate::resolver::DeviceCache; use cyfs_base::*; +use cyfs_bdt::StackGuard; use cyfs_debug::Mutex; use cyfs_lib::*; -use cyfs_bdt::StackGuard; use futures::future::{AbortHandle, Abortable}; use std::sync::Arc; @@ -163,6 +163,11 @@ impl ForwardRequestorContainer { } fn cacl_next_timeout_on_error(&self, error_count: u32) -> u64 { + log::debug!( + "cacl_next_timeout_on_error: min-interval {}, count {}.", + self.error_cache_min_interval, + error_count + ); let mut ret = self.error_cache_min_interval.pow(error_count + 1); if ret > self.error_cache_max_interval { ret = self.error_cache_max_interval; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index b224d06f1..191f77775 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -40,17 +40,29 @@ use crate::{ * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-8.sec -t=test-group/members/people-8.desc -dba * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s=test-group/members/people-9.sec -t=test-group/members/people-9.desc -dba * - * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-5 -d=test-group/members/people-5.desc 1 0 - * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-6 -d=test-group/members/people-6.desc 1 0 - * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-7 -d=test-group/members/people-7.desc 1 0 - * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-8 -d=test-group/members/people-8.desc 1 0 - * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-9 -d=test-group/members/people-9.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-5 -d=test-group/admins/people-5.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-6 -d=test-group/admins/people-6.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-7 -d=test-group/admins/people-7.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-8 -d=test-group/admins/people-8.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-10 -d=test-group/members/people-10.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-11 -d=test-group/members/people-11.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-12 -d=test-group/members/people-12.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-13 -d=test-group/members/people-13.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-14 -d=test-group/members/people-14.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-15 -d=test-group/members/people-15.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-16 -d=test-group/members/people-16.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-17 -d=test-group/members/people-17.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-18 -d=test-group/members/people-18.desc 1 0 * * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-1.desc -d=67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc 1 0 * * .\desc-tool show -a 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc * - * .\desc-tool modify 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc --prev_blob= -v=1 + * .\desc-tool modify 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc --add_admin=5r4MYfFBsQqy4r2LTccK1yyipRTtAjqvhX3GLU2qX3Lo --add_member=5r4MYfFapPzrXhfxWJNZJf4pk5Ncfrx5ax2yumWKZrZj + * .\desc-tool modify 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc --add_ood=5aSixgNLsF6r3qjDKP3XkBwnDRSr5G5hrGRM2v2LnLoA + * .\desc-tool modify 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc --prev_shell=9cfBkPt2RPa3MofMmsAXpq8xHYn8A2xvVPuQiBT4XTp9 -v=3 + * .\desc-tool sign 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc -s= + * */ mod Common { @@ -374,12 +386,12 @@ mod Common { pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { let min_port = 30217_u16; - init_member_from_dir("./test-group/admins", "admin", 4, min_port).await + init_member_from_dir("./test-group/admins", "admin", 8, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { let min_port = 31217_u16; - init_member_from_dir("./test-group/members", "member", 9, min_port).await + init_member_from_dir("./test-group/members", "member", 18, min_port).await } pub async fn init_group( From 9af8958308e7f13a53ceebd08433727e2ce5c5ee Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Wed, 19 Apr 2023 16:36:09 +0800 Subject: [PATCH 542/553] Add group_shell_id field in Timeout --- .../cyfs-core/protos/core_objects.proto | 1 + .../src/group/group_consensus_block.rs | 9 +- .../src/group/group_quorum_certificate.rs | 1 + .../protos/group_bft_protocol.proto | 1 + .../cyfs-group-lib/src/objects/certificate.rs | 21 +- .../src/consensus/hotstuff/hotstuff.rs | 280 +++++++++++------- .../consensus/synchronizer/synchronizer.rs | 8 + .../src/consensus/vote/committee.rs | 122 +++----- .../cyfs-group/src/consensus/vote/vote_mgr.rs | 128 +------- .../cyfs-group/src/dec/group_manager.rs | 7 +- .../src/dec_state/dec_state_synchronizer.rs | 8 +- .../cyfs-group/src/storage/group_shell_mgr.rs | 6 +- .../cyfs-group/src/storage/group_storage.rs | 12 +- src/tests/group-example/src/main.rs | 23 +- 14 files changed, 315 insertions(+), 312 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 881d20a99..058003d79 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -401,6 +401,7 @@ message HotstuffTimeout { } repeated VoteSignature votes = 2; + optional bytes group_shell_id = 3; // None if it's same as the block } message GroupConsensusBlockDescContent { diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index dc1834687..3f5aedd42 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -139,6 +139,7 @@ impl ProtobufTransform<&HotstuffTimeoutSign> pub struct HotstuffTimeout { pub round: u64, pub votes: Vec, + pub group_shell_id: Option, } #[derive(Clone, ProtobufTransformType)] @@ -274,9 +275,15 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { round: u64, group_shell_id: ObjectId, qc: Option, - tc: Option, + mut tc: Option, owner: ObjectId, ) -> Self { + if let Some(tc) = tc.as_mut() { + if tc.group_shell_id.as_ref() == Some(&group_shell_id) { + tc.group_shell_id = None; + } + } + let body = GroupConsensusBlockBodyContent { proposals, qc, tc }; let desc = GroupConsensusBlockDescContent { diff --git a/src/component/cyfs-core/src/group/group_quorum_certificate.rs b/src/component/cyfs-core/src/group/group_quorum_certificate.rs index 7c3ad77fc..df65c6c45 100644 --- a/src/component/cyfs-core/src/group/group_quorum_certificate.rs +++ b/src/component/cyfs-core/src/group/group_quorum_certificate.rs @@ -112,6 +112,7 @@ impl From for GroupQuorumCertificate { impl From for GroupQuorumCertificate { fn from(tc: HotstuffTimeout) -> Self { + assert!(tc.group_shell_id.is_some()); let desc = GroupQuorumCertificateDescContent::TC(tc); GroupQuorumCertificateBuilder::new(desc, EmptyBodyContent).build() } diff --git a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto index 427e17681..d04576c0b 100644 --- a/src/component/cyfs-group-lib/protos/group_bft_protocol.proto +++ b/src/component/cyfs-group-lib/protos/group_bft_protocol.proto @@ -14,6 +14,7 @@ message HotstuffTimeoutVote { uint64 round = 2; bytes voter = 3; bytes signature = 4; + bytes group_shell_id = 5; } message GroupRPathStatus { diff --git a/src/component/cyfs-group-lib/src/objects/certificate.rs b/src/component/cyfs-group-lib/src/objects/certificate.rs index 32b1b53c8..8614d1c8a 100644 --- a/src/component/cyfs-group-lib/src/objects/certificate.rs +++ b/src/component/cyfs-group-lib/src/objects/certificate.rs @@ -118,10 +118,12 @@ pub struct HotstuffTimeoutVote { pub round: u64, pub voter: ObjectId, pub signature: Signature, + pub group_shell_id: ObjectId, } impl HotstuffTimeoutVote { pub async fn new( + group_shell_id: ObjectId, high_qc: Option, round: u64, local_device_id: ObjectId, @@ -129,7 +131,12 @@ impl HotstuffTimeoutVote { ) -> BuckyResult { let signature = signer .sign( - Self::hash_content(high_qc.as_ref().map_or(0, |qc| qc.round), round).as_slice(), + Self::hash_content( + high_qc.as_ref().map_or(0, |qc| qc.round), + round, + &group_shell_id, + ) + .as_slice(), &SignatureSource::Object(ObjectLink { obj_id: local_device_id, obj_owner: None, @@ -142,17 +149,23 @@ impl HotstuffTimeoutVote { round, voter: local_device_id, signature, + group_shell_id, }) } pub fn hash(&self) -> HashValue { - Self::hash_content(self.high_qc.as_ref().map_or(0, |qc| qc.round), self.round) + Self::hash_content( + self.high_qc.as_ref().map_or(0, |qc| qc.round), + self.round, + &self.group_shell_id, + ) } - pub fn hash_content(high_qc_round: u64, round: u64) -> HashValue { + pub fn hash_content(high_qc_round: u64, round: u64, group_shell_id: &ObjectId) -> HashValue { let mut sha256 = sha2::Sha256::new(); sha256.input(high_qc_round.to_le_bytes()); sha256.input(round.to_le_bytes()); + sha256.input(group_shell_id.as_slice()); sha256.result().into() } } @@ -169,6 +182,7 @@ impl ProtobufTransform for HotstuffTi signature: Signature::raw_decode(value.signature.as_slice())?.0, round: value.round, high_qc, + group_shell_id: ObjectId::raw_decode(value.group_shell_id.as_slice())?.0, }) } } @@ -183,6 +197,7 @@ impl ProtobufTransform<&HotstuffTimeoutVote> for super::codec::protos::HotstuffT round: value.round, voter: value.voter.to_vec()?, signature: value.signature.to_vec()?, + group_shell_id: value.group_shell_id.to_vec()?, }; Ok(ret) diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e12e04da7..2b395dc5d 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -33,7 +33,7 @@ use crate::{ /** * TODO: generate empty block when the 'Node' is synchronizing * - * synchronizing: max_quorum_round - round > THRESHOLD + * How to distinguish synchronizing: max_quorum_round - round > THRESHOLD */ pub(crate) struct Hotstuff { @@ -72,7 +72,7 @@ impl Hotstuff { network_sender.clone(), rpath.clone(), non_driver.clone(), - shell_mgr, + shell_mgr.clone(), ); let mut runner = HotstuffRunner::new( @@ -83,6 +83,7 @@ impl Hotstuff { signer, network_sender, non_driver, + shell_mgr, tx_message.clone(), rx_message, proposal_consumer, @@ -218,6 +219,10 @@ impl Hotstuff { } } +enum HotstuffMessageInner { + Block(GroupConsensusBlock), +} + struct HotstuffRunner { local_id: ObjectId, local_device_id: ObjectId, @@ -233,8 +238,11 @@ struct HotstuffRunner { vote_mgr: VoteMgr, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, + tx_message_inner: Sender<(HotstuffMessageInner, ObjectId)>, + rx_message_inner: Receiver<(HotstuffMessageInner, ObjectId)>, tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, @@ -262,6 +270,7 @@ impl HotstuffRunner { signer: Arc, network_sender: crate::network::Sender, non_driver: crate::network::NONDriverHelper, + shell_mgr: GroupShellManager, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, proposal_consumer: PendingProposalConsumer, @@ -310,6 +319,7 @@ impl HotstuffRunner { }; let synchronizer = Synchronizer::new( + local_device_id, network_sender.clone(), rpath.clone(), max_height, @@ -318,6 +328,7 @@ impl HotstuffRunner { ); let (tx_block_gen, rx_block_gen) = async_std::channel::bounded(1); + let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); Self { local_id, @@ -345,6 +356,9 @@ impl HotstuffRunner { tx_block_gen, rx_block_gen, proposal_result_notifier, + tx_message_inner, + rx_message_inner, + shell_mgr, } } @@ -359,7 +373,10 @@ impl HotstuffRunner { block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), block.owner(), remote); - let latest_group = self.committee.get_group(None).await?; + let latest_group = self + .shell_mgr + .get_group(self.rpath.group_id(), None, Some(&remote)) + .await?; if !latest_group.contain_ood(&remote) { log::warn!( "[hotstuff] local: {:?}, receive block({}) from unknown({})", @@ -678,17 +695,31 @@ impl HotstuffRunner { ); // 乱序,同步 - if block.height() <= self.store.header_height() + 3 { + let fetch_height_immediate = self.store.header_height() + 3; + if block.height() <= fetch_height_immediate { self.fetch_block(block.prev_block_id().unwrap(), remote) .await; } - let max_round_block = self.store.block_with_max_round(); - self.synchronizer.push_outorder_block( - block.clone(), - max_round_block.map_or(1, |block| block.height() + 1), - remote, - ); + // let max_round_block = self.store.block_with_max_round(); + // let max_height = max_round_block.map_or(1, |block| block.height() + 1); + + if block.height() > fetch_height_immediate { + log::debug!( + "[hotstuff] local: {:?}, will sync blocks from height({}) to height({}). block.round={}, remote: {}", + self, + fetch_height_immediate, + block.height(), + block.round(), + remote + ); + + self.synchronizer.push_outorder_block( + block.clone(), + fetch_height_immediate, + remote, + ); + } Err(Ok(())) } @@ -764,17 +795,6 @@ impl HotstuffRunner { ); return self.process_block_qc(qc, block).await; } - VoteThresholded::TC(tc, max_high_qc_block) => { - log::debug!( - "[hotstuff] local: {:?}, the timeout-qc of block {:?} has received before", - self, - block.block_id() - ); - - return self - .process_timeout_qc(tc, max_high_qc_block.as_ref()) - .await; - } VoteThresholded::None => {} } @@ -977,25 +997,17 @@ impl HotstuffRunner { return; } - match self.committee.get_group(None).await { - Ok(group) => { - log::info!( - "[hotstuff] local: {:?}, update round from {} to {}", - self, - self.round, - round + 1 - ); + log::info!( + "[hotstuff] local: {:?}, update round from {} to {}", + self, + self.round, + round + 1 + ); - self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); - self.round = round + 1; - self.vote_mgr.cleanup(self.round); - self.tc = None; - } - Err(err) => { - log::warn!("[hotstuff] local: {:?}, get group before update round from {} to {} failed {:?}", - self, self.round, round + 1, err); - } - } + self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); + self.round = round + 1; + self.vote_mgr.cleanup(self.round); + self.tc = None; } fn update_high_qc(&mut self, qc: &Option) { @@ -1516,6 +1528,18 @@ impl HotstuffRunner { return Ok(()); } + match self.check_group_is_latest(&timeout.group_shell_id).await { + Ok(is) if is => {} + _ => { + log::warn!( + "[hotstuff] local: {:?}, handle_timeout: {:?}, ignore for is not latest group.", + self, + timeout.round, + ); + return Ok(()); + } + } + let block = match timeout.high_qc.as_ref() { Some(qc) => match self.store.find_block_in_cache(&qc.block_id) { Ok(block) => Some(block), @@ -1528,7 +1552,6 @@ impl HotstuffRunner { err ); - self.vote_mgr.add_waiting_timeout(timeout.clone()); self.fetch_block(&qc.block_id, remote).await; return Ok(()); } @@ -1554,7 +1577,7 @@ impl HotstuffRunner { let tc = self .vote_mgr - .add_timeout(timeout.clone(), block.as_ref()) + .add_timeout(timeout.clone()) .await .map_err(|err| { log::warn!( @@ -1566,33 +1589,33 @@ impl HotstuffRunner { err })?; - if let Some((tc, max_high_qc_block)) = tc { - self.process_timeout_qc(tc, max_high_qc_block.as_ref()) - .await?; + if let Some(tc) = tc { + self.process_timeout_qc(tc).await?; } Ok(()) } - async fn process_timeout_qc( - &mut self, - tc: HotstuffTimeout, - max_high_qc_block: Option<&GroupConsensusBlock>, - ) -> BuckyResult<()> { + async fn process_timeout_qc(&mut self, tc: HotstuffTimeout) -> BuckyResult<()> { log::debug!( - "[hotstuff] local: {:?}, process_timeout_qc: {:?}, voter: {:?}, high-qc block: {:?},", + "[hotstuff] local: {:?}, process_timeout_qc: {:?}, voter: {:?}.", self, tc.round, tc.votes .iter() .map(|vote| format!("{:?}/{:?}", vote.high_qc_round, vote.voter,)) .collect::>(), - max_high_qc_block.as_ref().map(|qc| qc.prev_block_id()) ); let quorum_round = tc.round; self.update_max_quorum_round(quorum_round); - self.store.save_tc(&tc).await?; + self.store + .save_tc( + &tc, + tc.group_shell_id + .expect("group-shell-id should not be None."), + ) + .await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1617,15 +1640,7 @@ impl HotstuffRunner { self.generate_block(Some(tc)).await; Ok(()) } else { - let latest_group = self.committee.get_group(None).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, process_timeout_qc: {:?}, get group failed {:?}", - self, - tc.round, - err - ); - err - })?; + let (latest_group, latest_shell_id) = self.shell_mgr.group(); self.broadcast(HotstuffMessage::Timeout(tc), &latest_group) } @@ -1674,37 +1689,42 @@ impl HotstuffRunner { return Ok(()); } - let block = if max_high_qc.high_qc_round == 0 { - None - } else { - let block = match self + let group_shell_id = match tc.group_shell_id.as_ref() { + Some(group_shell_id) => group_shell_id.clone(), + None => { + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} ignore for group-shell-id is None.", + self, + tc.round + ); + return Ok(()); + } + }; + + if max_high_qc.high_qc_round > 0 { + if let Err(err) = self .store .find_block_in_cache_by_round(max_high_qc.high_qc_round) { - Ok(block) => block, - Err(err) => { - log::warn!( - "[hotstuff] local: {:?}, handle_tc: {:?} find prev-block by round {} failed {:?}", - self, - tc.round, max_high_qc.high_qc_round, - err - ); + log::warn!( + "[hotstuff] local: {:?}, handle_tc: {:?} find prev-block by round {} failed {:?}", + self, + tc.round, max_high_qc.high_qc_round, + err + ); - // 同步前序block - let max_round_block = self.store.block_with_max_round(); - self.synchronizer.sync_with_round( - max_round_block.map_or(1, |block| block.height() + 1), - max_high_qc.high_qc_round, - remote, - ); - return Ok(()); - } + // 同步前序block + let max_round_block = self.store.block_with_max_round(); + self.synchronizer.sync_with_round( + max_round_block.map_or(1, |block| block.height() + 1), + max_high_qc.high_qc_round, + remote, + ); }; - Some(block) - }; + } self.committee - .verify_tc(tc, block.as_ref()) + .verify_tc(tc, &group_shell_id) .await .map_err(|err| { log::warn!( @@ -1721,7 +1741,7 @@ impl HotstuffRunner { let quorum_round = tc.round; self.update_max_quorum_round(quorum_round); - self.store.save_tc(&tc).await?; + self.store.save_tc(&tc, group_shell_id).await?; self.advance_round(tc.round).await; self.tc = Some(tc.clone()); @@ -1749,7 +1769,11 @@ impl HotstuffRunner { async fn local_timeout_round(&mut self) -> BuckyResult<()> { log::debug!("[hotstuff] local: {:?}, local_timeout_round", self,); - let latest_group = match self.committee.get_group(None).await { + let latest_group = match self + .shell_mgr + .get_group(self.rpath.group_id(), None, None) + .await + { Ok(group) => { self.timer.reset(GROUP_DEFAULT_CONSENSUS_INTERVAL); group @@ -1766,7 +1790,10 @@ impl HotstuffRunner { } }; + let latest_group_shell = latest_group.to_shell(); + let latest_group_shell_id = latest_group_shell.shell_id(); let timeout = HotstuffTimeoutVote::new( + latest_group_shell_id, self.high_qc.clone(), self.round, self.local_device_id, @@ -1838,15 +1865,19 @@ impl HotstuffRunner { } None => None, }; - let latest_group = self.committee.get_group(None).await.map_err(|err| { - log::warn!( - "[hotstuff] local: {:?}, generate_block get latest group failed {:?}", - self, - err - ); + let latest_group = self + .shell_mgr + .get_group(self.rpath.group_id(), None, None) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, generate_block get latest group failed {:?}", + self, + err + ); - err - })?; + err + })?; let mut remove_proposals = vec![]; // let mut dup_proposals = vec![]; @@ -2236,10 +2267,23 @@ impl HotstuffRunner { } async fn fetch_block(&mut self, block_id: &ObjectId, remote: ObjectId) -> BuckyResult<()> { - let block = self.non_driver.get_block(block_id, Some(&remote)).await?; + let block = self + .non_driver + .get_block(block_id, Some(&remote)) + .await + .map_err(|err| { + log::error!( + "[hotstuff] local: {:?}, fetch block({}) from {} failed, err: {:?}.", + self, + block_id, + remote, + err + ); + err + })?; - self.tx_message - .send((HotstuffMessage::Block(block), remote)) + self.tx_message_inner + .send((HotstuffMessageInner::Block(block), remote)) .await; Ok(()) } @@ -2258,10 +2302,18 @@ impl HotstuffRunner { } async fn check_group_is_latest(&self, group_shell_id: &ObjectId) -> BuckyResult { - let latest_group = self.committee.get_group(None).await?; - let group_shell = latest_group.to_shell(); - let latest_shell_id = group_shell.shell_id(); - Ok(&latest_shell_id == group_shell_id) + let (_, latest_shell_id) = self.shell_mgr.group(); + if &latest_shell_id == group_shell_id { + Ok(true) + } else { + let latest_group = self + .shell_mgr + .get_group(self.rpath.group_id(), None, None) + .await?; + let group_shell = latest_group.to_shell(); + let latest_shell_id = group_shell.shell_id(); + Ok(&latest_shell_id == group_shell_id) + } } async fn make_sure_result_state( @@ -2381,9 +2433,16 @@ impl HotstuffRunner { // Also, schedule a timer in case we don't hear from the leader. let max_round_block = self.store.block_with_max_round(); let group_shell_id = max_round_block.as_ref().map(|block| block.group_shell_id()); - let last_group = self.committee.get_group(group_shell_id).await; + let last_group = self + .shell_mgr + .get_group(self.rpath.group_id(), group_shell_id, None) + .await; let latest_group = match group_shell_id.as_ref() { - Some(_) => self.committee.get_group(None).await, + Some(_) => { + self.shell_mgr + .get_group(self.rpath.group_id(), None, None) + .await + } None => last_group.clone(), }; @@ -2460,6 +2519,19 @@ impl HotstuffRunner { Ok(()) }, }, + message = self.rx_message_inner.recv().fuse() => match message { + Ok((HotstuffMessageInner::Block(block), remote)) => { + if remote == self.local_device_id { + self.process_block(&block, remote, &HashMap::new()).await + } else { + self.handle_block(&block, remote).await + } + }, + Err(e) => { + log::warn!("[hotstuff] rx_message_inner closed."); + Ok(()) + }, + }, block = self.rx_block_gen.recv().fuse() => match block { Ok((block, proposals)) => self.process_block(&block, self.local_device_id, &proposals).await, Err(e) => { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 1052d4268..a4f381f2c 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -29,6 +29,7 @@ pub(crate) struct Synchronizer { impl Synchronizer { pub fn new( + local_device_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, height: u64, @@ -37,6 +38,7 @@ impl Synchronizer { ) -> Self { let (tx_sync_message, rx_sync_message) = async_std::channel::bounded(CHANNEL_CAPACITY); let mut runner = SynchronizerRunner::new( + local_device_id, network_sender.clone(), rpath.clone(), tx_block, @@ -315,6 +317,7 @@ impl RequestSendInfo { } struct SynchronizerRunner { + local_device_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, tx_block: Sender<(HotstuffMessage, ObjectId)>, @@ -329,6 +332,7 @@ struct SynchronizerRunner { impl SynchronizerRunner { fn new( + local_device_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, tx_block: Sender<(HotstuffMessage, ObjectId)>, @@ -346,6 +350,7 @@ impl SynchronizerRunner { sync_requests: vec![], out_order_blocks: vec![], tx_block, + local_device_id, } } @@ -513,6 +518,9 @@ impl SynchronizerRunner { block: GroupConsensusBlock, remote: ObjectId, ) { + log::debug!("[synchronizer] local: {:?}, handle_push_block want sync blocks from height({}) to height({}). block.round={}, round={}, prev={:?}", + self.local_device_id, min_height, block.height(), self.round, block.round(), block.prev_block_id()); + if block.round() <= self.round || min_height <= block.height() || block.prev_block_id().is_none() diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index d0a59bb3e..5f96f6158 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -23,7 +23,6 @@ pub(crate) struct Committee { non_driver: NONDriverHelper, shell_mgr: GroupShellManager, local_device_id: ObjectId, - group_cache: Arc>>, // (group_shell_id, group) } impl Committee { @@ -37,21 +36,19 @@ impl Committee { group_id, non_driver, shell_mgr, - group_cache: Arc::new(RwLock::new(HashMap::new())), local_device_id, } } - pub async fn get_group(&self, group_shell_id: Option<&ObjectId>) -> BuckyResult { - self.check_group(group_shell_id, None).await - } - pub async fn quorum_threshold( &self, voters: &HashSet, group_shell_id: Option<&ObjectId>, ) -> BuckyResult { - let group = self.check_group(group_shell_id, None).await?; + let group = self + .shell_mgr + .get_group(&self.group_id, group_shell_id, None) + .await?; let voters: Vec<&ObjectId> = voters .iter() .filter(|id| { @@ -72,7 +69,13 @@ impl Committee { group_shell_id: Option<&ObjectId>, round: u64, ) -> BuckyResult { - let group = self.check_group(group_shell_id, None).await?; + let group = if group_shell_id.is_none() { + self.shell_mgr.group().0 + } else { + self.shell_mgr + .get_group(&self.group_id, group_shell_id, None) + .await? + }; let i = (round % (group.ood_list().len() as u64)) as usize; Ok(group.ood_list()[i].object_id().clone()) } @@ -85,21 +88,23 @@ impl Committee { /* * * 验证block下的签名是否符合对上一个block归属group的确认 */ + let block_id = block.block_id(); if !block.check() { log::warn!( "[group committee] error block with invalid content: {}", - block.named_object().desc().calculate_id() + block_id ) } log::debug!( "[group committee] {} verify block {} step1", self.local_device_id, - block.block_id() + block_id ); let group = self - .check_group(Some(block.group_shell_id()), Some(&from)) + .shell_mgr + .get_group(&self.group_id, Some(block.group_shell_id()), Some(&from)) .await?; if !self.check_block_sign(&block, &group).await? { @@ -116,11 +121,23 @@ impl Committee { log::debug!( "[group committee] {} verify block {} step2", self.local_device_id, - block.block_id() + block_id ); let prev_block = if let Some(qc) = block.qc() { - let prev_block = self.non_driver.get_block(&qc.block_id, None).await?; + let prev_block = self + .non_driver + .get_block(&qc.block_id, Some(&from)) + .await + .map_err(|err| { + log::error!( + "get the prev-block({}) for verify block({}) failed: {:?}", + qc.block_id, + block_id, + err + ); + err + })?; self.verify_qc(qc, &prev_block).await?; Some(prev_block) } else { @@ -130,17 +147,17 @@ impl Committee { log::debug!( "[group committee] {} verify block {} step3", self.local_device_id, - block.block_id() + block_id ); if let Some(tc) = block.tc() { - self.verify_tc(tc, prev_block.as_ref()).await?; + self.verify_tc(tc, block.group_shell_id()).await?; } log::debug!( "[group committee] {} verify block {} step4", self.local_device_id, - block.block_id() + block_id ); Ok(()) @@ -167,7 +184,12 @@ impl Committee { )); } - self.check_group(Some(block_desc.content().group_shell_id()), Some(&from)) + self.shell_mgr + .get_group( + &self.group_id, + Some(block_desc.content().group_shell_id()), + Some(&from), + ) .await?; log::debug!( @@ -237,27 +259,14 @@ impl Committee { pub async fn verify_tc( &self, tc: &HotstuffTimeout, - prev_block: Option<&GroupConsensusBlock>, + group_shell_id: &ObjectId, ) -> BuckyResult<()> { - let highest_round = tc - .votes - .iter() - .map(|v| v.high_qc_round) - .max() - .map_or(0, |round| round); - let prev_round = prev_block.map_or(0, |b| b.round()); - if highest_round != prev_round { - log::warn!("[group committee] hightest round is not match with prev-block in tc, highest_round: {:?}, prev_round: {:?}", highest_round, prev_round); - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - "round not match in tc", - )); - } + let tc_group_shell_id = tc.group_shell_id.as_ref().unwrap_or(group_shell_id); let is_enough = self .quorum_threshold( &tc.votes.iter().map(|v| v.voter).collect(), - prev_block.map(|b| b.group_shell_id()), + Some(tc_group_shell_id), ) .await?; @@ -270,7 +279,8 @@ impl Committee { } let verify_vote_results = futures::future::join_all(tc.votes.iter().map(|vote| async { - let hash = HotstuffTimeoutVote::hash_content(vote.high_qc_round, tc.round); + let hash = + HotstuffTimeoutVote::hash_content(vote.high_qc_round, tc.round, tc_group_shell_id); match self.non_driver.get_device(&vote.voter).await { Ok(device) => { let verifier = RsaCPUObjectVerifier::new(device.desc().public_key().clone()); @@ -351,50 +361,6 @@ impl Committee { .map_or(Ok(()), |e| e) } - pub async fn check_group( - &self, - shell_id: Option<&ObjectId>, - from: Option<&ObjectId>, - ) -> BuckyResult { - { - // read - let cache = self.group_cache.read().await; - if let Some(shell_id) = shell_id { - if let Some(group) = cache.get(shell_id) { - return Ok(group.clone()); - } - } - } - - let group = self - .shell_mgr - .get_group(&self.group_id, shell_id, from) - .await?; - - let group_shell = group.to_shell(); - let calc_id = group_shell.shell_id(); - if let Some(id) = shell_id { - assert_eq!(&calc_id, id); - } - - { - // write - let mut cache = self.group_cache.write().await; - match cache.entry(calc_id) { - std::collections::hash_map::Entry::Occupied(mut entry) => { - if entry.get().version() < group.version() { - entry.insert(group.clone()); - } - } - std::collections::hash_map::Entry::Vacant(entry) => { - entry.insert(group.clone()); - } - } - } - - Ok(group) - } - async fn check_block_sign( &self, block: &GroupConsensusBlock, diff --git a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs index 6a5852b61..35f1b1fb0 100644 --- a/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs +++ b/src/component/cyfs-group/src/consensus/vote/vote_mgr.rs @@ -14,13 +14,11 @@ pub(crate) struct VoteMgr { round: u64, blocks: HashMap, votes: HashMap>>, // > - timeouts: HashMap>, // - waiting_timeouts: HashMap>>, // >> + timeouts: HashMap>>, // > } pub(crate) enum VoteThresholded { QC(HotstuffBlockQC), - TC(HotstuffTimeout, Option), None, } @@ -34,7 +32,6 @@ impl VoteMgr { timeouts: HashMap::new(), round, blocks: HashMap::new(), - waiting_timeouts: HashMap::new(), } } @@ -58,56 +55,6 @@ impl VoteMgr { } } - let mut timeouts: Vec<(&u64, &mut Box)> = self - .timeouts - .iter_mut() - .filter(|(round, tc_maker)| { - **round >= block.round() - && tc_maker - .max_block() - .as_ref() - .map_or(false, |max_block_id| block_id == max_block_id) - }) - .collect(); - - timeouts.sort_unstable_by(|l, r| r.0.cmp(l.0)); - - for (round, tc_maker) in timeouts { - if let Some(tc) = tc_maker - .on_block(Some(block), &self.committee) - .await - .unwrap_or(None) - { - return VoteThresholded::TC(tc, Some(block.clone())); - } - } - - let waiting_timeouts = self.waiting_timeouts.remove(block_id); - if let Some(waiting_timeouts) = waiting_timeouts { - let mut waiting_timeouts: Vec<(u64, HashMap)> = - waiting_timeouts.into_iter().collect(); - waiting_timeouts.sort_unstable_by(|l, r| r.0.cmp(&l.0)); - - for (_, timeouts) in waiting_timeouts { - for (_, timeout) in timeouts { - if self - .committee - .verify_timeout(&timeout, Some(block)) - .await - .is_ok() - { - if let Some((tc, block)) = self - .add_timeout(timeout, Some(block)) - .await - .map_or(None, |r| r) - { - return VoteThresholded::TC(tc, block); - } - } - } - } - } - VoteThresholded::None } @@ -141,60 +88,24 @@ impl VoteMgr { pub(crate) async fn add_timeout( &mut self, timeout: HotstuffTimeoutVote, - block: Option<&GroupConsensusBlock>, - ) -> BuckyResult)>> { - assert!( - block.map(|block| block.block_id().object_id().clone()) - == timeout.high_qc.as_ref().map(|qc| qc.block_id) - ); - + ) -> BuckyResult> { // Add the new timeout to our aggregator and see if we have a TC. let tc_maker = self .timeouts .entry(timeout.round) - .or_insert_with(|| Box::new(TCMaker::new(timeout.round))); - - if let Some(qc) = timeout.high_qc.as_ref() { - self.blocks - .insert(qc.block_id, block.clone().unwrap().clone()); - } - - let max_block = tc_maker - .max_block() - .or(timeout.high_qc.as_ref().map(|qc| qc.block_id)) - .as_ref() - .map(|max_block_id| self.blocks.get(max_block_id).unwrap()); + .or_insert_with(|| HashMap::new()) + .entry(timeout.group_shell_id.clone()) + .or_insert_with(|| { + Box::new(TCMaker::new(timeout.round, timeout.group_shell_id.clone())) + }); - tc_maker - .append(timeout, &self.committee, max_block) - .await - .map(|vote| vote.map(|v| (v, max_block.cloned()))) - } - - pub(crate) fn add_waiting_timeout(&mut self, timeout: HotstuffTimeoutVote) { - let block_id = timeout - .high_qc - .as_ref() - .expect("pre-block is empty") - .block_id; - - self.waiting_timeouts - .entry(block_id) - .or_insert_with(HashMap::new) - .entry(timeout.round) - .or_insert_with(HashMap::new) - .entry(timeout.voter) - .or_insert(timeout); + tc_maker.append(timeout, &self.committee).await } pub fn cleanup(&mut self, round: u64) { self.votes.retain(|k, _| k >= &round); self.timeouts.retain(|k, _| k >= &round); self.blocks.retain(|_, block| block.round() >= round); - self.waiting_timeouts.retain(|_, timeouts| { - timeouts.retain(|k, _| k >= &round); - !timeouts.is_empty() - }); self.round = round; } } @@ -270,17 +181,19 @@ impl QCMaker { struct TCMaker { round: u64, votes: Vec, + group_shell_id: ObjectId, used: HashSet, thresholded: bool, } impl TCMaker { - pub fn new(round: u64) -> Self { + pub fn new(round: u64, group_shell_id: ObjectId) -> Self { Self { round, votes: Vec::new(), used: HashSet::new(), thresholded: false, + group_shell_id, } } @@ -289,7 +202,6 @@ impl TCMaker { &mut self, timeout: HotstuffTimeoutVote, committee: &Committee, - block: Option<&GroupConsensusBlock>, ) -> BuckyResult> { let author = timeout.voter; @@ -303,19 +215,18 @@ impl TCMaker { // Add the timeout to the accumulator. self.votes.push(timeout); - self.on_block(block, committee).await + self.on_block(committee).await } pub async fn on_block( &mut self, - block: Option<&GroupConsensusBlock>, committee: &Committee, ) -> BuckyResult> { if !self.thresholded { self.thresholded = committee .quorum_threshold( &self.votes.iter().map(|v| v.voter).collect(), - block.map(|block| block.group_shell_id()), + Some(&self.group_shell_id), ) .await?; @@ -331,21 +242,10 @@ impl TCMaker { signature: v.signature.clone(), }) .collect(), + group_shell_id: Some(self.group_shell_id.clone()), })); } } Ok(None) } - - pub fn max_block(&self) -> Option { - self.votes - .iter() - .max_by(|l, r| { - l.high_qc - .as_ref() - .map_or(0, |qc| qc.round) - .cmp(&r.high_qc.as_ref().map_or(0, |qc| qc.round)) - }) - .map_or(None, |v| v.high_qc.as_ref().map(|qc| qc.block_id)) - } } diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index fc5a08986..5af50696e 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -414,6 +414,10 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); + let shell_mgr = self + .check_group_shell_mgr(group_id, non_driver.clone(), remote) + .await?; + let store = GroupStorage::load( group_id, dec_id, @@ -476,9 +480,6 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let shell_mgr = self - .check_group_shell_mgr(group_id, non_driver.clone(), remote) - .await?; let service = RPathService::load( local_id, local_device_id.object_id().clone(), diff --git a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs index f3f15ea8a..d4d30c3e1 100644 --- a/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs +++ b/src/component/cyfs-group/src/dec_state/dec_state_synchronizer.rs @@ -324,8 +324,12 @@ impl DecStateSynchronizerRunner { .is_ok() { let group = self - .committee - .check_group(Some(header_block.group_shell_id()), None) + .shell_mgr + .get_group( + self.rpath.group_id(), + Some(header_block.group_shell_id()), + None, + ) .await?; let group_shell_id = header_block.group_shell_id().clone(); diff --git a/src/component/cyfs-group/src/storage/group_shell_mgr.rs b/src/component/cyfs-group/src/storage/group_shell_mgr.rs index 72dc6fb9a..475c6732f 100644 --- a/src/component/cyfs-group/src/storage/group_shell_mgr.rs +++ b/src/component/cyfs-group/src/storage/group_shell_mgr.rs @@ -171,14 +171,16 @@ impl GroupShellManager { Ok(ret) } - pub fn group(&self) -> Group { + /// get latest group in cache without query. + /// let (latest_group, latest_shell_id) = self.group(); + pub fn group(&self) -> (Group, ObjectId) { async_std::task::block_on(async move { let cache = self.0.cache.read().await; let group = cache .groups_by_shell .get(&cache.latest_shell_id) .expect("lastest group must be exists."); - group.as_ref().clone() + (group.as_ref().clone(), cache.latest_shell_id.clone()) }) } diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index f272f95c3..53d65cb00 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -463,7 +463,11 @@ impl GroupStorage { &self.cache.last_tc } - pub async fn save_tc(&mut self, tc: &HotstuffTimeout) -> BuckyResult<()> { + pub async fn save_tc( + &mut self, + tc: &HotstuffTimeout, + group_shell_id: ObjectId, + ) -> BuckyResult<()> { let quorum_round = tc.round; if quorum_round < self.cache.last_vote_round || quorum_round <= self.cache.last_tc.as_ref().map_or(0, |tc| tc.round) @@ -471,7 +475,11 @@ impl GroupStorage { return Ok(()); } - let tc = GroupQuorumCertificate::from(tc.clone()); + let mut tc = tc.clone(); + if tc.group_shell_id.is_none() { + tc.group_shell_id = Some(group_shell_id); + } + let tc = GroupQuorumCertificate::from(tc); self.non_driver.put_qc(&tc).await?; let mut writer = self.storage_engine.create_writer().await?; diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 191f77775..7c774b129 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -80,7 +80,7 @@ mod Common { }; use cyfs_bdt_ext::{BdtStackParams, SNMode}; use cyfs_chunk_lib::ChunkMeta; - use cyfs_core::{DecApp, DecAppId}; + use cyfs_core::{DecApp, DecAppId, ToGroupShell}; use cyfs_lib::{BrowserSanboxMode, NONObjectInfo, SharedCyfsStack}; use cyfs_meta_lib::MetaMinerTarget; use cyfs_stack::{ @@ -386,12 +386,12 @@ mod Common { pub async fn init_admins() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { let min_port = 30217_u16; - init_member_from_dir("./test-group/admins", "admin", 8, min_port).await + init_member_from_dir("./test-group/admins", "admin", 5, min_port).await } pub async fn init_members() -> Vec<((People, PrivateKey), (Device, PrivateKey))> { let min_port = 31217_u16; - init_member_from_dir("./test-group/members", "member", 18, min_port).await + init_member_from_dir("./test-group/members", "member", 10, min_port).await } pub async fn init_group( @@ -532,6 +532,15 @@ mod Common { )))), )); + let group_shell = group.to_shell(); + let group_shell_vec = group_shell.to_vec().unwrap(); + let typeless = TypelessCoreObject::clone_from_slice(group_shell_vec.as_slice()).unwrap(); + known_objects.list.push(NONObjectInfo::new( + group_shell.shell_id(), + group_shell_vec, + Some(Arc::new(AnyNamedObject::Core(typeless))), + )); + let dec_app_vec = dec_app.to_vec().unwrap(); let typeless = TypelessCoreObject::clone_from_slice(dec_app_vec.as_slice()).unwrap(); known_objects.list.push(NONObjectInfo::new( @@ -1199,6 +1208,8 @@ async fn main_run() { ws_port += 1; } + log::info!("stacks for admins has opened."); + for ((member, _), (device, private_key)) in members.iter() { let (cyfs_stack, shared_stack) = create_stack( member, @@ -1223,6 +1234,8 @@ async fn main_run() { ws_port += 1; } + log::info!("stacks for members has opened."); + async_std::task::sleep(Duration::from_millis(10000)).await; for i in 0..admin_stacks.len() { @@ -1242,6 +1255,8 @@ async fn main_run() { admin_group_mgrs.push(group_mgr); } + log::info!("test dec-service for admins has opened."); + for i in 0..member_stacks.len() { let (_, shared_stack) = member_stacks.get(i).unwrap(); let ((member, _), _) = members.get(i).unwrap(); @@ -1255,6 +1270,8 @@ async fn main_run() { member_group_mgrs.push(group_mgr); } + log::info!("test dec-client for members has opened."); + // async_std::task::sleep(Duration::from_millis(10000)).await; let mut proposals: Vec = vec![]; From dadb6286b33765779ed220ee37b78c28e5fbaebc Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 20 Apr 2023 16:48:31 +0800 Subject: [PATCH 543/553] Update the `ObjectShell` as a standalone type --- .../cyfs-core/protos/core_objects.proto | 34 +- src/component/cyfs-core/src/coreobj.rs | 3 + .../cyfs-core/src/group/group_shell.rs | 6 +- .../cyfs-core/src/storage/object_shell.rs | 615 ++++++++++++------ .../cyfs-core/src/storage/storage.rs | 56 +- .../cyfs-group/src/storage/group_shell_mgr.rs | 61 +- 6 files changed, 520 insertions(+), 255 deletions(-) diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index 058003d79..fc292ef9f 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -7,8 +7,38 @@ message StorageDescContent { } message StorageBodyContent { - bytes value = 1; // match with the hash in `Desc` - optional bytes freedom_attachment = 2; // content without hash, you can update it with the same hash in `Desc`; + bytes value = 1; +} + +// ObjectShellObject +message ObjectShellDescContent { + // true: storage `ObjectId` in `desc` only, without `ObjectDesc`; + // false: encode the `ObjectDesc` in `desc`. + bool is_object_id_only = 1; + + // true: calculate the `fix_content_hash` include `desc_sign`; + // false: calculate the `fix_content_hash` without `desc_sign`. + bool is_desc_sign_fix = 2; + + // true: calculate the `fix_content_hash` include `body_sign`; + // false: calculate the `fix_content_hash` without `body_sign`. + bool is_body_sign_fix = 3; + + // true: calculate the `fix_content_hash` include `nonce`; + // false: calculate the `fix_content_hash` without `nonce`. + bool is_nonce_fix = 4; + + // hash of `fix_content` in `ObjectShellBodyContent` + bytes fix_content_hash = 5; +} + +message ObjectShellBodyContent { + bytes desc = 1; + optional bytes body = 2; + + optional bytes desc_signatures = 3; + optional bytes body_signatures = 4; + optional bytes nonce = 5; } // TextObject diff --git a/src/component/cyfs-core/src/coreobj.rs b/src/component/cyfs-core/src/coreobj.rs index 8eb96a930..a19e3a775 100644 --- a/src/component/cyfs-core/src/coreobj.rs +++ b/src/component/cyfs-core/src/coreobj.rs @@ -15,6 +15,9 @@ pub enum CoreObjectType { // 文本对象 Text = 41, + // A shell of an mutable `Object`, we can use it to storage `Object` with different `Body` and same `Desc` in `NOC`. + ObjectShell = 42, + // 通讯录 // FriendList = 130, FriendOption = 131, diff --git a/src/component/cyfs-core/src/group/group_shell.rs b/src/component/cyfs-core/src/group/group_shell.rs index 1e569d1a1..bd871f170 100644 --- a/src/component/cyfs-core/src/group/group_shell.rs +++ b/src/component/cyfs-core/src/group/group_shell.rs @@ -1,8 +1,8 @@ use cyfs_base::{Group, GroupType}; -use crate::{ObjectShell, OBJECT_SHELL_ALL_FREEDOM}; +use crate::{ObjectShell, OBJECT_SHELL_ALL_FREEDOM_WITH_FULL_DESC}; -pub type GroupShell = ObjectShell; +pub type GroupShell = ObjectShell; pub trait ToGroupShell: Sized { fn to_shell(&self) -> GroupShell; @@ -10,6 +10,6 @@ pub trait ToGroupShell: Sized { impl ToGroupShell for Group { fn to_shell(&self) -> GroupShell { - GroupShell::from_object(self.clone(), OBJECT_SHELL_ALL_FREEDOM) + GroupShell::from_object(self, OBJECT_SHELL_ALL_FREEDOM_WITH_FULL_DESC) } } diff --git a/src/component/cyfs-core/src/storage/object_shell.rs b/src/component/cyfs-core/src/storage/object_shell.rs index ffe2f3a98..d2f639b7b 100644 --- a/src/component/cyfs-core/src/storage/object_shell.rs +++ b/src/component/cyfs-core/src/storage/object_shell.rs @@ -1,263 +1,508 @@ -use std::marker::PhantomData; - use cyfs_base::{ - BodyContent, BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc, ObjectId, - ObjectType, RawDecode, RawEncode, Signature, + BodyContent, BuckyError, BuckyErrorCode, BuckyResult, DescContent, HashValue, NamedObjType, + NamedObject, NamedObjectBase, NamedObjectBaseBuilder, NamedObjectBodyContext, + NamedObjectBuilder, NamedObjectDesc, NamedObjectId, ObjectDesc, ObjectId, ObjectMutBody, + ObjectSigns, ObjectType, ProtobufDecode, ProtobufEncode, ProtobufTransform, RawConvertTo, + RawDecode, RawEncode, RawEncodePurpose, RawEncodeWithContext, Signature, SubDescNone, + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF, }; +use serde::Serialize; +use sha2::Digest; + +use crate::CoreObjectType; + +#[derive(Debug, Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)] +#[cyfs_protobuf_type(crate::codec::protos::ObjectShellDescContent)] +struct ObjectShellDescContent { + is_object_id_only: bool, + is_desc_sign_fix: bool, + is_body_sign_fix: bool, + is_nonce_fix: bool, + fix_content_hash: HashValue, +} + +impl DescContent for ObjectShellDescContent { + fn obj_type() -> u16 { + CoreObjectType::ObjectShell as u16 + } + + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } + + type OwnerType = SubDescNone; + type AreaType = SubDescNone; + type AuthorType = SubDescNone; + type PublicKeyType = SubDescNone; +} + +#[derive(Clone, Debug, ProtobufEncode, ProtobufDecode, ProtobufTransform)] +#[cyfs_protobuf_type(crate::codec::protos::ObjectShellBodyContent)] +struct ObjectShellBodyContent { + desc: Vec, + body: Option>, + desc_signatures: Option>, + body_signatures: Option>, + nonce: Option>, +} + +impl BodyContent for ObjectShellBodyContent { + fn format(&self) -> u8 { + OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF + } +} + +impl ObjectShellBodyContent { + fn hash(&self, flags: &ObjectShellFlags) -> HashValue { + let occupy = [0u8; 0]; + let occupy = occupy.raw_encode_to_buffer().unwrap(); + + let mut sha256 = sha2::Sha256::new(); + sha256.input(self.desc.as_slice()); + sha256.input( + self.body + .as_ref() + .map_or(occupy.as_slice(), |v| v.as_slice()), + ); + + if flags.is_desc_sign_fix { + sha256.input( + self.desc_signatures + .as_ref() + .map_or(occupy.as_slice(), |v| v.as_slice()), + ); + } + if flags.is_body_sign_fix { + sha256.input( + self.body_signatures + .as_ref() + .map_or(occupy.as_slice(), |v| v.as_slice()), + ); + } + if flags.is_nonce_fix { + sha256.input( + self.nonce + .as_ref() + .map_or(occupy.as_slice(), |v| v.as_slice()), + ); + } + HashValue::from(sha256.result()) + } +} + +type ObjectShellType = NamedObjType; +type ObjectShellBuilder = NamedObjectBuilder; +type ObjectShellDesc = NamedObjectDesc; + +type ObjectShellId = NamedObjectId; +type ObjectShellStorage = NamedObjectBase; + +trait ObjectShellStorageObjectId { + fn shell_id(&self) -> ObjectId; + fn check_hash(&self) -> bool; + fn hash(&self) -> Option; + fn flags(&self) -> ObjectShellFlags; +} +impl ObjectShellStorageObjectId for ObjectShellStorage { + fn shell_id(&self) -> ObjectId { + self.desc().calculate_id() + } -use crate::{Storage, StorageObj}; + fn check_hash(&self) -> bool { + self.hash().as_ref().map_or(false, |hash| { + &self.desc().content().fix_content_hash == hash + }) + } + + fn hash(&self) -> Option { + self.body() + .as_ref() + .map(|body| body.content().hash(&self.flags())) + } -const OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE: u8 = 0b_1; -const OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE: u8 = 0b_10; -const OBJECT_SHELL_FLAGS_FREEDOM_NONCE: u8 = 0b_100; -const OBJECT_SHELL_FLAGS_EXT: u8 = 0b_10000000; + fn flags(&self) -> ObjectShellFlags { + let desc = self.desc().content(); + ObjectShellFlags { + is_object_id_only: desc.is_object_id_only, + is_desc_sign_fix: desc.is_desc_sign_fix, + is_body_sign_fix: desc.is_body_sign_fix, + is_nonce_fix: desc.is_nonce_fix, + } + } +} #[derive(Copy, Clone)] pub struct ObjectShellFlags { - flags: u8, + is_object_id_only: bool, + is_desc_sign_fix: bool, + is_body_sign_fix: bool, + is_nonce_fix: bool, } -pub const OBJECT_SHELL_ALL_FREEDOM: ObjectShellFlags = ObjectShellFlags { - flags: OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE - | OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE - | OBJECT_SHELL_FLAGS_FREEDOM_NONCE, -}; - impl ObjectShellFlags { - fn is_desc_sign_freedom(&self) -> bool { - self.flags & OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE != 0 + pub fn object_id_only(&self) -> bool { + self.is_object_id_only + } + + pub fn desc_sign_fix(&self) -> bool { + self.is_desc_sign_fix } - fn is_body_sign_freedom(&self) -> bool { - self.flags & OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE != 0 + pub fn body_sign_fix(&self) -> bool { + self.is_body_sign_fix } - fn is_nonce_freedom(&self) -> bool { - self.flags & OBJECT_SHELL_FLAGS_FREEDOM_NONCE != 0 + pub fn nonce_fix(&self) -> bool { + self.is_nonce_fix } } +pub const OBJECT_SHELL_ALL_FREEDOM_WITH_FULL_DESC: ObjectShellFlags = ObjectShellFlags { + is_object_id_only: false, + is_desc_sign_fix: false, + is_body_sign_fix: false, + is_nonce_fix: false, +}; + pub struct ObjectShellFlagsBuilder { - flags: u8, + flags: ObjectShellFlags, } impl ObjectShellFlagsBuilder { pub fn new() -> Self { - Self { flags: 0 } + Self { + flags: OBJECT_SHELL_ALL_FREEDOM_WITH_FULL_DESC, + } } pub fn build(&self) -> ObjectShellFlags { - ObjectShellFlags { flags: self.flags } + self.flags } - pub fn freedom_desc_signature(&mut self) -> &mut Self { - self.flags |= OBJECT_SHELL_FLAGS_FREEDOM_DESC_SIGNATURE; + pub fn object_id_only(&mut self, is_only: bool) -> &mut Self { + self.flags.is_object_id_only = is_only; self } - pub fn freedom_body_signature(&mut self) -> &mut Self { - self.flags |= OBJECT_SHELL_FLAGS_FREEDOM_BODY_SIGNATURE; + pub fn desc_sign_fix(&mut self, is_fix: bool) -> &mut Self { + self.flags.is_desc_sign_fix = is_fix; self } - pub fn freedom_nonce(&mut self) -> &mut Self { - self.flags |= OBJECT_SHELL_FLAGS_FREEDOM_NONCE; + pub fn body_sign_fix(&mut self, is_fix: bool) -> &mut Self { + self.flags.is_body_sign_fix = is_fix; self } + + pub fn nonce_fix(&mut self, is_fix: bool) -> &mut Self { + self.flags.is_nonce_fix = is_fix; + self + } +} + +enum ShelledDesc { + ObjectId(ObjectId), + Desc(D), } -pub struct ObjectShell { - raw: O, +pub struct ObjectShell +where + O: ObjectType, + O::ContentType: BodyContent, +{ + desc: ShelledDesc, + body: Option>, + signs: ObjectSigns, + nonce: Option, flags: ObjectShellFlags, - phantom: PhantomData, } -impl ObjectShell +impl ObjectShell where - O: NamedObject + RawEncode + for<'local> RawDecode<'local> + Clone, // TODO: how to support other parameter against `O` for `NamedObject` - OT: ObjectType, - OT::ContentType: BodyContent, + O: ObjectType, + O::ContentType: BodyContent + RawEncode + for<'de> RawDecode<'de> + Clone, + O::DescType: RawEncode + for<'de> RawDecode<'de> + Clone, { - pub fn from_storage(storage: &Storage) -> BuckyResult { - if storage.check_hash() != Some(true) { - return Err(BuckyError::new( - BuckyErrorCode::NotMatch, - "Hash does not match with raw object", - )); + pub fn from_object(raw: &NO, flags: ObjectShellFlags) -> Self + where + NO: NamedObject + RawEncode + for<'local> RawDecode<'local> + Clone, + { + Self { + flags, + desc: ShelledDesc::Desc(raw.desc().clone()), + body: raw.body().clone(), + signs: raw.signs().clone(), + nonce: raw.nonce().clone(), } + } - let value = storage.value().as_slice(); - if value.len() == 0 { - return Err(BuckyError::new( - BuckyErrorCode::OutOfLimit, - "empty for object shell", - )); + pub fn shell_id(&self) -> ObjectId { + self.to_storage().shell_id() + } + + pub fn flags(&self) -> &ObjectShellFlags { + &self.flags + } + + pub fn with_full_desc(&self) -> bool { + match self.desc { + ShelledDesc::ObjectId(_) => false, + ShelledDesc::Desc(_) => true, } + } - let (freedom_flags, unfreedom) = value.split_at(1); + pub fn body(&self) -> &Option> { + &self.body + } + // update the raw object + pub fn body_mut(&mut self) -> &mut Option> { + &mut self.body + } - let freedom_flags = ObjectShellFlags { - flags: *freedom_flags.get(0).unwrap(), - }; + pub fn signs(&self) -> &ObjectSigns { + &self.signs + } - let (mut raw, remain) = O::raw_decode(unfreedom)?; - assert_eq!(remain.len(), 0); + // update the signatures + pub fn signs_mut(&mut self) -> &mut ObjectSigns { + &mut self.signs + } - match storage.freedom_attachment().as_ref() { - Some(freedom) if freedom.len() > 0 => { - let (exist_field_flags, freedom) = freedom.split_at(1); - let exist_field_flags = ObjectShellFlags { - flags: *exist_field_flags.get(0).unwrap(), - }; + pub fn nonce(&self) -> &Option { + &self.nonce + } - let mut buf = freedom; + // update the nonce + pub fn nonce_mut(&mut self) -> &mut Option { + &mut self.nonce + } - if freedom_flags.is_desc_sign_freedom() && exist_field_flags.is_desc_sign_freedom() - { - let (signs, remain) = Vec::::raw_decode(buf)?; - buf = remain; - for sign in signs { - raw.signs_mut().push_desc_sign(sign); + pub fn try_into_object( + mut self, + desc: Option<&O::DescType>, + ) -> BuckyResult> { + let flags = self.flags; + let body = self.body.take(); + let mut signs = ObjectSigns::default(); + std::mem::swap(&mut signs, &mut self.signs); + let nonce = self.nonce.take(); + + let desc = match self.desc { + ShelledDesc::Desc(desc_inner) => { + let id = desc_inner.object_id(); + if let Some(desc) = desc { + let obj_id_param = desc.object_id(); + if obj_id_param != id { + let msg = format!( + "parameter desc({}) is not match with object-id({}) from desc.", + obj_id_param, id + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotMatch, msg)); } } - - if freedom_flags.is_body_sign_freedom() && exist_field_flags.is_body_sign_freedom() - { - let (signs, remain) = Vec::::raw_decode(buf)?; - buf = remain; - for sign in signs { - raw.signs_mut().push_body_sign(sign); + desc_inner + } + ShelledDesc::ObjectId(id) => match desc { + Some(desc) => { + let obj_id_param = desc.object_id(); + if obj_id_param == id { + desc.clone() + } else { + let msg = format!( + "parameter desc({}) is not match with object-id({}).", + obj_id_param, id + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::NotMatch, msg)); } } - - if freedom_flags.is_nonce_freedom() && exist_field_flags.is_nonce_freedom() { - let (nonce, remain) = u128::raw_decode(buf)?; - buf = remain; - unreachable!("nonce is not supported currently for the NamedObject::set_nonce is not exported."); - // raw.set_nonce() + None => { + let msg = format!( + "no desc stored in the shell, you should input it from parameters. object-id is {}", + id + ); + log::error!("{}", msg); + return Err(BuckyError::new(BuckyErrorCode::InvalidParam, msg)); } - assert_eq!(buf.len(), 0); - } - _ => {} - } + }, + }; - Ok(Self { - raw, - flags: freedom_flags, - phantom: PhantomData, - }) + let builder = NamedObjectBaseBuilder::::new(desc); + let builder = if let Some(body) = body { + builder.body(body) + } else { + builder + }; + let builder = builder.signs(signs); + let obj = if let Some(nonce) = nonce { + builder.nonce(nonce).build() + } else { + builder.build() + }; + + Ok(obj) } - pub fn to_storage(&self) -> Storage { - let mut const_raw = self.raw.clone(); - let max_buf_size = const_raw - .raw_measure(&None) - .expect("encode measure faield for object-shell"); - - let mut freedom_buf = vec![0; max_buf_size + 1]; - let mut exist_freedom_field_flags = ObjectShellFlagsBuilder::new(); - let (freedom_flag_buf, mut freedom_remain) = freedom_buf.split_at_mut(1); - - if self.flags.is_desc_sign_freedom() { - let desc_signs = const_raw.signs_mut().desc_signs(); - if let Some(signs) = desc_signs { - if signs.len() > 0 { - freedom_remain = signs - .raw_encode(freedom_remain, &None) - .expect("encode desc signature for object-shell failed."); - exist_freedom_field_flags.freedom_desc_signature(); - const_raw.signs_mut().clear_desc_signs(); - } - } + fn from_storage(storage: &ObjectShellStorage) -> BuckyResult { + if !storage.check_hash() { + return Err(BuckyError::new( + BuckyErrorCode::NotMatch, + "Hash does not match with raw object", + )); } - if self.flags.is_body_sign_freedom() { - let body_signs = const_raw.signs_mut().body_signs(); - if let Some(signs) = body_signs { - if signs.len() > 0 { - freedom_remain = signs - .raw_encode(freedom_remain, &None) - .expect("encode body signature for object-shell failed."); - exist_freedom_field_flags.freedom_body_signature(); - const_raw.signs_mut().clear_body_signs(); + let flags = storage.flags(); + + let storage_body = storage.body().as_ref().unwrap().content(); + + let nonce = match storage_body.nonce.as_ref() { + Some(nonce_buf) => { + if nonce_buf.len() != 16 { + return Err(BuckyError::new( + BuckyErrorCode::OutOfLimit, + "nonce should be a u128.", + )); } + let mut nonce = [0; 16]; + nonce.clone_from_slice(nonce_buf.as_slice()); + Some(u128::from_be_bytes(nonce)) } - } + None => None, + }; + + let desc = if flags.is_object_id_only { + let (id, remain) = ObjectId::raw_decode(storage_body.desc.as_slice())?; + assert_eq!(remain.len(), 0); + ShelledDesc::ObjectId(id) + } else { + let (desc, remain) = O::DescType::raw_decode(storage_body.desc.as_slice())?; + assert_eq!(remain.len(), 0); + ShelledDesc::Desc(desc) + }; - if self.flags.is_nonce_freedom() { - let nonce = const_raw.nonce(); - if let Some(nonce) = nonce.as_ref() { - freedom_remain = nonce - .raw_encode(freedom_remain, &None) - .expect("encode nonce for object-shell failed."); - exist_freedom_field_flags.freedom_nonce(); - - unreachable!( - "nonce is not supported currently for the NamedObject::set_nonce is not exported." - ); - // const_raw.set_nonce(None); + let body = match storage_body.body.as_ref() { + Some(body) => { + let (body, remain) = + ObjectMutBody::::raw_decode(body.as_slice())?; + assert_eq!(remain.len(), 0); + Some(body) } - } + None => None, + }; - let freedom_attachment = if freedom_remain.len() < max_buf_size { - *freedom_flag_buf.get_mut(0).unwrap() = exist_freedom_field_flags.flags; - let len = max_buf_size + 1 - freedom_remain.len(); - unsafe { - freedom_buf.set_len(len); + let mut signs = ObjectSigns::default(); + if let Some(desc_signatures) = storage_body.desc_signatures.as_ref() { + let (desc_signatures, remain) = + Vec::::raw_decode(desc_signatures.as_slice())?; + assert_eq!(remain.len(), 0); + for sign in desc_signatures { + signs.push_desc_sign(sign); } - Some(freedom_buf) - } else { - None }; - let mut value = vec![0; max_buf_size + 1]; - *value.get_mut(0).unwrap() = self.flags.flags; - let remain = const_raw - .raw_encode(&mut value.as_mut_slice()[1..], &None) - .unwrap(); - let len = max_buf_size + 1 - remain.len(); - unsafe { - value.set_len(len); - } + if let Some(body_signatures) = storage_body.body_signatures.as_ref() { + let (body_signatures, remain) = + Vec::::raw_decode(body_signatures.as_slice())?; + assert_eq!(remain.len(), 0); + for sign in body_signatures { + signs.push_body_sign(sign); + } + }; - Storage::create_with_hash_and_freedom( - self.raw.desc().object_id().to_string().as_str(), - value, - freedom_attachment, - ) + Ok(Self { + desc, + body, + signs, + nonce, + flags, + }) } - pub fn shell_id(&self) -> ObjectId { - self.to_storage().storage_id().object_id().clone() - } + fn to_storage(&self) -> ObjectShellStorage { + let desc = match &self.desc { + ShelledDesc::ObjectId(obj_id) => { + assert!(self.flags.is_object_id_only); + obj_id.to_vec().expect("encode desc as object-id failed.") + } + ShelledDesc::Desc(desc) => { + if self.flags.is_object_id_only { + desc.object_id() + .to_vec() + .expect("encode desc as object-id from desc failed.") + } else { + desc.to_vec().expect("encode desc as desc failed.") + } + } + }; - pub fn from_object(raw: O, flags: ObjectShellFlags) -> Self { - Self { - raw, - flags, - phantom: PhantomData, - } - } + let body = match self.body.as_ref() { + Some(body) => { + let mut ctx = NamedObjectBodyContext::new(); + let size = body + .raw_measure_with_context(&mut ctx, &None) + .expect("measure body failed."); + let mut body_buf = vec![]; + body_buf.resize(size, 0u8); + let remain = body + .raw_encode_with_context(body_buf.as_mut(), &mut ctx, &None) + .expect("encode body failed."); + assert_eq!(remain.len(), 0); + Some(body_buf) + } + None => None, + }; - pub fn as_ref(&self) -> &O { - &self.raw - } + let desc_signatures = match self.signs.desc_signs().as_ref() { + Some(desc_signatures) => Some( + desc_signatures + .to_vec() + .expect("encode desc-signatures failed."), + ), + None => None, + }; - pub fn as_mut(&mut self) -> &mut O { - // update the raw object - &mut self.raw - } + let body_signatures = match self.signs.body_signs().as_ref() { + Some(body_signatures) => Some( + body_signatures + .to_vec() + .expect("encode body-signatures failed."), + ), + None => None, + }; + + let nonce = self.nonce.clone(); + + let storage_body = ObjectShellBodyContent { + desc, + body, + desc_signatures, + body_signatures, + nonce: nonce.map(|n| Vec::from(n.to_be_bytes())), + }; + + let hash = storage_body.hash(&self.flags); + + let storage_desc = ObjectShellDescContent { + is_object_id_only: self.flags.is_object_id_only, + is_desc_sign_fix: self.flags.is_desc_sign_fix, + is_body_sign_fix: self.flags.is_body_sign_fix, + is_nonce_fix: self.flags.is_nonce_fix, + fix_content_hash: hash, + }; - pub fn into_object(self) -> O { - self.raw + let shell = ObjectShellBuilder::new(storage_desc, storage_body) + .no_create_time() + .build(); + shell } } -impl RawEncode for ObjectShell +impl RawEncode for ObjectShell where - O: NamedObject + RawEncode + for<'de> RawDecode<'de> + Clone, - OT: ObjectType, - OT::ContentType: BodyContent, + O: ObjectType, + O::ContentType: BodyContent + RawEncode + for<'de> RawDecode<'de> + Clone, + O::DescType: RawEncode + for<'de> RawDecode<'de> + Clone, { fn raw_measure(&self, purpose: &Option) -> BuckyResult { self.to_storage().raw_measure(purpose) @@ -272,14 +517,14 @@ where } } -impl<'de, O, OT> RawDecode<'de> for ObjectShell +impl<'de, O> RawDecode<'de> for ObjectShell where - O: NamedObject + RawEncode + for<'local> RawDecode<'local> + Clone, - OT: ObjectType, - OT::ContentType: BodyContent, + O: ObjectType, + O::ContentType: BodyContent + RawEncode + for<'de1> RawDecode<'de1> + Clone, + O::DescType: RawEncode + for<'de1> RawDecode<'de1> + Clone, { fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> { - let (storage, remain) = Storage::raw_decode(buf)?; + let (storage, remain) = ObjectShellStorage::raw_decode(buf)?; Self::from_storage(&storage).map(|o| (o, remain)) } } diff --git a/src/component/cyfs-core/src/storage/storage.rs b/src/component/cyfs-core/src/storage/storage.rs index b0700b796..3f25ad0ac 100644 --- a/src/component/cyfs-core/src/storage/storage.rs +++ b/src/component/cyfs-core/src/storage/storage.rs @@ -28,7 +28,6 @@ impl DescContent for StorageDescContent { #[cyfs_protobuf_type(crate::codec::protos::StorageBodyContent)] pub struct StorageBodyContent { pub(crate) value: Vec, - freedom_attachment: Option>, } impl BodyContent for StorageBodyContent { @@ -47,11 +46,6 @@ pub type Storage = NamedObjectBase; pub trait StorageObj { fn create(id: &str, value: Vec) -> Self; fn create_with_hash(id: &str, value: Vec) -> Self; - fn create_with_hash_and_freedom( - id: &str, - value: Vec, - freedom_attachment: Option>, - ) -> Self; fn id(&self) -> &str; fn hash(&self) -> &Option; @@ -62,10 +56,6 @@ pub trait StorageObj { fn update_value(&mut self, value: Vec) -> bool; fn into_value(self) -> Vec; - fn freedom_attachment(&self) -> &Option>; - fn freedom_attachment_mut(&mut self) -> &mut Option>; - fn into_value_freedom(self) -> (Vec, Option>); - fn storage_id(&self) -> StorageId; fn check_hash(&self) -> Option; @@ -73,10 +63,7 @@ pub trait StorageObj { impl StorageObj for Storage { fn create(id: &str, value: Vec) -> Self { - let body = StorageBodyContent { - value, - freedom_attachment: None, - }; + let body = StorageBodyContent { value }; let desc = StorageDescContent { id: id.to_owned(), hash: None, @@ -89,27 +76,10 @@ impl StorageObj for Storage { id: id.to_owned(), hash: Some(hash_data(&value)), }; - let body = StorageBodyContent { - value, - freedom_attachment: None, - }; + let body = StorageBodyContent { value }; StorageBuilder::new(desc, body).no_create_time().build() } - fn create_with_hash_and_freedom( - id: &str, - value: Vec, - freedom_attachment: Option>, - ) -> Self { - let mut obj = Self::create_with_hash(id, value); - obj.body_mut() - .as_mut() - .unwrap() - .content_mut() - .freedom_attachment = freedom_attachment; - obj - } - fn id(&self) -> &str { &self.desc().content().id } @@ -160,28 +130,6 @@ impl StorageObj for Storage { true } - fn freedom_attachment(&self) -> &Option> { - &self.body().as_ref().unwrap().content().freedom_attachment - } - - fn freedom_attachment_mut(&mut self) -> &mut Option> { - &mut self - .body_mut() - .as_mut() - .unwrap() - .content_mut() - .freedom_attachment - } - - fn into_value_freedom(mut self) -> (Vec, Option>) { - let body = &mut self.body_mut().as_mut().unwrap().content_mut(); - let mut value = vec![]; - let mut attachment = None; - std::mem::swap(&mut value, &mut body.value); - std::mem::swap(&mut attachment, &mut body.freedom_attachment); - (value, attachment) - } - fn storage_id(&self) -> StorageId { self.desc().calculate_id().try_into().unwrap() } diff --git a/src/component/cyfs-group/src/storage/group_shell_mgr.rs b/src/component/cyfs-group/src/storage/group_shell_mgr.rs index 475c6732f..61410820c 100644 --- a/src/component/cyfs-group/src/storage/group_shell_mgr.rs +++ b/src/component/cyfs-group/src/storage/group_shell_mgr.rs @@ -2,8 +2,9 @@ use std::{collections::HashMap, sync::Arc}; use async_std::sync::RwLock; use cyfs_base::{ - BuckyError, BuckyErrorCode, BuckyResult, Group, NamedObject, ObjectDesc, ObjectId, - ObjectMapRootManagerRef, OpEnvPathAccess, RawConvertTo, RawDecode, + AnyNamedObject, BuckyError, BuckyErrorCode, BuckyResult, Group, GroupDesc, NamedObject, + ObjectDesc, ObjectId, ObjectMapRootManagerRef, OpEnvPathAccess, RawConvertTo, RawDecode, + RawFrom, TypelessCoreObject, }; use cyfs_base_meta::SavedMetaObject; use cyfs_core::{DecApp, DecAppObj, GroupShell, ToGroupShell}; @@ -22,6 +23,7 @@ struct GroupShellCache { struct GroupShellManagerRaw { cache: RwLock, + group_desc: GroupDesc, shell_state: ObjectMapRootManagerRef, state_path: GroupShellStatePath, meta_client: Arc, @@ -40,8 +42,16 @@ impl GroupShellManager { root_state_mgr: &GlobalStateManagerRawProcessorRef, remote: Option<&ObjectId>, ) -> BuckyResult { - let (group, shell_id) = - Self::get_group_impl(&non_driver, &meta_client, group_id, None, remote, None).await?; + let (group, shell_id) = Self::get_group_impl( + &non_driver, + &meta_client, + group_id, + None, + remote, + None, + None, + ) + .await?; let shell_dec_id = Self::shell_dec_id(group_id); @@ -60,12 +70,13 @@ impl GroupShellManager { cache: RwLock::new(GroupShellCache { latest_shell_id: shell_id, groups_by_shell: HashMap::from([(shell_id.clone(), group.clone())]), - groups_by_version: HashMap::from([(group.version(), group)]), + groups_by_version: HashMap::from([(group.version(), group.clone())]), }), shell_state, meta_client, non_driver, state_path: GroupShellStatePath::new(), + group_desc: group.desc().clone(), }; let ret = Self(Arc::new(raw)); @@ -124,6 +135,7 @@ impl GroupShellManager { Some(&latest_shell_id), None, None, + None, ) .await { @@ -135,9 +147,16 @@ impl GroupShellManager { latest_shell_id, err ); - let (group, shell_id) = - Self::get_group_impl(&non_driver, &meta_client, group_id, None, None, None) - .await?; + let (group, shell_id) = Self::get_group_impl( + &non_driver, + &meta_client, + group_id, + None, + None, + None, + None, + ) + .await?; Self::mount_shell( &shell_state, @@ -158,12 +177,13 @@ impl GroupShellManager { cache: RwLock::new(GroupShellCache { latest_shell_id, groups_by_shell: HashMap::from([(latest_shell_id.clone(), group.clone())]), - groups_by_version: HashMap::from([(group.version(), group)]), + groups_by_version: HashMap::from([(group.version(), group.clone())]), }), shell_state, meta_client, non_driver, state_path: GroupShellStatePath::new(), + group_desc: group.desc().clone(), }; let ret = Self(Arc::new(raw)); @@ -208,6 +228,7 @@ impl GroupShellManager { group_shell_id, from, Some(&latest_shell_id), + Some(&self.0.group_desc), ) .await?; @@ -285,13 +306,26 @@ impl GroupShellManager { group_shell_id: Option<&ObjectId>, from: Option<&ObjectId>, latest_group_shell_id: Option<&ObjectId>, + group_desc: Option<&GroupDesc>, ) -> BuckyResult<(Group, ObjectId)> { match group_shell_id { Some(group_shell_id) => { let shell = non_driver.get_object(group_shell_id, from).await?; let (group_shell, remain) = GroupShell::raw_decode(shell.object_raw.as_slice())?; assert_eq!(remain.len(), 0); - let group = group_shell.into_object(); + let group = if !group_shell.with_full_desc() { + match group_desc { + Some(group_desc) => group_shell.try_into_object(Some(group_desc))?, + None => { + let group = non_driver.get_object(group_id, from).await?; + let (group, _remain) = Group::raw_decode(group.object_raw.as_slice())?; + group_shell.try_into_object(Some(group.desc()))? + } + } + } else { + group_shell.try_into_object(None)? + }; + let body_hash = group.body().as_ref().unwrap().calculate_hash()?; // TODO: 用`body_hash`从链上验证其合法性 let group_id_from_shell = group.desc().object_id(); @@ -313,7 +347,12 @@ impl GroupShellManager { let shell_id = group_shell.shell_id(); if latest_group_shell_id != Some(&shell_id) { // put to noc - let shell_obj = NONObjectInfo::new(shell_id, group_shell.to_vec()?, None); + let buf = group_shell.to_vec()?; + let shell_any = Arc::new(AnyNamedObject::Core( + TypelessCoreObject::clone_from_slice(buf.as_slice()).unwrap(), + )); + let shell_obj = + NONObjectInfo::new(shell_id, group_shell.to_vec()?, Some(shell_any)); non_driver.put_object(shell_obj).await?; } From 20fb5f5d767f5034e11b118ad38e1c12c5292bb4 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 21 Apr 2023 21:57:14 +0800 Subject: [PATCH 544/553] Synchronizer --- .../cyfs-core/protos/core_objects.proto | 14 +- .../cyfs-core/src/storage/object_shell.rs | 54 ++++- .../src/consensus/hotstuff/hotstuff.rs | 204 +++++++++++++++--- .../consensus/synchronizer/synchronizer.rs | 15 +- src/component/cyfs-group/src/constant.rs | 1 + .../cyfs-group/src/dec/group_manager.rs | 152 ++++++++++--- .../cyfs-group/src/dec/rpath_service.rs | 6 +- .../src/network/meta_client_timeout.rs | 43 ++++ src/component/cyfs-group/src/network/mod.rs | 2 + .../cyfs-group/src/network/non_driver.rs | 1 + .../cyfs-group/src/storage/group_shell_mgr.rs | 2 +- .../cyfs-group/src/storage/group_storage.rs | 10 + src/tests/group-example/src/main.rs | 11 +- 13 files changed, 443 insertions(+), 72 deletions(-) create mode 100644 src/component/cyfs-group/src/network/meta_client_timeout.rs diff --git a/src/component/cyfs-core/protos/core_objects.proto b/src/component/cyfs-core/protos/core_objects.proto index fc292ef9f..3fbf3b7e9 100644 --- a/src/component/cyfs-core/protos/core_objects.proto +++ b/src/component/cyfs-core/protos/core_objects.proto @@ -28,16 +28,28 @@ message ObjectShellDescContent { // false: calculate the `fix_content_hash` without `nonce`. bool is_nonce_fix = 4; - // hash of `fix_content` in `ObjectShellBodyContent` + // hash of fixed fields in `ObjectShellBodyContent`. + // hash_buf = desc + body + [desc_signatures] + [body_signatures] + [nonce] + // * any field with a value of `None` should be occupied with 1 byte with a value of 0. + // fix_content_hash = sha256(hash_buf) bytes fix_content_hash = 5; } message ObjectShellBodyContent { + // if is_object_id_only is true, `desc` is the encoded buffer of `ObjectId` of the original object. + // otherwise, `desc` is the encoded buffer of the full `Desc` of the original object. bytes desc = 1; + + // `body` is the encoded buffer of the `Body` of the original object. optional bytes body = 2; + // `desc_signatures` is the encoded buffer of the `Object.signs().desc_signs()` of the original object. optional bytes desc_signatures = 3; + + // `body_signatures` is the encoded buffer of the `Object.signs().body_signs()` of the original object. optional bytes body_signatures = 4; + + // `nonce` is the encoded buffer of the `nonce` of the original object. optional bytes nonce = 5; } diff --git a/src/component/cyfs-core/src/storage/object_shell.rs b/src/component/cyfs-core/src/storage/object_shell.rs index d2f639b7b..0e467714b 100644 --- a/src/component/cyfs-core/src/storage/object_shell.rs +++ b/src/component/cyfs-core/src/storage/object_shell.rs @@ -97,13 +97,13 @@ type ObjectShellDesc = NamedObjectDesc; type ObjectShellId = NamedObjectId; type ObjectShellStorage = NamedObjectBase; -trait ObjectShellStorageObjectId { +trait ObjectShellStorageObject { fn shell_id(&self) -> ObjectId; fn check_hash(&self) -> bool; fn hash(&self) -> Option; fn flags(&self) -> ObjectShellFlags; } -impl ObjectShellStorageObjectId for ObjectShellStorage { +impl ObjectShellStorageObject for ObjectShellStorage { fn shell_id(&self) -> ObjectId { self.desc().calculate_id() } @@ -200,15 +200,18 @@ impl ObjectShellFlagsBuilder { } } -enum ShelledDesc { +#[derive(Clone)] +enum ShelledDesc { ObjectId(ObjectId), Desc(D), } +#[derive(Clone)] pub struct ObjectShell where O: ObjectType, O::ContentType: BodyContent, + O::DescType: Clone, { desc: ShelledDesc, body: Option>, @@ -281,7 +284,6 @@ where mut self, desc: Option<&O::DescType>, ) -> BuckyResult> { - let flags = self.flags; let body = self.body.take(); let mut signs = ObjectSigns::default(); std::mem::swap(&mut signs, &mut self.signs); @@ -528,3 +530,47 @@ where Self::from_storage(&storage).map(|o| (o, remain)) } } + +#[cfg(test)] +mod object_shell_test { + use crate::{ObjectShell, Text, TextObj, OBJECT_SHELL_ALL_FREEDOM_WITH_FULL_DESC}; + + #[test] + fn test() { + let txt_v1 = Text::create("txt-storage", "header", "v1"); + // shell with full-desc, desc-signatures freedom, body-signatures freedom, nonce freedom. + let txt_shell_v1 = + ObjectShell::from_object::(&txt_v1, OBJECT_SHELL_ALL_FREEDOM_WITH_FULL_DESC); + let txt_v1_from_shell = txt_shell_v1 + .try_into_object(None) + .expect("recover text from shell failed."); + let shell_id_v1 = txt_shell_v1.shell_id(); + assert_eq!(txt_v1_from_shell.id(), txt_v1.id()); + assert_eq!(txt_v1_from_shell.header(), txt_v1.header()); + assert_eq!(txt_v1_from_shell.value(), txt_v1.value()); + + // shell-id changed when the body updated. + let mut txt_shell_v2 = txt_shell_v1.clone(); + *txt_shell_v2.body_mut().unwrap().content().value_mut() = "v2".to_string(); + let txt_v2_from_shell = txt_shell_v2 + .try_into_object(None) + .expect("recover text from shell failed."); + let shell_id_v2 = txt_shell_v2.shell_id(); + assert_eq!(txt_v2_from_shell.id(), txt_v1.id()); + assert_eq!(txt_v2_from_shell.header(), txt_v1.header()); + assert_eq!(txt_v2_from_shell.value(), "v2"); + assert_ne!(shell_id_v1, shell_id_v2); + + // shell-id not changed when the nonce updated. + let mut txt_shell_v2_nonce = txt_shell_v2.clone(); + *txt_shell_v2_nonce.nonce_mut() = Some(1); + let txt_v2_nonce_from_shell = txt_shell_v2_nonce + .try_into_object(None) + .expect("recover text from shell failed."); + let shell_id_v2_nonce = txt_shell_v2_nonce.shell_id(); + assert_eq!(txt_v2_nonce_from_shell.id(), txt_v1.id()); + assert_eq!(txt_v2_nonce_from_shell.header(), txt_v1.header()); + assert_eq!(txt_v2_nonce_from_shell.value(), txt_v2_from_shell.value()); + assert_ne!(shell_id_v2_nonce, shell_id_v2); + } +} diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 2b395dc5d..52c99b734 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -25,15 +25,15 @@ use crate::{ helper::Timer, storage::GroupShellManager, Committee, GroupObjectMapProcessor, GroupStorage, HotstuffMessage, PendingProposalConsumer, - RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, CHANNEL_CAPACITY, - GROUP_DEFAULT_CONSENSUS_INTERVAL, HOTSTUFF_TIMEOUT_DEFAULT, PROPOSAL_MAX_TIMEOUT, - TIME_PRECISION, + RPathEventNotifier, SyncBound, VoteMgr, VoteThresholded, BLOCK_COUNT_REST_TO_SYNC, + CHANNEL_CAPACITY, GROUP_DEFAULT_CONSENSUS_INTERVAL, HOTSTUFF_TIMEOUT_DEFAULT, + PROPOSAL_MAX_TIMEOUT, TIME_PRECISION, }; /** * TODO: generate empty block when the 'Node' is synchronizing * - * How to distinguish synchronizing: max_quorum_round - round > THRESHOLD + * How to distinguish synchronizing: max_quorum_round - round > BLOCK_COUNT_REST_TO_SYNC */ pub(crate) struct Hotstuff { @@ -219,10 +219,6 @@ impl Hotstuff { } } -enum HotstuffMessageInner { - Block(GroupConsensusBlock), -} - struct HotstuffRunner { local_id: ObjectId, local_device_id: ObjectId, @@ -241,8 +237,8 @@ struct HotstuffRunner { shell_mgr: GroupShellManager, tx_message: Sender<(HotstuffMessage, ObjectId)>, rx_message: Receiver<(HotstuffMessage, ObjectId)>, - tx_message_inner: Sender<(HotstuffMessageInner, ObjectId)>, - rx_message_inner: Receiver<(HotstuffMessageInner, ObjectId)>, + tx_message_inner: Sender<(GroupConsensusBlock, ObjectId)>, + rx_message_inner: Receiver<(GroupConsensusBlock, ObjectId)>, tx_block_gen: Sender<(GroupConsensusBlock, HashMap)>, rx_block_gen: Receiver<(GroupConsensusBlock, HashMap)>, proposal_consumer: PendingProposalConsumer, @@ -318,18 +314,18 @@ impl HotstuffRunner { header_height + 1 }; + let (tx_block_gen, rx_block_gen) = async_std::channel::bounded(1); + let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); + let synchronizer = Synchronizer::new( local_device_id, network_sender.clone(), rpath.clone(), max_height, round, - tx_message.clone(), + tx_message_inner.clone(), ); - let (tx_block_gen, rx_block_gen) = async_std::channel::bounded(1); - let (tx_message_inner, rx_message_inner) = async_std::channel::bounded(CHANNEL_CAPACITY); - Self { local_id, local_device_id, @@ -373,6 +369,17 @@ impl HotstuffRunner { block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), block.owner(), remote); + if block.height() <= self.store.header_height() { + log::warn!( + "[hotstuff] local: {:?}, handle_block: {:?}/{:?}/{:?} ignored for expired.", + self, + block.block_id(), + block.round(), + block.height(), + ); + return Err(BuckyError::new(BuckyErrorCode::Expired, "block expired")); + } + let latest_group = self .shell_mgr .get_group(self.rpath.group_id(), None, Some(&remote)) @@ -694,26 +701,34 @@ impl HotstuffRunner { block.height() ); - // 乱序,同步 let fetch_height_immediate = self.store.header_height() + 3; if block.height() <= fetch_height_immediate { - self.fetch_block(block.prev_block_id().unwrap(), remote) - .await; - } - - // let max_round_block = self.store.block_with_max_round(); - // let max_height = max_round_block.map_or(1, |block| block.height() + 1); - - if block.height() > fetch_height_immediate { + // little blocks, get them from remote immediately. + self.sync_to_block(block.clone(), remote).await; + } else { + // large blocks, notify remote to push. log::debug!( "[hotstuff] local: {:?}, will sync blocks from height({}) to height({}). block.round={}, remote: {}", self, - fetch_height_immediate, + self.store.max_height(), block.height(), block.round(), remote ); + if self.store.max_height() + 1 <= fetch_height_immediate - 1 { + self.network_sender + .post_message( + HotstuffMessage::SyncRequest( + SyncBound::Height(self.store.max_height() + 1), + SyncBound::Height(fetch_height_immediate - 1), + ), + self.rpath.clone(), + &remote, + ) + .await; + } + self.synchronizer.push_outorder_block( block.clone(), fetch_height_immediate, @@ -1767,7 +1782,17 @@ impl HotstuffRunner { } async fn local_timeout_round(&mut self) -> BuckyResult<()> { - log::debug!("[hotstuff] local: {:?}, local_timeout_round", self,); + log::debug!( + "[hotstuff] local: {:?}, local_timeout_round, max_quorum_height: {}, max_height: {}", + self, + self.max_quorum_height, + self.store.max_height() + ); + + if self.is_synchronizing() { + log::info!("[hotstuff] local: {:?}, local_timeout_round, is synchronizing, ignore the timeout. max_quorum_height: {}, max_height: {}", self, self.max_quorum_height, self.store.max_height()); + return Ok(()); + } let latest_group = match self .shell_mgr @@ -1790,6 +1815,11 @@ impl HotstuffRunner { } }; + log::debug!( + "[hotstuff] local: {:?}, local_timeout_round, latest group got.", + self, + ); + let latest_group_shell = latest_group.to_shell(); let latest_group_shell_id = latest_group_shell.shell_id(); let timeout = HotstuffTimeoutVote::new( @@ -1809,9 +1839,22 @@ impl HotstuffRunner { err })?; - self.store.set_last_vote_round(self.round).await?; + log::debug!( + "[hotstuff] local: {:?}, local_timeout_round, vote for timeout created.", + self, + ); + + let ret = self.store.set_last_vote_round(self.round).await; + log::debug!("[hotstuff] local: {:?}, local_timeout_round, round last vote is stored. round = {}, result: {:?}", self, self.round, ret); + ret?; self.broadcast(HotstuffMessage::TimeoutVote(timeout.clone()), &latest_group); + + log::debug!( + "[hotstuff] local: {:?}, local_timeout_round, broadcast.", + self, + ); + self.tx_message .send((HotstuffMessage::TimeoutVote(timeout), self.local_device_id)) .await; @@ -1819,6 +1862,10 @@ impl HotstuffRunner { Ok(()) } + fn is_synchronizing(&self) -> bool { + self.max_quorum_height > self.store.max_height() + BLOCK_COUNT_REST_TO_SYNC + } + async fn generate_block(&mut self, tc: Option) -> BuckyResult<()> { let now = SystemTime::now(); @@ -2282,9 +2329,93 @@ impl HotstuffRunner { err })?; - self.tx_message_inner - .send((HotstuffMessageInner::Block(block), remote)) - .await; + self.tx_message_inner.send((block, remote)).await; + Ok(()) + } + + async fn sync_to_block( + &mut self, + latest_block: GroupConsensusBlock, + remote: ObjectId, + ) -> BuckyResult<()> { + // 1. fetch prev blocks in range (header_height, latest_block.height) + let header_height = self.store.header_height(); + let max_height = latest_block.height(); + if max_height <= header_height { + return Ok(()); + } + + let mut blocks = Vec::with_capacity((max_height - header_height) as usize); + let mut fetching_block_id = latest_block.prev_block_id().cloned(); + + blocks.push(latest_block); + + for i in 0..(max_height - header_height - 1) { + let expected_height = max_height - i - 1; + match fetching_block_id.as_ref() { + Some(block_id) => { + if self.store.find_block_in_cache(block_id).is_ok() { + break; + } + + let block = self + .non_driver + .get_block(block_id, Some(&remote)) + .await + .map_err(|err| { + log::error!( + "[hotstuff] local: {:?}, sync block({}) at height({}) from {} failed, err: {:?}.", + self, + block_id, + expected_height, + remote, + err + ); + err + })?; + + if block.height() != expected_height { + log::error!("[hotstuff] local: {:?}, sync block({}) at height({}) from {} failed, block.height is {}.", self, block_id, expected_height, remote, block.height()); + return Err(BuckyError::new( + BuckyErrorCode::Unmatch, + "unexpected block height", + )); + } + + log::debug!( + "[hotstuff] local: {:?}, sync block({}) at height({}) from {}, fetch success.", + self, + block_id, + expected_height, + remote + ); + + fetching_block_id = block.prev_block_id().cloned(); + blocks.push(block); + } + None => { + log::error!("[hotstuff] local: {:?}, sync block at height({}) from {} failed, block id is None.", self, expected_height, remote); + return Err(BuckyError::new( + BuckyErrorCode::Failed, + "unexpected block id", + )); + } + } + } + + // 2. handle blocks in order + for block in blocks.into_iter().rev() { + log::debug!( + "[hotstuff] local: {:?}, sync block({}) at height({}) from {}, will handle it.", + self, + block.block_id(), + block.height(), + remote + ); + + self.tx_message_inner.send((block, remote)).await; + } + Ok(()) } @@ -2491,8 +2622,12 @@ impl HotstuffRunner { } async fn run(&mut self) -> ! { + log::info!("[hotstuff] {:?} start, will recover.", self); + self.recover().await; + log::info!("[hotstuff] {:?} start, recovered.", self); + // This is the main loop: it processes incoming blocks and votes, // and receive timeout notifications from our Timeout Manager. loop { @@ -2520,7 +2655,16 @@ impl HotstuffRunner { }, }, message = self.rx_message_inner.recv().fuse() => match message { - Ok((HotstuffMessageInner::Block(block), remote)) => { + Ok((block, remote)) => { + log::debug!( + "[hotstuff] local: {:?}, receive block({}) from ({}) from rx_message_inner, height: {}, round: {}.", + self, + block.block_id(), + remote, + block.height(), + block.round() + ); + if remote == self.local_device_id { self.process_block(&block, remote, &HashMap::new()).await } else { diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index a4f381f2c..6e1eedd9c 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -34,7 +34,7 @@ impl Synchronizer { rpath: GroupRPath, height: u64, round: u64, - tx_block: Sender<(HotstuffMessage, ObjectId)>, + tx_block: Sender<(GroupConsensusBlock, ObjectId)>, ) -> Self { let (tx_sync_message, rx_sync_message) = async_std::channel::bounded(CHANNEL_CAPACITY); let mut runner = SynchronizerRunner::new( @@ -320,7 +320,7 @@ struct SynchronizerRunner { local_device_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, - tx_block: Sender<(HotstuffMessage, ObjectId)>, + tx_block: Sender<(GroupConsensusBlock, ObjectId)>, rx_message: Receiver, timer: Timer, height: u64, @@ -335,7 +335,7 @@ impl SynchronizerRunner { local_device_id: ObjectId, network_sender: crate::network::Sender, rpath: GroupRPath, - tx_block: Sender<(HotstuffMessage, ObjectId)>, + tx_block: Sender<(GroupConsensusBlock, ObjectId)>, rx_message: Receiver, height: u64, round: u64, @@ -652,10 +652,11 @@ impl SynchronizerRunner { self.sync_requests.splice(0..(remove_request_pos + 1), []); } - futures::future::join_all(order_blocks.into_iter().map(|(order_block, remote)| { - self.tx_block - .send((HotstuffMessage::Block(order_block), remote)) - })) + futures::future::join_all( + order_blocks + .into_iter() + .map(|(order_block, remote)| self.tx_block.send((order_block, remote))), + ) .await; } diff --git a/src/component/cyfs-group/src/constant.rs b/src/component/cyfs-group/src/constant.rs index 61f8a1106..e5db191b0 100644 --- a/src/component/cyfs-group/src/constant.rs +++ b/src/component/cyfs-group/src/constant.rs @@ -23,3 +23,4 @@ pub const NET_PROTOCOL_VPORT: u16 = 2048; pub const MEMORY_CACHE_SIZE: usize = 1024; pub const MEMORY_CACHE_DURATION: Duration = Duration::from_secs(300); pub const GROUP_DEFAULT_CONSENSUS_INTERVAL: u64 = 5000; // default 5000 ms +pub const BLOCK_COUNT_REST_TO_SYNC: u64 = 8; // the node will stop most work, and synchronize the lost blocks. diff --git a/src/component/cyfs-group/src/dec/group_manager.rs b/src/component/cyfs-group/src/dec/group_manager.rs index 5af50696e..ef873b774 100644 --- a/src/component/cyfs-group/src/dec/group_manager.rs +++ b/src/component/cyfs-group/src/dec/group_manager.rs @@ -83,6 +83,15 @@ impl GroupManager { rpath: &str, is_auto_create: bool, ) -> BuckyResult { + log::info!( + "find rpath service, group: {}, dec_id: {}, rpath: {}, is_auto_create: {}. local: {}", + group_id, + dec_id, + rpath, + is_auto_create, + self.local_info().bdt_stack.local_device_id() + ); + self.find_rpath_service_inner(group_id, dec_id, rpath, is_auto_create, None, None) .await } @@ -202,11 +211,20 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, Some(&block), Some(&remote), ) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(Block) received, and find rpath service failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; service .on_message(HotstuffMessage::Block(block), remote) .await; @@ -218,11 +236,20 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, None, Some(&remote), ) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(BlockVote) received, and find rpath service failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; service .on_message(HotstuffMessage::BlockVote(vote), remote) .await; @@ -234,11 +261,20 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, None, Some(&remote), ) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(TimeoutVote) received, and find rpath service failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; service .on_message(HotstuffMessage::TimeoutVote(vote), remote) .await; @@ -250,11 +286,20 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, None, Some(&remote), ) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(Timeout) received, and find rpath service failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; service .on_message(HotstuffMessage::Timeout(tc), remote) .await; @@ -266,11 +311,20 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, None, Some(&remote), ) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(SyncRequest) received, and find rpath service failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; service .on_message(HotstuffMessage::SyncRequest(min_bound, max_bound), remote) .await; @@ -282,11 +336,20 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, None, Some(&remote), ) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(LastStateRequest) received, and find rpath service failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; service .on_message(HotstuffMessage::LastStateRequest, remote) .await; @@ -330,7 +393,7 @@ impl GroupManager { rpath.group_id(), rpath.dec_id(), rpath.rpath(), - false, + true, None, Some(&remote), ) @@ -342,10 +405,25 @@ impl GroupManager { .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; } - _ => { + Err(err) => { + log::debug!( + "new msg(QueryState) received, and find rpath service failed, will try query state from client, {:?}. local: {}", + rpath, + self.local_info().bdt_stack.local_device_id() + ); + let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(QueryState) received, and find rpath client failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; client .on_message(HotstuffMessage::QueryState(sub_path), remote) .await; @@ -359,7 +437,16 @@ impl GroupManager { ); let client = self .rpath_client(rpath.group_id(), rpath.dec_id(), rpath.rpath()) - .await?; + .await + .map_err(|err| { + log::error!( + "new msg(VerifiableState) received, and find rpath client failed, {:?}. local: {}, err: {:?}", + rpath, + self.local_info().bdt_stack.local_device_id(), + err + ); + err + })?; client .on_message( HotstuffMessage::VerifiableState(sub_path, result.map_err(|(err, _)| err)), @@ -382,6 +469,12 @@ impl GroupManager { remote: Option<&ObjectId>, ) -> BuckyResult { { + log::debug!( + "try will find service({}) from exist cache, local: {}.", + rpath, + self.local_info().bdt_stack.local_device_id() + ); + // read let raw = self.read().await; let found = raw @@ -396,6 +489,12 @@ impl GroupManager { } { + log::debug!( + "find service({}) from exist cache failed, will try create new, local: {}.", + rpath, + self.local_info().bdt_stack.local_device_id() + ); + // write let local_info = self.local_info(); let local_id = local_info.bdt_stack.local_const().owner().unwrap(); @@ -414,10 +513,6 @@ impl GroupManager { ); let local_device_id = local_info.bdt_stack.local_device_id().clone(); - let shell_mgr = self - .check_group_shell_mgr(group_id, non_driver.clone(), remote) - .await?; - let store = GroupStorage::load( group_id, dec_id, @@ -452,7 +547,15 @@ impl GroupManager { } }; - let mut raw = self.write().await; + log::debug!( + "find service({}) from exist cache failed, will create new auto, local: {}.", + rpath, + self.local_info().bdt_stack.local_device_id() + ); + + let shell_mgr = self + .check_group_shell_mgr(group_id, non_driver.clone(), remote) + .await?; let store = match store { Some(store) => store, @@ -469,6 +572,8 @@ impl GroupManager { } }; + let mut raw = self.write().await; + let found = raw .service_by_group .entry(group_id.clone()) @@ -480,7 +585,7 @@ impl GroupManager { match found { std::collections::hash_map::Entry::Occupied(found) => Ok(found.get().clone()), std::collections::hash_map::Entry::Vacant(entry) => { - let service = RPathService::load( + let service = RPathService::start( local_id, local_device_id.object_id().clone(), GroupRPath::new(group_id.clone(), dec_id.clone(), rpath.to_string()), @@ -490,8 +595,7 @@ impl GroupManager { non_driver, shell_mgr, store, - ) - .await?; + ); entry.insert(service.clone()); Ok(service) } diff --git a/src/component/cyfs-group/src/dec/rpath_service.rs b/src/component/cyfs-group/src/dec/rpath_service.rs index eb743355f..01c45cae8 100644 --- a/src/component/cyfs-group/src/dec/rpath_service.rs +++ b/src/component/cyfs-group/src/dec/rpath_service.rs @@ -27,7 +27,7 @@ struct RPathServiceRaw { pub struct RPathService(Arc); impl RPathService { - pub(crate) async fn load( + pub(crate) fn start( local_id: ObjectId, local_device_id: ObjectId, rpath: GroupRPath, @@ -37,7 +37,7 @@ impl RPathService { non_driver: NONDriverHelper, shell_mgr: GroupShellManager, store: GroupStorage, - ) -> BuckyResult { + ) -> Self { let (pending_proposal_handle, pending_proposal_consumer) = PendingProposalMgr::new(); let committee = Committee::new( rpath.group_id().clone(), @@ -68,7 +68,7 @@ impl RPathService { non_driver, }; - Ok(Self(Arc::new(raw))) + Self(Arc::new(raw)) } pub fn rpath(&self) -> &GroupRPath { diff --git a/src/component/cyfs-group/src/network/meta_client_timeout.rs b/src/component/cyfs-group/src/network/meta_client_timeout.rs new file mode 100644 index 000000000..26b55fdb1 --- /dev/null +++ b/src/component/cyfs-group/src/network/meta_client_timeout.rs @@ -0,0 +1,43 @@ +use std::time::Duration; + +use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, ObjectId}; +use cyfs_base_meta::SavedMetaObject; +use cyfs_meta_lib::MetaClient; +use futures::FutureExt; + +const TIMEOUT_HALF: Duration = Duration::from_millis(2000); + +#[async_trait::async_trait] +pub trait MetaClientTimeout { + async fn get_desc_timeout(&self, id: &ObjectId) -> BuckyResult; +} + +#[async_trait::async_trait] +impl MetaClientTimeout for MetaClient { + async fn get_desc_timeout(&self, id: &ObjectId) -> BuckyResult { + let fut1 = match futures::future::select( + self.get_desc(id).boxed(), + async_std::future::timeout(TIMEOUT_HALF, futures::future::pending::<()>()).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => return ret, + futures::future::Either::Right((_, fut)) => fut, + }; + + log::warn!("get desc timeout (id={})", id,); + + match futures::future::select( + self.get_desc(id).boxed(), + async_std::future::timeout(TIMEOUT_HALF, fut1).boxed(), + ) + .await + { + futures::future::Either::Left((ret, _)) => ret, + futures::future::Either::Right((ret, _)) => ret.map_or( + Err(BuckyError::new(BuckyErrorCode::Timeout, "timeout")), + |ret| ret, + ), + } + } +} diff --git a/src/component/cyfs-group/src/network/mod.rs b/src/component/cyfs-group/src/network/mod.rs index 096bd0950..6dc60dea4 100644 --- a/src/component/cyfs-group/src/network/mod.rs +++ b/src/component/cyfs-group/src/network/mod.rs @@ -1,9 +1,11 @@ mod listener; +mod meta_client_timeout; mod non_driver; mod protocol; mod sender; pub(crate) use listener::*; +pub(crate) use meta_client_timeout::*; pub use non_driver::*; pub(crate) use protocol::*; pub(crate) use sender::*; diff --git a/src/component/cyfs-group/src/network/non_driver.rs b/src/component/cyfs-group/src/network/non_driver.rs index 4fb20f79b..fa88497c2 100644 --- a/src/component/cyfs-group/src/network/non_driver.rs +++ b/src/component/cyfs-group/src/network/non_driver.rs @@ -102,6 +102,7 @@ impl NONDriverHelper { object_id: &ObjectId, from: Option<&ObjectId>, ) -> BuckyResult { + // TODO: remove block without signatures let obj = self.get_object(object_id, from).await?; let (block, remain) = GroupConsensusBlock::raw_decode(obj.object_raw.as_slice())?; assert_eq!(remain.len(), 0); diff --git a/src/component/cyfs-group/src/storage/group_shell_mgr.rs b/src/component/cyfs-group/src/storage/group_shell_mgr.rs index 61410820c..ae2ff5ecc 100644 --- a/src/component/cyfs-group/src/storage/group_shell_mgr.rs +++ b/src/component/cyfs-group/src/storage/group_shell_mgr.rs @@ -11,7 +11,7 @@ use cyfs_core::{DecApp, DecAppObj, GroupShell, ToGroupShell}; use cyfs_lib::{GlobalStateManagerRawProcessorRef, NONObjectInfo}; use cyfs_meta_lib::MetaClient; -use crate::{GroupShellStatePath, NONDriverHelper}; +use crate::{GroupShellStatePath, MetaClientTimeout, NONDriverHelper}; const ACCESS: Option = None; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index 53d65cb00..db214673e 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -144,6 +144,16 @@ impl GroupStorage { self.cache.header_block.as_ref().map_or(0, |b| b.height()) } + pub fn max_height(&self) -> u64 { + if self.cache.prepares.len() > 0 { + self.header_height() + 2 + } else if self.cache.pre_commits.len() > 0 { + self.header_height() + 1 + } else { + self.header_height() + } + } + pub fn first_block(&self) -> &Option { &self.cache.first_block } diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 7c774b129..d3284d6ce 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -54,7 +54,7 @@ use crate::{ * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-17 -d=test-group/members/people-17.desc 1 0 * .\cyfs-meta-client.exe putdesc -c=test-group/members/people-18 -d=test-group/members/people-18.desc 1 0 * - * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-1.desc -d=67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc 1 0 + * .\cyfs-meta-client.exe putdesc -c=test-group/admins/people-1.desc -d=67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc 0 0 * * .\desc-tool show -a 67fz8e9wt6Yqb9ex61tr2C1PwCqavBLFe153wfiVAhqQ.desc * @@ -1240,9 +1240,16 @@ async fn main_run() { for i in 0..admin_stacks.len() { let (_, shared_stack) = admin_stacks.get(i).unwrap(); - let ((admin, _), _) = admins.get(i).unwrap(); + let ((admin, _), (admin_device, _)) = admins.get(i).unwrap(); let local_name = admin.name().unwrap(); + log::info!( + "will start service, admin: {}, name: {}, device: {}", + admin.desc().object_id(), + local_name, + admin_device.desc().object_id() + ); + let group_mgr = DecService::run( &shared_stack, local_name.to_string(), From f4b17d146300be9311e33953d2ee293bee6f805f Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sun, 23 Apr 2023 21:11:12 +0800 Subject: [PATCH 545/553] Fix several bugs of synchronization --- .../src/group/group_consensus_block.rs | 14 ++- .../src/consensus/hotstuff/hotstuff.rs | 100 +++++++++++++++--- .../consensus/synchronizer/synchronizer.rs | 24 ++--- .../cyfs-group/src/storage/group_shell_mgr.rs | 4 + .../cyfs-group/src/storage/group_storage.rs | 4 + 5 files changed, 118 insertions(+), 28 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 3f5aedd42..4c2490d59 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -314,12 +314,18 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { if state == BLOCK_CHECK_STATE_NONE { let desc = self.0.desc().content(); let body = self.0.body().as_ref().unwrap().content(); - if body.hash() != desc.body_hash { - self.1 .0.store(BLOCK_CHECK_STATE_FAIL, Ordering::SeqCst); - false - } else { + + let is_result_state_match = body + .proposals + .last() + .map_or(true, |p| p.result_state == desc.result_state_id); + + if is_result_state_match && body.hash() == desc.body_hash { self.1 .0.store(BLOCK_CHECK_STATE_SUCC, Ordering::SeqCst); true + } else { + self.1 .0.store(BLOCK_CHECK_STATE_FAIL, Ordering::SeqCst); + false } } else { state == BLOCK_CHECK_STATE_SUCC diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index 52c99b734..e826bafc9 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -307,7 +307,6 @@ impl HotstuffRunner { let init_timer_interval = GROUP_DEFAULT_CONSENSUS_INTERVAL; let max_quorum_round = round - 1; let header_height = store.header_height(); - let max_height = header_height + 2; let max_quorum_height = if header_height == 0 { 0 } else { @@ -321,8 +320,8 @@ impl HotstuffRunner { local_device_id, network_sender.clone(), rpath.clone(), - max_height, - round, + store.max_height(), + store.max_round(), tx_message_inner.clone(), ); @@ -514,6 +513,7 @@ impl HotstuffRunner { Ok(()) } + #[async_recursion::async_recursion] async fn check_block_proposal_result_state_by_app( &self, block: &GroupConsensusBlock, @@ -525,8 +525,54 @@ impl HotstuffRunner { Some(prev_block) => { let result_state_id = prev_block.result_state_id(); if let Some(result_state_id) = result_state_id { - self.make_sure_result_state(result_state_id, &[prev_block.owner(), remote]) - .await?; + if let Err(err) = self + .make_sure_result_state(result_state_id, &[prev_block.owner(), remote]) + .await + { + // TODO + // try rebuild the result-state for prev-block, it'll unreachable usually except something broken. + // if we can successfully rebuild the result-state in the future, we can remove this part. + match prev_block.prev_block_id() { + Some(prev_prev_block_id) => { + let prev_prev_block = + self.non_driver.get_block(prev_prev_block_id, None).await.map_err(|err| { + log::warn!("[hotstuff] local: {:?}, rebuild of prev-prev-block({:?}) failed, get prev-prev-block failed {:?}." + , self, prev_prev_block_id, err); + err + })?; + + let mut prev_proposals = HashMap::new(); + for proposal_ex_info in prev_block.proposals() { + let proposal = self + .non_driver + .get_proposal(&proposal_ex_info.proposal, Some(remote)) + .await.map_err(|err| { + log::warn!("[hotstuff] local: {:?}, rebuild of prev-prev-block({:?}) failed, get proposal({}) failed {:?}." + , self, prev_prev_block_id, proposal_ex_info.proposal, err); + err + })?; + prev_proposals.insert(proposal_ex_info.proposal, proposal); + } + + self.check_block_proposal_result_state_by_app( + &prev_block, + &prev_proposals, + &Some(prev_prev_block), + remote, + ) + .await.map_err(|err| { + log::warn!("[hotstuff] local: {:?}, rebuild of prev-prev-block({:?}) failed, {:?}." + , self, prev_prev_block_id, err); + err + })?; + } + None => { + log::warn!("[hotstuff] local: {:?}, rebuild result-state-id({:?}) of prev-block({:?}) failed, {:?}." + , self, result_state_id, prev_block.block_id(), err); + return Err(err); + } + } + } } result_state_id.clone() } @@ -671,11 +717,19 @@ impl HotstuffRunner { .map_err(|err| Err(err))? { crate::storage::BlockLinkState::Expired => { - log::warn!("[hotstuff] local: {:?}, receive block expired.", self); + log::warn!( + "[hotstuff] local: {:?}, receive block({}) expired.", + self, + block.block_id() + ); Err(Err(BuckyError::new(BuckyErrorCode::Ignored, "expired"))) } crate::storage::BlockLinkState::Duplicate => { - log::warn!("[hotstuff] local: {:?}, receive duplicate block.", self); + log::warn!( + "[hotstuff] local: {:?}, receive duplicate block({}).", + self, + block.block_id() + ); Err(Err(BuckyError::new( BuckyErrorCode::AlreadyExists, "duplicate block", @@ -683,8 +737,9 @@ impl HotstuffRunner { } crate::storage::BlockLinkState::Link(prev_block) => { log::debug!( - "[hotstuff] local: {:?}, receive in-order block, height: {}.", + "[hotstuff] local: {:?}, receive in-order block({}), height: {}.", self, + block.block_id(), block.height() ); @@ -695,8 +750,9 @@ impl HotstuffRunner { } crate::storage::BlockLinkState::Pending => { log::warn!( - "[hotstuff] local: {:?}, receive out-order block, expect height: {}, get height: {}.", + "[hotstuff] local: {:?}, receive out-order block({}), expect height: {}, get height: {}.", self, + block.block_id(), self.store.header_height() + 3, block.height() ); @@ -740,8 +796,9 @@ impl HotstuffRunner { } crate::storage::BlockLinkState::InvalidBranch => { log::warn!( - "[hotstuff] local: {:?}, receive block in invalid branch.", - self + "[hotstuff] local: {:?}, receive block({}) in invalid branch.", + self, + block.block_id() ); Err(Err(BuckyError::new( BuckyErrorCode::Conflict, @@ -757,6 +814,23 @@ impl HotstuffRunner { remote: ObjectId, proposals: &HashMap, ) -> BuckyResult<()> { + log::debug!("[hotstuff] local: {:?}, process_block: {:?}/{:?}/{:?}, prev: {:?}/{:?}, owner: {:?}, remote: {:?},", + self, + block.block_id(), block.round(), block.height(), + block.prev_block_id(), block.qc().as_ref().map_or(0, |qc| qc.round), + block.owner(), remote); + + if block.height() <= self.store.header_height() { + log::warn!( + "[hotstuff] local: {:?}, handle_block: {:?}/{:?}/{:?} ignored for expired.", + self, + block.block_id(), + block.round(), + block.height(), + ); + return Err(BuckyError::new(BuckyErrorCode::Expired, "block expired")); + } + /** * 验证过的块执行这个函数 */ @@ -1105,14 +1179,16 @@ impl HotstuffRunner { } let mut only_rebuild_result_state = false; - if self.max_quorum_round >= self.round { + if self.max_quorum_round >= self.store.max_round() { if let Some(result_state_id) = block.result_state_id() { if self .make_sure_result_state(result_state_id, &[block.owner(), remote]) .await .is_err() { + // TODO: // download from remote failed, we need to calcute the result-state by the DEC.on_verify + // if we can successfully rebuild the result-state in the future, we can remove this part. only_rebuild_result_state = true; } } diff --git a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs index 6e1eedd9c..caa0949a4 100644 --- a/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs +++ b/src/component/cyfs-group/src/consensus/synchronizer/synchronizer.rs @@ -446,7 +446,7 @@ impl SynchronizerRunner { min_height: u64, max_bound: SyncBound, ) -> Vec<(u64, SyncBound)> { - // TODO: limit the lenght of per range + // TODO: limit the length of per range let mut last_range = Some((SyncBound::Height(min_height), max_bound)); let mut requests = vec![]; for (block, _) in self.out_order_blocks.as_slice() { @@ -472,15 +472,15 @@ impl SynchronizerRunner { fn splite_range_with_block( mut range: (SyncBound, SyncBound), - height: u64, - round: u64, + cut_height: u64, + cut_round: u64, ) -> ( Option<(SyncBound, SyncBound)>, Option<(SyncBound, SyncBound)>, ) { let min_ord = match range.0 { - SyncBound::Height(height) => height.cmp(&height), - SyncBound::Round(round) => round.cmp(&round), + SyncBound::Height(height) => cut_height.cmp(&height), + SyncBound::Round(round) => cut_round.cmp(&round), }; match min_ord { @@ -494,17 +494,17 @@ impl SynchronizerRunner { } std::cmp::Ordering::Greater => { let ord = match range.1 { - SyncBound::Height(height) => height.cmp(&height), - SyncBound::Round(round) => round.cmp(&round), + SyncBound::Height(height) => cut_height.cmp(&height), + SyncBound::Round(round) => cut_round.cmp(&round), }; match ord { std::cmp::Ordering::Less => ( - Some((range.0, SyncBound::Height(height - 1))), - Some((SyncBound::Height(height + 1), range.1)), + Some((range.0, SyncBound::Height(cut_height - 1))), + Some((SyncBound::Height(cut_height + 1), range.1)), ), std::cmp::Ordering::Equal => { - (Some((range.0, SyncBound::Height(height - 1))), None) + (Some((range.0, SyncBound::Height(cut_height - 1))), None) } std::cmp::Ordering::Greater => (Some((range.0, range.1)), None), } @@ -519,10 +519,10 @@ impl SynchronizerRunner { remote: ObjectId, ) { log::debug!("[synchronizer] local: {:?}, handle_push_block want sync blocks from height({}) to height({}). block.round={}, round={}, prev={:?}", - self.local_device_id, min_height, block.height(), self.round, block.round(), block.prev_block_id()); + self.local_device_id, min_height, block.height(), block.round(), self.round, block.prev_block_id()); if block.round() <= self.round - || min_height <= block.height() + || min_height >= block.height() || block.prev_block_id().is_none() { return; diff --git a/src/component/cyfs-group/src/storage/group_shell_mgr.rs b/src/component/cyfs-group/src/storage/group_shell_mgr.rs index ae2ff5ecc..e1f03ba55 100644 --- a/src/component/cyfs-group/src/storage/group_shell_mgr.rs +++ b/src/component/cyfs-group/src/storage/group_shell_mgr.rs @@ -254,6 +254,10 @@ impl GroupShellManager { .groups_by_version .insert(group.version(), cached_group.clone()); } + + if group_shell_id.is_none() && cache.latest_shell_id == latest_shell_id { + cache.latest_shell_id = shell_id; + } } Ok(group) diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index db214673e..da3ae4e25 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -667,6 +667,10 @@ impl GroupStorage { Ok(is_finished) } + pub fn max_round(&self) -> u64 { + self.block_with_max_round().map_or(0, |b| b.round()) + } + pub fn block_with_max_round(&self) -> Option { let mut max_round = 0; let mut max_block = None; From 7b9fddc19c76e4c088d5f69ab8b6ab4d9c26f785 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 25 Apr 2023 17:25:19 +0800 Subject: [PATCH 546/553] Debug ok for add oods. --- .../src/group/group_consensus_block.rs | 5 +- .../src/consensus/hotstuff/hotstuff.rs | 258 ++++++++++++------ .../src/consensus/vote/committee.rs | 3 +- .../cyfs-group/src/storage/group_storage.rs | 26 +- .../cyfs-stack/src/stack/group_non_driver.rs | 10 +- src/tests/group-example/src/main.rs | 94 +++++-- 6 files changed, 278 insertions(+), 118 deletions(-) diff --git a/src/component/cyfs-core/src/group/group_consensus_block.rs b/src/component/cyfs-core/src/group/group_consensus_block.rs index 4c2490d59..c967dcb41 100644 --- a/src/component/cyfs-core/src/group/group_consensus_block.rs +++ b/src/component/cyfs-core/src/group/group_consensus_block.rs @@ -320,7 +320,10 @@ impl GroupConsensusBlockObject for GroupConsensusBlock { .last() .map_or(true, |p| p.result_state == desc.result_state_id); - if is_result_state_match && body.hash() == desc.body_hash { + if is_result_state_match + && self.0.desc().owner().is_some() + && body.hash() == desc.body_hash + { self.1 .0.store(BLOCK_CHECK_STATE_SUCC, Ordering::SeqCst); true } else { diff --git a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs index e826bafc9..6ec5909f2 100644 --- a/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs +++ b/src/component/cyfs-group/src/consensus/hotstuff/hotstuff.rs @@ -20,7 +20,7 @@ use futures::FutureExt; use itertools::Itertools; use crate::{ - consensus::synchronizer::Synchronizer, + consensus::{proposal, synchronizer::Synchronizer}, dec_state::{CallReplyNotifier, CallReplyWaiter, StatePusher}, helper::Timer, storage::GroupShellManager, @@ -410,7 +410,7 @@ impl HotstuffRunner { { // check leader let leader_owner = self - .get_leader_owner(Some(block.group_shell_id()), block.round()) + .get_leader_owner(Some(block.group_shell_id()), block.round(), Some(&remote)) .await?; if &leader_owner != block.owner() { @@ -458,6 +458,42 @@ impl HotstuffRunner { block.block_id() ); + { + // 1. verify the results for proposals by DecApp + // 2. rebuild the result-state in on_verify by DecApp + // TODO: + // We can accept the block only for signatures enough without verify from `DecApp`. + // The `QC` is valuable for confirm the previous block. + // But we should not make a vote to the block not verified by `DecApp`. + // So we should only verify the block from `DecApp` before it will be voted, not here. + // But I cannot download the result-state with downloading from remote, + // so I need to verify it here to generate the result-state one by one in the `DecApp.on_verify`. + // If we can download the result-state tree to rebuild it, we can remove the code in this scope. + let mut proposals = HashMap::default(); + self + .non_driver + .load_all_proposals_for_block(block, &mut proposals) + .await.map_err(|err| { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for load proposals failed {:?}", + self, + block.block_id(), + err + ); + err + })?; + + self.check_block_proposal_result_state_by_app(block, &proposals, &prev_block, &remote) + .await + .map_err(|err| { + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for app verify failed {:?}", + self, + block.block_id(), + err); + err + })?; + } + self.synchronizer.pop_link_from(block); self.process_qc(block.qc()).await; @@ -531,7 +567,7 @@ impl HotstuffRunner { { // TODO // try rebuild the result-state for prev-block, it'll unreachable usually except something broken. - // if we can successfully rebuild the result-state in the future, we can remove this part. + // if we can successfully rebuild the result-state in the future, we can remove the code in this part. match prev_block.prev_block_id() { Some(prev_prev_block_id) => { let prev_prev_block = @@ -543,12 +579,13 @@ impl HotstuffRunner { let mut prev_proposals = HashMap::new(); for proposal_ex_info in prev_block.proposals() { + // TODO: Need a method to allow access in `Group`, Now only get from the owner(AccessString::full()) let proposal = self .non_driver - .get_proposal(&proposal_ex_info.proposal, Some(remote)) + .get_proposal(&proposal_ex_info.proposal, Some(prev_block.owner())) .await.map_err(|err| { - log::warn!("[hotstuff] local: {:?}, rebuild of prev-prev-block({:?}) failed, get proposal({}) failed {:?}." - , self, prev_prev_block_id, proposal_ex_info.proposal, err); + log::warn!("[hotstuff] local: {:?}, rebuild of prev-prev-block({:?}) failed, get proposal({}) from {} failed {:?}." + , self, prev_prev_block_id, proposal_ex_info.proposal, remote, err); err })?; prev_proposals.insert(proposal_ex_info.proposal, proposal); @@ -656,10 +693,11 @@ impl HotstuffRunner { &self, group_shell_id: Option<&ObjectId>, round: u64, + remote: Option<&ObjectId>, ) -> BuckyResult { let leader = self .committee - .get_leader(group_shell_id, round) + .get_leader(group_shell_id, round, remote) .await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader from group {:?} with round {} failed, {:?}.", @@ -757,40 +795,7 @@ impl HotstuffRunner { block.height() ); - let fetch_height_immediate = self.store.header_height() + 3; - if block.height() <= fetch_height_immediate { - // little blocks, get them from remote immediately. - self.sync_to_block(block.clone(), remote).await; - } else { - // large blocks, notify remote to push. - log::debug!( - "[hotstuff] local: {:?}, will sync blocks from height({}) to height({}). block.round={}, remote: {}", - self, - self.store.max_height(), - block.height(), - block.round(), - remote - ); - - if self.store.max_height() + 1 <= fetch_height_immediate - 1 { - self.network_sender - .post_message( - HotstuffMessage::SyncRequest( - SyncBound::Height(self.store.max_height() + 1), - SyncBound::Height(fetch_height_immediate - 1), - ), - self.rpath.clone(), - &remote, - ) - .await; - } - - self.synchronizer.push_outorder_block( - block.clone(), - fetch_height_immediate, - remote, - ); - } + self.sync_to_block(block, remote).await; Err(Ok(())) } @@ -828,6 +833,7 @@ impl HotstuffRunner { block.round(), block.height(), ); + return Err(BuckyError::new(BuckyErrorCode::Expired, "block expired")); } @@ -845,6 +851,7 @@ impl HotstuffRunner { block.height(), block.round() ); + return Err(err); } } @@ -882,7 +889,7 @@ impl HotstuffRunner { self, block.block_id() ); - return self.process_block_qc(qc, block).await; + return self.process_block_qc(qc, block, &remote).await; } VoteThresholded::None => {} } @@ -914,7 +921,7 @@ impl HotstuffRunner { let next_leader = self .committee - .get_leader(None, self.round + 1) + .get_leader(None, self.round + 1, None) .await .map_err(|err| { log::warn!( @@ -973,7 +980,7 @@ impl HotstuffRunner { self.cleanup_proposal(new_header_block).await; log::debug!( - "[hotstuff] local: {:?}, process_block-step1 {:?}", + "[hotstuff] local: {:?}, on_new_block_commit-step1 {:?}", self, qc_qc_block.block_id() ); @@ -989,7 +996,7 @@ impl HotstuffRunner { .await; log::debug!( - "[hotstuff] local: {:?}, process_block-step2 {:?}", + "[hotstuff] local: {:?}, on_new_block_commit-step2 {:?}", self, qc_qc_block.block_id() ); @@ -1020,7 +1027,7 @@ impl HotstuffRunner { } log::debug!( - "[hotstuff] local: {:?}, process_block-step3 {:?}", + "[hotstuff] local: {:?}, on_new_block_commit-step3 {:?}", self, qc_qc_block.block_id() ); @@ -1179,16 +1186,15 @@ impl HotstuffRunner { } let mut only_rebuild_result_state = false; - if self.max_quorum_round >= self.store.max_round() { + if self.max_quorum_height >= self.store.max_height() { if let Some(result_state_id) = block.result_state_id() { + // `make_sure_result_state` will rebuild result-state by downloading from remote. if self .make_sure_result_state(result_state_id, &[block.owner(), remote]) .await .is_err() { - // TODO: // download from remote failed, we need to calcute the result-state by the DEC.on_verify - // if we can successfully rebuild the result-state in the future, we can remove this part. only_rebuild_result_state = true; } } @@ -1201,8 +1207,48 @@ impl HotstuffRunner { } } - // round只能逐个递增 + let prev_block = match block.prev_block_id() { + Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { + Ok(block) => Some(block), + Err(_) => { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", + self, + block.block_id(), + block.prev_block_id() + ); + + return None; + } + }, + None => None, + }; + + // select the highest branch to vote. + if block.height() != self.store.max_height() { + log::warn!( + "[hotstuff] local: {:?}, make vote to block {} ignore for higher({}!={}) branch.", + self, + block.block_id(), + block.height(), + self.store.max_height(), + ); + + return None; + } + + // `round` must be increased one by one let qc_round = block.qc().as_ref().map_or(0, |qc| qc.round); + if qc_round != prev_block.as_ref().map_or(0, |p| p.round()) { + log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for qc-round({}) is unmatch with prev-block({}/{:?})", + self, + block.block_id(), + qc_round, + prev_block.as_ref().map_or(0, |p| p.round()), + block.prev_block_id() + ); + return None; + } + let is_valid_round = if block.round() == qc_round + 1 { true } else if let Some(tc) = block.tc() { @@ -1227,22 +1273,6 @@ impl HotstuffRunner { return None; } - let prev_block = match block.prev_block_id() { - Some(prev_block_id) => match self.store.find_block_in_cache(prev_block_id) { - Ok(block) => Some(block), - Err(_) => { - log::warn!("[hotstuff] local: {:?}, make vote to block {} ignore for prev-block {:?} is invalid", - self, - block.block_id(), - block.prev_block_id() - ); - - return None; - } - }, - None => None, - }; - log::debug!( "[hotstuff] local: {:?} make vote {} step 1", self, @@ -1332,6 +1362,8 @@ impl HotstuffRunner { block.block_id() ); + // 1. verify the results for proposals by DecApp + // 2. rebuild the result-state in on_verify by DecApp if let Err(err) = self .check_block_proposal_result_state_by_app(block, &proposals, &prev_block, remote) .await @@ -1345,6 +1377,12 @@ impl HotstuffRunner { return None; } + if only_rebuild_result_state { + log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{} rebuild only.", + self, block.block_id(), block.round(), self.max_quorum_round, self.round); + return None; + } + log::debug!( "[hotstuff] local: {:?}, make-vote before sign {}, round: {}", self, @@ -1352,12 +1390,6 @@ impl HotstuffRunner { block.round() ); - if only_rebuild_result_state { - log::debug!("[hotstuff] local: {:?}, make vote ignore for the block {}/{} has enough votes {}/{} rebuild only.", - self, block.block_id(), block.round(), self.max_quorum_round, self.round); - return None; - } - let vote = match HotstuffBlockQCVote::new(block, self.local_device_id, &self.signer).await { Ok(vote) => { log::debug!( @@ -1528,7 +1560,7 @@ impl HotstuffRunner { if is_prev_none { "None" } else { "Some" } ); - self.process_block_qc(qc, &block).await?; + self.process_block_qc(qc, &block, &remote).await?; } else if vote.round > self.round && is_prev_none { self.fetch_block(&vote.block_id, remote).await?; } @@ -1539,6 +1571,7 @@ impl HotstuffRunner { &mut self, qc: HotstuffBlockQC, prev_block: &GroupConsensusBlock, + remote: &ObjectId, ) -> BuckyResult<()> { let qc_block_id = qc.block_id; let qc_round = qc.round; @@ -1552,7 +1585,7 @@ impl HotstuffRunner { self.update_max_quorum_height(prev_block.height()); - let new_leader = self.committee.get_leader(None, self.round).await.map_err(|err| { + let new_leader = self.committee.get_leader(None, self.round, Some(remote)).await.map_err(|err| { log::warn!( "[hotstuff] local: {:?}, get leader for vote-qc({}/{}/{:?}) with round {} failed {:?}", self, @@ -1681,12 +1714,16 @@ impl HotstuffRunner { })?; if let Some(tc) = tc { - self.process_timeout_qc(tc).await?; + self.process_timeout_qc(tc, &remote).await?; } Ok(()) } - async fn process_timeout_qc(&mut self, tc: HotstuffTimeout) -> BuckyResult<()> { + async fn process_timeout_qc( + &mut self, + tc: HotstuffTimeout, + remote: &ObjectId, + ) -> BuckyResult<()> { log::debug!( "[hotstuff] local: {:?}, process_timeout_qc: {:?}, voter: {:?}.", self, @@ -1715,7 +1752,7 @@ impl HotstuffRunner { let new_leader = self .committee - .get_leader(None, self.round) + .get_leader(None, self.round, Some(remote)) .await .map_err(|err| { log::warn!( @@ -1839,7 +1876,7 @@ impl HotstuffRunner { let new_leader = self .committee - .get_leader(None, self.round) + .get_leader(None, self.round, Some(&remote)) .await .map_err(|err| { log::warn!( @@ -2372,7 +2409,7 @@ impl HotstuffRunner { log::debug!("[hotstuff] local: {:?}, handle_proposal_waiting", self); assert_eq!( - self.committee.get_leader(None, self.round).await?, + self.committee.get_leader(None, self.round, None).await?, self.local_device_id ); @@ -2409,7 +2446,66 @@ impl HotstuffRunner { Ok(()) } - async fn sync_to_block( + async fn sync_to_block(&mut self, latest_block: &GroupConsensusBlock, remote: ObjectId) { + let fetch_height_immediate = self.store.header_height() + 3; + + if latest_block.height() <= fetch_height_immediate { + // little blocks, get them from remote immediately. + if self + .sync_to_block_by_get_prev(latest_block.clone(), remote) + .await + .is_err() + { + self.network_sender + .post_message( + HotstuffMessage::SyncRequest( + SyncBound::Height(self.store.header_height() + 1), + SyncBound::Height(latest_block.height() - 1), + ), + self.rpath.clone(), + &remote, + ) + .await; + + self.synchronizer.push_outorder_block( + latest_block.clone(), + fetch_height_immediate, + remote, + ); + } + } else { + // large blocks, notify remote to push. + log::debug!( + "[hotstuff] local: {:?}, will sync blocks from height({}) to height({}). block.round={}, remote: {}", + self, + self.store.max_height(), + latest_block.height(), + latest_block.round(), + remote + ); + + if self.store.max_height() + 1 <= fetch_height_immediate - 1 { + self.network_sender + .post_message( + HotstuffMessage::SyncRequest( + SyncBound::Height(self.store.max_height() + 1), + SyncBound::Height(fetch_height_immediate - 1), + ), + self.rpath.clone(), + &remote, + ) + .await; + } + + self.synchronizer.push_outorder_block( + latest_block.clone(), + fetch_height_immediate, + remote, + ); + } + } + + async fn sync_to_block_by_get_prev( &mut self, latest_block: GroupConsensusBlock, remote: ObjectId, @@ -2658,7 +2754,7 @@ impl HotstuffRunner { }); self.timer.reset(duration); - if let Ok(leader) = self.committee.get_leader(None, self.round).await { + if let Ok(leader) = self.committee.get_leader(None, self.round, None).await { if leader == self.local_device_id { match max_round_block { Some(max_round_block) diff --git a/src/component/cyfs-group/src/consensus/vote/committee.rs b/src/component/cyfs-group/src/consensus/vote/committee.rs index 5f96f6158..26b0e1bf4 100644 --- a/src/component/cyfs-group/src/consensus/vote/committee.rs +++ b/src/component/cyfs-group/src/consensus/vote/committee.rs @@ -68,12 +68,13 @@ impl Committee { &self, group_shell_id: Option<&ObjectId>, round: u64, + remote: Option<&ObjectId>, ) -> BuckyResult { let group = if group_shell_id.is_none() { self.shell_mgr.group().0 } else { self.shell_mgr - .get_group(&self.group_id, group_shell_id, None) + .get_group(&self.group_id, group_shell_id, remote) .await? }; let i = (round % (group.ood_list().len() as u64)) as usize; diff --git a/src/component/cyfs-group/src/storage/group_storage.rs b/src/component/cyfs-group/src/storage/group_storage.rs index da3ae4e25..371986cdc 100644 --- a/src/component/cyfs-group/src/storage/group_storage.rs +++ b/src/component/cyfs-group/src/storage/group_storage.rs @@ -145,13 +145,14 @@ impl GroupStorage { } pub fn max_height(&self) -> u64 { + let mut max_height = self.header_height(); if self.cache.prepares.len() > 0 { - self.header_height() + 2 - } else if self.cache.pre_commits.len() > 0 { - self.header_height() + 1 - } else { - self.header_height() + max_height += 1; + } + if self.cache.pre_commits.len() > 0 { + max_height += 1; } + max_height } pub fn first_block(&self) -> &Option { @@ -508,7 +509,12 @@ impl GroupStorage { ); let header_height = self.header_height(); - if block.height() <= header_height { + let header_round = self.header_round(); + let qc_round = block.qc().as_ref().map_or(0, |q| q.round); + if block.height() <= header_height + || block.round() <= header_round + || qc_round < header_round + { return Ok(BlockLinkState::Expired); } @@ -538,7 +544,7 @@ impl GroupStorage { if prev_block.height() + 1 != block.height() { return Err(BuckyError::new(BuckyErrorCode::Failed, "height error")); } else if prev_block.round() >= block.round() { - return Err(BuckyError::new(BuckyErrorCode::Failed, "round error")); + return Err(BuckyError::new(BuckyErrorCode::Failed, "qc round to large")); } else { Some(prev_block) } @@ -561,6 +567,12 @@ impl GroupStorage { } }; + if prev_block.as_ref().map_or(0, |b| b.round()) + != block.qc().as_ref().map_or(0, |q| q.round) + { + return Err(BuckyError::new(BuckyErrorCode::Failed, "qc round error")); + } + log::debug!( "[group storage] {} block_linked {} step3", self.local_device_id, diff --git a/src/component/cyfs-stack/src/stack/group_non_driver.rs b/src/component/cyfs-stack/src/stack/group_non_driver.rs index 5f00c6640..2019f1607 100644 --- a/src/component/cyfs-stack/src/stack/group_non_driver.rs +++ b/src/component/cyfs-stack/src/stack/group_non_driver.rs @@ -38,7 +38,8 @@ impl GroupNONDriver { from ); - self.non_service + let resp = self + .non_service .get_object(NONGetObjectInputRequest { common: NONInputRequestCommon { req_path: None, @@ -61,8 +62,11 @@ impl GroupNONDriver { object_id: object_id.clone(), inner_path: None, }) - .await - .map(|resp| resp.object) + .await?; + + // TODO: only set the permissions + self.put_object_impl(dec_id, resp.object.clone()).await; + Ok(resp.object) } async fn put_object_impl(&self, dec_id: &ObjectId, obj: NONObjectInfo) -> BuckyResult<()> { diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index d3284d6ce..481989ffc 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -98,7 +98,7 @@ mod Common { lazy_static::lazy_static! { pub static ref EXAMPLE_APP_NAME: String = "group-example".to_string(); - pub static ref EXAMPLE_RPATH: String = "rpath-example".to_string(); + pub static ref EXAMPLE_RPATH: String = "rpath-example-7".to_string(); pub static ref EXAMPLE_VALUE_PATH: String = "/root/folder1/folder2/value".to_string(); pub static ref STATE_PATH_SEPARATOR: String = "/".to_string(); } @@ -880,27 +880,42 @@ mod GroupDecService { }; let result_state_id = { - state_op_env - .set_with_path(EXAMPLE_VALUE_PATH.as_str(), &result_value, prev_value, true) - .await - .expect( - format!( - "set_with_path {:?} from {:?} to {} failed", - EXAMPLE_VALUE_PATH.as_str(), - prev_value, - result_value + let mut obj_map_id = result_value; + for key in EXAMPLE_VALUE_PATH.split('/').rev() { + let key: &str = key.into(); + if key.is_empty() { + continue; + } + + let state_op_env = object_map_processor + .create_single_op_env(Some(RootStateOpEnvAccess { + path: "".to_string(), + access: AccessPermissions::Full, + })) + .await + .expect(format!("create_sub_tree_op_env failed").as_str()); + + state_op_env + .create_new_with_option( + ObjectMapSimpleContentType::Map, + &CreateObjectMapOption::new_with_owner( + proposal.rpath().group_id().clone(), + ), ) - .as_str(), - ); - state_op_env.commit().await.expect( - format!( - "commit {:?} from {:?} to {} failed", - EXAMPLE_VALUE_PATH.as_str(), - prev_value, - result_value - ) - .as_str(), - ) + .await + .expect(format!("create_new {} failed", key).as_str()); + + state_op_env + .insert_with_key(key, &obj_map_id) + .await + .expect(format!("insert with key {} failed", key).as_str()); + + obj_map_id = state_op_env + .commit() + .await + .expect(format!("commit key {} failed", key).as_str()); + } + obj_map_id }; let receipt = { @@ -929,7 +944,7 @@ mod GroupDecService { */ Ok(ExecuteResult { context, - result_state_id: Some(result_state_id.root), + result_state_id: Some(result_state_id), receipt, }) } @@ -945,12 +960,23 @@ mod GroupDecService { * let is_same = (execute_result.result_state_id, execute_result.return_object) * == prev_state_id + proposal + execute_result.context */ + + log::info!( + "verify({}) enter, expect: prev-state: {:?}, {:?}/{:?}/{:?}", + self.stack.local_device_id(), + prev_state_id, + execute_result.result_state_id, + execute_result.context.as_ref().map(|v| v.to_hex()), + execute_result.receipt.as_ref().map(|r| r.object_id), + ); + let result = self .execute(proposal, prev_state_id, object_map_processor) .await?; log::info!( - "verify expect: prev-state: {:?}, {:?}/{:?}/{:?}, got: {:?}/{:?}/{:?}", + "verify({}) expect: prev-state: {:?}, {:?}/{:?}/{:?}, got: {:?}/{:?}/{:?}", + self.stack.local_device_id(), prev_state_id, execute_result.result_state_id, execute_result.context.as_ref().map(|v| v.to_hex()), @@ -981,8 +1007,26 @@ mod GroupDecService { prev_state_id: &Option, object_map_processor: &dyn GroupObjectMapProcessor, ) -> BuckyResult { - self.execute(proposal, prev_state_id, object_map_processor) - .await + log::info!( + "execute({}) enter, proposal: {}, prev-state: {:?}", + self.stack.local_device_id(), + proposal.desc().object_id(), + prev_state_id, + ); + + let result = self + .execute(proposal, prev_state_id, object_map_processor) + .await?; + + log::info!( + "execute({}), proposal: {}, prev-state: {:?}, result: {:?}", + self.stack.local_device_id(), + proposal.desc().object_id(), + prev_state_id, + result.result_state_id, + ); + + Ok(result) } async fn on_verify( From a0620971ebeb98bfd0559f40f8d210a1a7f21642 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Fri, 12 May 2023 18:18:04 +0800 Subject: [PATCH 547/553] Adapt the parameters --- src/component/cyfs-backup/src/state_backup/roots.rs | 2 +- src/tests/group-example/src/main.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/component/cyfs-backup/src/state_backup/roots.rs b/src/component/cyfs-backup/src/state_backup/roots.rs index a14fd766f..061034244 100644 --- a/src/component/cyfs-backup/src/state_backup/roots.rs +++ b/src/component/cyfs-backup/src/state_backup/roots.rs @@ -37,7 +37,7 @@ impl RootObjectCategoryManager { list.push(item); let item = RootObjectCategory { - object_type: ObjectTypeCode::SimpleGroup.to_u16(), + object_type: ObjectTypeCode::Group.to_u16(), ref_depth: 0, }; list.push(item); diff --git a/src/tests/group-example/src/main.rs b/src/tests/group-example/src/main.rs index 481989ffc..a56ebdc64 100644 --- a/src/tests/group-example/src/main.rs +++ b/src/tests/group-example/src/main.rs @@ -453,6 +453,7 @@ mod Common { known_passive_pn: vec![], udp_sn_only: None, sn_mode: SNMode::Normal, + ping_interval: None, }; let stack_param = CyfsStackParams { From da2337f50d3a5fd6b672bb31b6b48c3875866054 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 13 May 2023 11:20:17 +0800 Subject: [PATCH 548/553] Remove StandardObject::SimpleGroup and StandardObject::Org --- src/component/cyfs-base/src/codec/format.rs | 4 ---- src/component/cyfs-base/src/objects/any.rs | 4 ---- .../cyfs-base/src/objects/standard.rs | 18 ------------------ src/tools/desc-tool/src/sign.rs | 4 ---- 4 files changed, 30 deletions(-) diff --git a/src/component/cyfs-base/src/codec/format.rs b/src/component/cyfs-base/src/codec/format.rs index a13a032fb..4afc0874d 100644 --- a/src/component/cyfs-base/src/codec/format.rs +++ b/src/component/cyfs-base/src/codec/format.rs @@ -494,10 +494,6 @@ impl ObjectFormat for StandardObject { StandardObject::Action(o) => o.format_json(), StandardObject::ObjectMap(o) => o.format_json(), StandardObject::Contract(o) => o.format_json(), - StandardObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } } } diff --git a/src/component/cyfs-base/src/objects/any.rs b/src/component/cyfs-base/src/objects/any.rs index 7bc835c1a..169d00249 100644 --- a/src/component/cyfs-base/src/objects/any.rs +++ b/src/component/cyfs-base/src/objects/any.rs @@ -26,10 +26,6 @@ macro_rules! match_any_obj { StandardObject::Action($o) => $body, StandardObject::ObjectMap($o) => $body, StandardObject::Contract($o) => $body, - StandardObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - StandardObject::Org => panic!("Org is deprecated, you can use the Group."), }, AnyNamedObject::Core($o) => $body, AnyNamedObject::DECApp($o) => $body, diff --git a/src/component/cyfs-base/src/objects/standard.rs b/src/component/cyfs-base/src/objects/standard.rs index 6d84b31c4..de2d5fffc 100644 --- a/src/component/cyfs-base/src/objects/standard.rs +++ b/src/component/cyfs-base/src/objects/standard.rs @@ -4,8 +4,6 @@ use crate::*; pub enum StandardObject { Device(Device), People(People), - SimpleGroup, - Org, AppGroup(AppGroup), UnionAccount(UnionAccount), ChunkId(ChunkId), @@ -38,10 +36,6 @@ macro_rules! match_standard_obj { StandardObject::Action($o) => $body, StandardObject::ObjectMap($o) => $body, StandardObject::Contract($o) => $body, - StandardObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } }; } @@ -269,10 +263,6 @@ impl StandardObject { Self::ChunkId(_) => { unreachable!(); } - Self::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - Self::Org => panic!("Org is deprecated, you can use the Group."), } } } @@ -294,10 +284,6 @@ impl RawEncode for StandardObject { StandardObject::Action(o) => o.raw_measure(purpose), StandardObject::ObjectMap(o) => o.raw_measure(purpose), StandardObject::Contract(o) => o.raw_measure(purpose), - StandardObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } } @@ -321,10 +307,6 @@ impl RawEncode for StandardObject { StandardObject::Action(o) => o.raw_encode(buf, purpose), StandardObject::ObjectMap(o) => o.raw_encode(buf, purpose), StandardObject::Contract(o) => o.raw_encode(buf, purpose), - StandardObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - StandardObject::Org => panic!("Org is deprecated, you can use the Group."), } } } diff --git a/src/tools/desc-tool/src/sign.rs b/src/tools/desc-tool/src/sign.rs index 05589fa1b..e44d42722 100644 --- a/src/tools/desc-tool/src/sign.rs +++ b/src/tools/desc-tool/src/sign.rs @@ -78,10 +78,6 @@ macro_rules! match_any_obj_mut { StandardObject::Tx($o) => $body, StandardObject::Action($o) => $body, StandardObject::ObjectMap($o) => $body, - StandardObject::SimpleGroup => { - panic!("SimpleGroup is deprecated, you can use the Group.") - } - StandardObject::Org => panic!("Org is deprecated, you can use the Group."), }, AnyNamedObject::Core($o) => $body, AnyNamedObject::DECApp($o) => $body, From b0419e7db559e98e203dbfcd533843211b018b35 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 13 May 2023 11:25:34 +0800 Subject: [PATCH 549/553] Use `increase_update_time` to ensure that `update-time` is incrementally updated. --- src/tools/desc-tool/src/modify.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/desc-tool/src/modify.rs b/src/tools/desc-tool/src/modify.rs index d3bcb6f8b..c165e5233 100644 --- a/src/tools/desc-tool/src/modify.rs +++ b/src/tools/desc-tool/src/modify.rs @@ -433,7 +433,7 @@ fn modify_group_desc(group: &mut Group, matches: &ArgMatches) -> BuckyResult<()> .body_mut() .as_mut() .unwrap() - .set_update_time(bucky_time_now()); + .increase_update_time(bucky_time_now()); group.signs_mut().clear_body_signs(); From beec9d04e721a255fdc3cc6a6522a4d774cf3480 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Sat, 13 May 2023 20:40:54 +0800 Subject: [PATCH 550/553] rename some identify --- src/component/cyfs-group-lib/src/requestor.rs | 4 ++-- src/component/cyfs-stack/src/group_api/acl/group_acl.rs | 4 ++-- .../cyfs-stack/src/group_api/service/group_handler.rs | 2 +- .../cyfs-stack/src/group_api/service/group_listener.rs | 4 ++-- src/component/cyfs-stack/src/resolver/device_manager.rs | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index af17be0c6..ac9f48cba 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -91,7 +91,7 @@ impl GroupRequestor { ) -> BuckyResult { log::info!("will start group service: {:?}", rpath); - let url = self.service_url.join("start-service").unwrap(); + let url = self.service_url.join("service").unwrap(); let mut http_req = Request::new(Method::Put, url); let req = GroupStartServiceOutputRequest { @@ -154,7 +154,7 @@ impl GroupRequestor { proposal_id ); - let url = self.service_url.join("push-proposal").unwrap(); + let url = self.service_url.join("proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs index 0e789c023..873c253dd 100644 --- a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -46,7 +46,7 @@ impl GroupInputProcessor for GroupAclInnerInputProcessor { req_common: NONInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - self.check_local_zone_permit("group.start-service", &req_common.source)?; + self.check_local_zone_permit("group.service", &req_common.source)?; self.next.start_service(req_common, req).await } @@ -55,7 +55,7 @@ impl GroupInputProcessor for GroupAclInnerInputProcessor { req_common: NONInputRequestCommon, req: GroupProposal, ) -> BuckyResult { - self.check_local_zone_permit("group.push-proposal", &req_common.source)?; + self.check_local_zone_permit("group.proposal", &req_common.source)?; self.next.push_proposal(req_common, req).await } } diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs index 182cc2f2d..d2c2f298b 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_handler.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -49,7 +49,7 @@ impl GroupRequestHandler { Ok(ret) } - // group/start-service + // group/service pub async fn process_start_service( &self, req: NONInputHttpRequest, diff --git a/src/component/cyfs-stack/src/group_api/service/group_listener.rs b/src/component/cyfs-stack/src/group_api/service/group_listener.rs index 47be52927..fc5a51874 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_listener.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_listener.rs @@ -49,14 +49,14 @@ impl GroupRequestHandlerEndpoint { handler: &GroupRequestHandler, server: &mut tide::Server<()>, ) { - server.at("/group/start-service").put(Self::new( + server.at("/group/service").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::StartService, handler.clone(), )); - server.at("group/push-proposal").put(Self::new( + server.at("/group/proposal").put(Self::new( zone_manager.clone(), protocol.to_owned(), GroupRequestType::PushProposal, diff --git a/src/component/cyfs-stack/src/resolver/device_manager.rs b/src/component/cyfs-stack/src/resolver/device_manager.rs index adf57f608..650f4eff7 100644 --- a/src/component/cyfs-stack/src/resolver/device_manager.rs +++ b/src/component/cyfs-stack/src/resolver/device_manager.rs @@ -127,7 +127,7 @@ impl DeviceInfoManagerImpl { } } - async fn verfiy_group_own_signs( + async fn verfiy_group( &self, object_id: &ObjectId, object: &Arc, @@ -472,7 +472,7 @@ impl DeviceCache for DeviceInfoManager { object: &Arc, ) -> BuckyResult<()> { if ObjectTypeCode::Group == object_id.obj_type_code() { - self.0.verfiy_group_own_signs(object_id, object).await + self.0.verfiy_group(object_id, object).await } else { self.0.verfiy_single_own_signs(object_id, object).await } From ceada206ca1201e4e1e4b753b3f56019f8351669 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Mon, 15 May 2023 20:59:39 +0800 Subject: [PATCH 551/553] Translate chinese to english and remove redundant parameters --- src/component/cyfs-group-lib/readme.md | 14 ---- src/component/cyfs-group-lib/src/requestor.rs | 13 +-- .../cyfs-group/src/statepath/design.md | 82 ++++++------------- 3 files changed, 27 insertions(+), 82 deletions(-) delete mode 100644 src/component/cyfs-group-lib/readme.md diff --git a/src/component/cyfs-group-lib/readme.md b/src/component/cyfs-group-lib/readme.md deleted file mode 100644 index fd211a02c..000000000 --- a/src/component/cyfs-group-lib/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -# 模块说明 - -支持群组产权数据相关需求 - -# 方案简介 - -1. 抛弃目前的 SimpleGroup 标准对象,提供一个可以包含多个 People 对象的 Group 标准对象,Group 对象可以支持动态配置相关属性(成员、权力等) -2. 提供 GroupState 结构,在 Group 的各成员 OOD 上保存其所属 Group 的 r-path 状态信息,类似个人产权的 RootState 设计,但更新机制不同,需要 Group 成员之间通过共识协议保持一致 -3. 共识协议目前采用 BFT(HotStuff?) -4. 向 Group 发起的请求(Post/Get),能自动寻址到其成员,并投递 -5. 对从 Group 获取到的信息,Group 提供方法验证(主要是验证签名的过程) -6. 支持 cyfs://r/${groupid}/${decid}/${r-path} -7. 提供对 GroupState 的访问权限控制 ACL -8. 提供操作 Group 的权限配置 Group-ACL diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index ac9f48cba..35d7a36a2 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -42,12 +42,7 @@ impl GroupRequestor { Arc::new(Box::new(self.clone())) } - fn encode_common_headers( - &self, - action: NONAction, - com_req: &NONOutputRequestCommon, - http_req: &mut Request, - ) { + fn encode_common_headers(&self, com_req: &NONOutputRequestCommon, http_req: &mut Request) { let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); @@ -57,8 +52,6 @@ impl GroupRequestor { com_req.req_path.as_deref(), ); - http_req.insert_header(cyfs_base::CYFS_NON_ACTION, action.to_string()); - http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); if let Some(target) = &com_req.target { @@ -99,7 +92,7 @@ impl GroupRequestor { rpath: rpath.to_string(), }; - self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); + self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -157,7 +150,7 @@ impl GroupRequestor { let url = self.service_url.join("proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(NONAction::PutObject, &req_common, &mut http_req); + self.encode_common_headers(&req_common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, diff --git a/src/component/cyfs-group/src/statepath/design.md b/src/component/cyfs-group/src/statepath/design.md index 967f61b48..0c8ab2c36 100644 --- a/src/component/cyfs-group/src/statepath/design.md +++ b/src/component/cyfs-group/src/statepath/design.md @@ -1,72 +1,38 @@ ``` -/--groups // for manager;通过决议以后构造/更新的Group对象放在这里,更新步骤 -| | // 1.得到一个创建/更新一个Group的决议(旧成员一定量的投票+所有新成员签名) -| | // 形成决议的方式可以是合约,也可以是超送用`DEC框架`实现的DEC -| | // 2.跟friend管理一样,用决议设定到系统更新Group信息 -| | // 3.更新Group下所有r-path的本地Group版本,并达成共识;这里主要要同步ood-list -| |--list-->Set -| |--option-->GroupOption -| -|--${group-id} +|--${group-id} // one group | |--${DecId("shells", ${group-id})} | | |--.shells | | |--.latest-->GroupShell // latest version | | |--${group.version}-->GroupShell // add shells for history versions of group -| |--${dec-id} -| |--.dec-state-->ObjectId // for dec;各Group的dec状态放这里 -| | // APP控制的实体状态,通常是个map-id -| | // 最终在APP看到的${r-path}结构是这级物理结构的相对路径 -| | // 其他内部逻辑隐藏掉 -| | // 每个${r-path}管理范围内是串行的 -| | // 不同${r-path}范围内的操作是并行的 -| | // 且不同${r-path}之间是并列的,不能嵌套 -| |--.link // 区块链结构,记录状态变更链条 -| |--${r-path} -| |--users +| |--${dec-id} // one dec for a group +| |--${r-path} +| |--.dec-state-->ObjectId // for dec;the latest state of all groups +| | // one state of a r-path, It's calculated by the app, and it's a map-id in most times +| | // Each state change for same ${r-path} is serial +| | // Each state change for different ${r-path} is parallel +| | // **The process of state change for different ${r-path} should always not be nested, Because the change of each branch will affect the state of the root** +| |--.link // Blockchain for hotstuff, record the state change chain,Most of the time, application developers do not need to pay attention +| |--group-blob-->BLOB(Group) // the latest group, it's store as chunk, so, it'll not be updated by different version +| |--users // info of any user, is useful? | | |--${user-id} | | |--xxx -| |--last-vote-round-->u64 // 最后一次投票的 轮次 -| |--last-qc-->GroupQuorumCertificate // 最后一次被确认的共识证明 +| |--last-vote-round-->u64 // the round that I voted last time +| |--last-qc-->GroupQuorumCertificate | | -| |--range-->(${first_height}, ${header_height}) // 保留的历史block序列号区间 -| |--str(${height})->block +| |--range-->(${first_height}, ${header_height}) // the range retained, we can remove some history +| |--str(${height})->block // commited blocks with any height, QC(Quorum Certificate) by next blocks at least 2 | | -| |--prepares // Prepare状态的block +| |--prepares // prepare blocks, with QC for pre-block(pre-commit/commited), but not QC by any one | | |--${block.id} -| | |--block -| | |--result-state-->ObjectId(result-state) -| |--pre-commits // pre-commit状态的block +| | |--block +| | |--result-state-->ObjectId(result-state) // hold the ref to avoid recycle +| |--pre-commits // pre-commit blocks, with QC for the header block, and is QC by a prepare block | | |--${block.id} -| | |--block -| | |--result-state-->ObjectId(result-state) +| | |--block +| | |--result-state-->ObjectId(result-state) // hold the ref to avoid recycle | | -| |--finish-proposals -| | |--flip-time-->Timestamp // 取block时间戳 -| | |--over-->Set +| |--finish-proposals // The proposal is de-duplicated. Proposals that exceed the timeout period are directly discarded, and those within the timeout period are de-duplicated by the list +| | |--flip-time-->Timestamp // the timestamp of the first block +| | |--recycle-->Set | | |--adding-->Set ``` - -``` -// .group结构 -/--${group-id} - |--ObjectId(.group) - |--.update - |--voting - | |--${proposal-id} - | |--proposal-->GroupUpdateProposal - | |--decides-->Set - |--latest-version-->GroupUpdateProposal // Chunk(Encode(group)) - |--str(version-seq)-->GroupUpdateProposal // Chunk(Encode(group)) - |--str(group-hash)-->GroupUpdateProposal -``` - -member 同步结构 - -``` -|--${/} // config by the DecAPP - |--${group-id} - |--${r-path} - |--state-->ObjectId // the latest state - |--block-->Block // the hightest block - |--qc-->qc-block // the qc for the ${block} -``` From 533e8e73a0abe3a667830693ef71df8988a13fa3 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Tue, 16 May 2023 20:33:30 +0800 Subject: [PATCH 552/553] Remove unusefull fields in RPC --- .../cyfs-group-lib/src/input_request.rs | 18 +++++- .../cyfs-group-lib/src/output_request.rs | 26 ++++++++- src/component/cyfs-group-lib/src/processor.rs | 7 +-- src/component/cyfs-group-lib/src/requestor.rs | 45 +++------------ .../cyfs-stack/src/group/processor.rs | 8 +-- .../cyfs-stack/src/group/transform.rs | 56 ++++++------------- .../cyfs-stack/src/group_api/acl/group_acl.rs | 7 ++- .../group_api/router/group_service_router.rs | 29 ++++------ .../src/group_api/router/local_service.rs | 8 +-- .../src/group_api/service/group_handler.rs | 30 ++-------- 10 files changed, 97 insertions(+), 137 deletions(-) diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index 54df4dda9..c883ca37c 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -1,5 +1,21 @@ +use std::fmt; + use cyfs_base::ObjectId; -use cyfs_lib::NONObjectInfo; +use cyfs_lib::{NONObjectInfo, RequestSourceInfo}; + +#[derive(Clone, Debug)] +pub struct GroupInputRequestCommon { + // the request source info in bundle + pub source: RequestSourceInfo, +} + +impl fmt::Display for GroupInputRequestCommon { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, ", {}", self.source)?; + + Ok(()) + } +} pub struct GroupStartServiceInputRequest { pub group_id: ObjectId, diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index 964abcc4b..293f8bf7e 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -1,6 +1,30 @@ -use cyfs_base::ObjectId; +use std::fmt; + +use cyfs_base::{DeviceId, ObjectId}; use cyfs_lib::NONObjectInfo; +#[derive(Clone, Debug)] +pub struct GroupOutputRequestCommon { + // source dec-id + pub dec_id: Option, +} + +impl GroupOutputRequestCommon { + pub fn new() -> Self { + Self { dec_id: None } + } +} + +impl fmt::Display for GroupOutputRequestCommon { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(dec_id) = &self.dec_id { + write!(f, ", dec_id: {}", dec_id)?; + } + + Ok(()) + } +} + #[derive(Debug)] pub struct GroupStartServiceOutputRequest { pub group_id: ObjectId, diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index 9aec5a354..a9a2edcf7 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -2,10 +2,9 @@ use std::sync::Arc; use cyfs_base::BuckyResult; use cyfs_core::GroupProposal; -use cyfs_lib::NONOutputRequestCommon; use crate::{ - GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, + GroupOutputRequestCommon, GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, }; @@ -13,12 +12,12 @@ use crate::{ pub trait GroupOutputProcessor: Send + Sync { async fn start_service( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult; async fn push_proposal( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupProposal, ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 35d7a36a2..94c93af56 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -2,19 +2,15 @@ use std::sync::Arc; use cyfs_base::{ BuckyError, BuckyResult, JsonCodec, NamedObject, ObjectDesc, ObjectId, RawConvertTo, - CYFS_API_LEVEL, }; use cyfs_core::{GroupProposal, GroupProposalObject}; -use cyfs_lib::{ - HttpRequestorRef, NONAction, NONObjectInfo, NONOutputRequestCommon, NONRequestorHelper, - RequestorHelper, -}; +use cyfs_lib::{HttpRequestorRef, NONObjectInfo, NONRequestorHelper, RequestorHelper}; use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, - GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, + GroupOutputRequestCommon, GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -42,43 +38,20 @@ impl GroupRequestor { Arc::new(Box::new(self.clone())) } - fn encode_common_headers(&self, com_req: &NONOutputRequestCommon, http_req: &mut Request) { + fn encode_common_headers(&self, com_req: &GroupOutputRequestCommon, http_req: &mut Request) { let dec_id = com_req.dec_id.as_ref().unwrap_or(&self.dec_id); http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string()); - - RequestorHelper::encode_opt_header_with_encoding( - http_req, - cyfs_base::CYFS_REQ_PATH, - com_req.req_path.as_deref(), - ); - - http_req.insert_header(CYFS_API_LEVEL, com_req.level.to_string()); - - if let Some(target) = &com_req.target { - http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string()); - } - - if let Some(source) = &com_req.source { - http_req.insert_header(cyfs_base::CYFS_SOURCE, source.to_string()); - } - - http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string()); } - pub(crate) fn make_default_common(dec_id: ObjectId) -> NONOutputRequestCommon { - NONOutputRequestCommon { - req_path: None, - source: None, + pub(crate) fn make_default_common(dec_id: ObjectId) -> GroupOutputRequestCommon { + GroupOutputRequestCommon { dec_id: Some(dec_id), - level: cyfs_lib::NONAPILevel::NOC, - target: None, - flags: 0, } } pub async fn start_service( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, group_id: &ObjectId, rpath: &str, ) -> BuckyResult { @@ -137,7 +110,7 @@ impl GroupRequestor { pub async fn push_proposal( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, proposal: &GroupProposal, ) -> BuckyResult { let proposal_id = proposal.desc().object_id(); @@ -190,7 +163,7 @@ impl GroupRequestor { impl GroupOutputProcessor for GroupRequestor { async fn start_service( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult { GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await @@ -198,7 +171,7 @@ impl GroupOutputProcessor for GroupRequestor { async fn push_proposal( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupProposal, ) -> BuckyResult { GroupRequestor::push_proposal(self, req_common, &req).await diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs index b6fe1544b..8ee37ab63 100644 --- a/src/component/cyfs-stack/src/group/processor.rs +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -1,9 +1,9 @@ use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, }; -use cyfs_lib::*; use std::sync::Arc; @@ -11,13 +11,13 @@ use std::sync::Arc; pub(crate) trait GroupInputProcessor: Sync + Send { async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult; async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult; } diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs index 74ee64c85..ce1ea5584 100644 --- a/src/component/cyfs-stack/src/group/transform.rs +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -1,9 +1,10 @@ use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupOutputProcessor, GroupOutputProcessorRef, GroupPushProposalInputResponse, - GroupPushProposalOutputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, - GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, + GroupInputRequestCommon, GroupOutputProcessor, GroupOutputProcessorRef, + GroupOutputRequestCommon, GroupPushProposalInputResponse, GroupPushProposalOutputResponse, + GroupStartServiceInputRequest, GroupStartServiceInputResponse, GroupStartServiceOutputRequest, + GroupStartServiceOutputResponse, }; use cyfs_lib::*; @@ -22,29 +23,15 @@ impl GroupInputTransformer { Arc::new(ret) } - fn convert_common(common: NONInputRequestCommon) -> NONOutputRequestCommon { - NONOutputRequestCommon { - // 请求路径,可为空 - req_path: common.req_path, - - // 来源DEC + fn convert_common(common: GroupInputRequestCommon) -> GroupOutputRequestCommon { + GroupOutputRequestCommon { dec_id: common.source.get_opt_dec().cloned(), - - // 默认行为 - level: common.level, - - // 用以处理默认行为 - target: common.target, - - flags: common.flags, - - source: common.source.zone.device, } } async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { let out_req = GroupStartServiceOutputRequest { @@ -64,7 +51,7 @@ impl GroupInputTransformer { async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult { let out_resp = self @@ -84,7 +71,7 @@ impl GroupInputTransformer { impl GroupInputProcessor for GroupInputTransformer { async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { GroupInputTransformer::start_service(self, req_common, req).await @@ -92,7 +79,7 @@ impl GroupInputProcessor for GroupInputTransformer { async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult { GroupInputTransformer::push_proposal(self, req_common, req).await @@ -106,24 +93,13 @@ pub(crate) struct GroupOutputTransformer { } impl GroupOutputTransformer { - fn convert_common(&self, common: NONOutputRequestCommon) -> NONInputRequestCommon { + fn convert_common(&self, common: GroupOutputRequestCommon) -> GroupInputRequestCommon { let mut source = self.source.clone(); if let Some(dec_id) = common.dec_id { source.set_dec(dec_id); } - NONInputRequestCommon { - // 请求路径,可为空 - req_path: common.req_path, - - // 默认行为 - level: common.level, - - // 用以处理默认行为 - target: common.target, - - flags: common.flags, - + GroupInputRequestCommon { source, } } @@ -138,7 +114,7 @@ impl GroupOutputTransformer { async fn push_proposal( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupProposal, ) -> BuckyResult { let in_resp = self @@ -155,7 +131,7 @@ impl GroupOutputTransformer { async fn start_service( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult { let in_req = GroupStartServiceInputRequest { @@ -178,7 +154,7 @@ impl GroupOutputTransformer { impl GroupOutputProcessor for GroupOutputTransformer { async fn start_service( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult { GroupOutputTransformer::start_service(self, req_common, req).await @@ -186,7 +162,7 @@ impl GroupOutputProcessor for GroupOutputTransformer { async fn push_proposal( &self, - req_common: NONOutputRequestCommon, + req_common: GroupOutputRequestCommon, req: GroupProposal, ) -> BuckyResult { GroupOutputTransformer::push_proposal(self, req_common, req).await diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs index 873c253dd..7698904d4 100644 --- a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -2,7 +2,8 @@ use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, }; use cyfs_lib::*; @@ -43,7 +44,7 @@ impl GroupAclInnerInputProcessor { impl GroupInputProcessor for GroupAclInnerInputProcessor { async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { self.check_local_zone_permit("group.service", &req_common.source)?; @@ -52,7 +53,7 @@ impl GroupInputProcessor for GroupAclInnerInputProcessor { async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult { self.check_local_zone_permit("group.proposal", &req_common.source)?; diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs index 2c1a2841f..c61ad9d83 100644 --- a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -3,10 +3,9 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, DeviceId, ObjectId}; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupPushProposalInputResponse, GroupRequestor, GroupStartServiceInputRequest, - GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputResponse, GroupRequestor, + GroupStartServiceInputRequest, GroupStartServiceInputResponse, }; -use cyfs_lib::NONInputRequestCommon; use crate::{ forward::ForwardProcessorManager, @@ -86,23 +85,19 @@ impl GroupServiceRouter { pub async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - let processor = self - .get_processor(req_common.source.dec, req_common.target.as_ref()) - .await?; + let processor = self.get_processor(req_common.source.dec, None).await?; processor.start_service(req_common, req).await } pub async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult { - let processor = self - .get_processor(req_common.source.dec, req_common.target.as_ref()) - .await?; + let processor = self.get_processor(req_common.source.dec, None).await?; processor.push_proposal(req_common, req).await } } @@ -111,23 +106,19 @@ impl GroupServiceRouter { impl GroupInputProcessor for GroupServiceRouter { async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - let processor = self - .get_processor(req_common.source.dec, req_common.target.as_ref()) - .await?; + let processor = self.get_processor(req_common.source.dec, None).await?; processor.start_service(req_common, req).await } async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult { - let processor = self - .get_processor(req_common.source.dec, req_common.target.as_ref()) - .await?; + let processor = self.get_processor(req_common.source.dec, None).await?; processor.push_proposal(req_common, req).await } } diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs index a6e65420c..e7257a258 100644 --- a/src/component/cyfs-stack/src/group_api/router/local_service.rs +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -4,9 +4,9 @@ use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_group::GroupManager; use cyfs_group_lib::{ - GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, }; -use cyfs_lib::NONInputRequestCommon; use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; @@ -29,7 +29,7 @@ impl LocalGroupService { impl GroupInputProcessor for LocalGroupService { async fn start_service( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { self.group_manager @@ -55,7 +55,7 @@ impl GroupInputProcessor for LocalGroupService { async fn push_proposal( &self, - req_common: NONInputRequestCommon, + req_common: GroupInputRequestCommon, req: GroupProposal, ) -> BuckyResult { let proposal_id = req.desc().object_id(); diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs index d2c2f298b..24d8eef54 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_handler.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -1,9 +1,10 @@ use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, }; -use cyfs_lib::{NONInputRequestCommon, NONRequestorHelper, RequestorHelper}; +use cyfs_lib::{NONRequestorHelper, RequestorHelper}; use crate::{group::GroupInputProcessorRef, non::NONInputHttpRequest}; @@ -20,30 +21,9 @@ impl GroupRequestHandler { // 解析通用header字段 fn decode_common_headers( req: &NONInputHttpRequest, - ) -> BuckyResult { - // req_path - let req_path = RequestorHelper::decode_optional_header_with_utf8_decoding( - &req.request, - cyfs_base::CYFS_REQ_PATH, - )?; - - // 尝试提取flags - let flags: Option = - RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_FLAGS)?; - - // 尝试提取default_action字段 - let level = - RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_API_LEVEL)?; - - // 尝试提取target字段 - let target = RequestorHelper::decode_optional_header(&req.request, cyfs_base::CYFS_TARGET)?; - - let ret = NONInputRequestCommon { - req_path, + ) -> BuckyResult { + let ret = GroupInputRequestCommon { source: req.source.clone(), - level: level.unwrap_or_default(), - target, - flags: flags.unwrap_or(0), }; Ok(ret) From c2bfcaf04513ef711326deb511a052811f550627 Mon Sep 17 00:00:00 2001 From: zhangzhen Date: Thu, 18 May 2023 12:00:31 +0800 Subject: [PATCH 553/553] Combine the `GroupInputRequestCommon` with the request parameters. --- .../cyfs-group-lib/src/input_request.rs | 7 ++ .../cyfs-group-lib/src/output_request.rs | 20 +++++- src/component/cyfs-group-lib/src/processor.rs | 8 +-- .../cyfs-group-lib/src/request_codec.rs | 39 ++++++++++- src/component/cyfs-group-lib/src/requestor.rs | 37 +++++------ .../cyfs-group-lib/src/rpath_service.rs | 23 ++++--- .../cyfs-stack/src/group/processor.rs | 7 +- .../cyfs-stack/src/group/transform.rs | 65 ++++++++----------- .../cyfs-stack/src/group_api/acl/group_acl.rs | 16 ++--- .../group_api/router/group_service_router.rs | 28 ++++---- .../src/group_api/router/local_service.rs | 26 ++++---- .../src/group_api/service/group_handler.rs | 10 +-- 12 files changed, 163 insertions(+), 123 deletions(-) diff --git a/src/component/cyfs-group-lib/src/input_request.rs b/src/component/cyfs-group-lib/src/input_request.rs index c883ca37c..def36929a 100644 --- a/src/component/cyfs-group-lib/src/input_request.rs +++ b/src/component/cyfs-group-lib/src/input_request.rs @@ -1,6 +1,7 @@ use std::fmt; use cyfs_base::ObjectId; +use cyfs_core::GroupProposal; use cyfs_lib::{NONObjectInfo, RequestSourceInfo}; #[derive(Clone, Debug)] @@ -18,12 +19,18 @@ impl fmt::Display for GroupInputRequestCommon { } pub struct GroupStartServiceInputRequest { + pub common: GroupInputRequestCommon, pub group_id: ObjectId, pub rpath: String, } pub struct GroupStartServiceInputResponse {} +pub struct GroupPushProposalInputRequest { + pub common: GroupInputRequestCommon, + pub proposal: GroupProposal, +} + pub struct GroupPushProposalInputResponse { pub object: Option, } diff --git a/src/component/cyfs-group-lib/src/output_request.rs b/src/component/cyfs-group-lib/src/output_request.rs index 293f8bf7e..348d32934 100644 --- a/src/component/cyfs-group-lib/src/output_request.rs +++ b/src/component/cyfs-group-lib/src/output_request.rs @@ -1,6 +1,7 @@ -use std::fmt; +use std::fmt::{self, Debug}; -use cyfs_base::{DeviceId, ObjectId}; +use cyfs_base::{NamedObject, ObjectDesc, ObjectId}; +use cyfs_core::GroupProposal; use cyfs_lib::NONObjectInfo; #[derive(Clone, Debug)] @@ -27,12 +28,27 @@ impl fmt::Display for GroupOutputRequestCommon { #[derive(Debug)] pub struct GroupStartServiceOutputRequest { + pub common: GroupOutputRequestCommon, pub group_id: ObjectId, pub rpath: String, } pub struct GroupStartServiceOutputResponse {} +pub struct GroupPushProposalOutputRequest { + pub common: GroupOutputRequestCommon, + pub proposal: GroupProposal, +} + +impl Debug for GroupPushProposalOutputRequest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("GroupPushProposalOutputRequest") + .field("common", &self.common) + .field("proposal", &self.proposal.desc().object_id()) + .finish() + } +} + pub struct GroupPushProposalOutputResponse { pub object: Option, } diff --git a/src/component/cyfs-group-lib/src/processor.rs b/src/component/cyfs-group-lib/src/processor.rs index a9a2edcf7..dc7962e28 100644 --- a/src/component/cyfs-group-lib/src/processor.rs +++ b/src/component/cyfs-group-lib/src/processor.rs @@ -4,21 +4,19 @@ use cyfs_base::BuckyResult; use cyfs_core::GroupProposal; use crate::{ - GroupOutputRequestCommon, GroupPushProposalOutputResponse, GroupStartServiceOutputRequest, - GroupStartServiceOutputResponse, + GroupOutputRequestCommon, GroupPushProposalOutputRequest, GroupPushProposalOutputResponse, + GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, }; #[async_trait::async_trait] pub trait GroupOutputProcessor: Send + Sync { async fn start_service( &self, - req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult; async fn push_proposal( &self, - req_common: GroupOutputRequestCommon, - req: GroupProposal, + req: GroupPushProposalOutputRequest, ) -> BuckyResult; } diff --git a/src/component/cyfs-group-lib/src/request_codec.rs b/src/component/cyfs-group-lib/src/request_codec.rs index 4c7ddfe88..bc8203626 100644 --- a/src/component/cyfs-group-lib/src/request_codec.rs +++ b/src/component/cyfs-group-lib/src/request_codec.rs @@ -1,13 +1,47 @@ use cyfs_base::{BuckyResult, JsonCodec, JsonCodecHelper}; use serde_json::{Map, Value}; -use crate::{output_request::GroupStartServiceOutputRequest, GroupStartServiceInputRequest}; +use crate::{ + output_request::GroupStartServiceOutputRequest, GroupInputRequestCommon, + GroupOutputRequestCommon, GroupStartServiceInputRequest, +}; + +impl JsonCodec for GroupOutputRequestCommon { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_option_string_field(&mut obj, "dec-id", self.dec_id.as_ref()); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + dec_id: JsonCodecHelper::decode_option_string_field(obj, "dec-id")?, + }) + } +} + +impl JsonCodec for GroupInputRequestCommon { + fn encode_json(&self) -> Map { + let mut obj = Map::new(); + JsonCodecHelper::encode_field(&mut obj, "source", &self.source); + + obj + } + + fn decode_json(obj: &Map) -> BuckyResult { + Ok(Self { + source: JsonCodecHelper::decode_field(obj, "source")?, + }) + } +} impl JsonCodec for GroupStartServiceOutputRequest { fn encode_json(&self) -> Map { let mut obj = Map::new(); JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + JsonCodecHelper::encode_field(&mut obj, "common", &self.common); obj } @@ -16,6 +50,7 @@ impl JsonCodec for GroupStartServiceOutputReques Ok(Self { group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + common: JsonCodecHelper::decode_field(obj, "common")?, }) } } @@ -25,6 +60,7 @@ impl JsonCodec for GroupStartServiceInputRequest let mut obj = Map::new(); JsonCodecHelper::encode_string_field(&mut obj, "group-id", &self.group_id); JsonCodecHelper::encode_string_field(&mut obj, "rpath", self.rpath.as_str()); + JsonCodecHelper::encode_field(&mut obj, "common", &self.common); obj } @@ -33,6 +69,7 @@ impl JsonCodec for GroupStartServiceInputRequest Ok(Self { group_id: JsonCodecHelper::decode_string_field(obj, "group-id")?, rpath: JsonCodecHelper::decode_string_field(obj, "rpath")?, + common: JsonCodecHelper::decode_field(obj, "common")?, }) } } diff --git a/src/component/cyfs-group-lib/src/requestor.rs b/src/component/cyfs-group-lib/src/requestor.rs index 94c93af56..1c9068da4 100644 --- a/src/component/cyfs-group-lib/src/requestor.rs +++ b/src/component/cyfs-group-lib/src/requestor.rs @@ -10,7 +10,8 @@ use http_types::{Method, Request, Url}; use crate::{ output_request::GroupStartServiceOutputRequest, processor::{GroupOutputProcessor, GroupOutputProcessorRef}, - GroupOutputRequestCommon, GroupPushProposalOutputResponse, GroupStartServiceOutputResponse, + GroupOutputRequestCommon, GroupPushProposalOutputRequest, GroupPushProposalOutputResponse, + GroupStartServiceOutputResponse, }; #[derive(Clone)] @@ -51,21 +52,20 @@ impl GroupRequestor { pub async fn start_service( &self, - req_common: GroupOutputRequestCommon, - group_id: &ObjectId, - rpath: &str, + req: GroupStartServiceOutputRequest, ) -> BuckyResult { - log::info!("will start group service: {:?}", rpath); + log::info!("will start group service: {:?}", req.rpath); let url = self.service_url.join("service").unwrap(); let mut http_req = Request::new(Method::Put, url); + self.encode_common_headers(&req.common, &mut http_req); let req = GroupStartServiceOutputRequest { - group_id: group_id.clone(), - rpath: rpath.to_string(), + group_id: req.group_id.clone(), + rpath: req.rpath.to_string(), + common: req.common, }; - self.encode_common_headers(&req_common, &mut http_req); let body = req.encode_string(); http_req.set_body(body); @@ -99,7 +99,7 @@ impl GroupRequestor { let e = RequestorHelper::error_from_resp(&mut resp).await; log::error!( "group start service failed: rpath={:?}, status={}, {}", - rpath, + req.rpath, code, e ); @@ -110,24 +110,23 @@ impl GroupRequestor { pub async fn push_proposal( &self, - req_common: GroupOutputRequestCommon, - proposal: &GroupProposal, + req: GroupPushProposalOutputRequest, ) -> BuckyResult { - let proposal_id = proposal.desc().object_id(); + let proposal_id = req.proposal.desc().object_id(); log::info!( "will push proposal: {:?}, {}", - proposal.rpath(), + req.proposal.rpath(), proposal_id ); let url = self.service_url.join("proposal").unwrap(); let mut http_req = Request::new(Method::Put, url); - self.encode_common_headers(&req_common, &mut http_req); + self.encode_common_headers(&req.common, &mut http_req); NONRequestorHelper::encode_object_info( &mut http_req, - NONObjectInfo::new(proposal_id, proposal.to_vec()?, None), + NONObjectInfo::new(proposal_id, req.proposal.to_vec()?, None), ); let mut resp = self.requestor.request(http_req).await?; @@ -163,17 +162,15 @@ impl GroupRequestor { impl GroupOutputProcessor for GroupRequestor { async fn start_service( &self, - req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult { - GroupRequestor::start_service(self, req_common, &req.group_id, req.rpath.as_str()).await + GroupRequestor::start_service(self, req).await } async fn push_proposal( &self, - req_common: GroupOutputRequestCommon, - req: GroupProposal, + req: GroupPushProposalOutputRequest, ) -> BuckyResult { - GroupRequestor::push_proposal(self, req_common, &req).await + GroupRequestor::push_proposal(self, req).await } } diff --git a/src/component/cyfs-group-lib/src/rpath_service.rs b/src/component/cyfs-group-lib/src/rpath_service.rs index 74f113e3f..03825d416 100644 --- a/src/component/cyfs-group-lib/src/rpath_service.rs +++ b/src/component/cyfs-group-lib/src/rpath_service.rs @@ -7,7 +7,10 @@ use cyfs_lib::{ SingleOpEnvStub, }; -use crate::{ExecuteResult, GroupObjectMapProcessor, GroupRequestor, RPathDelegate}; +use crate::{ + ExecuteResult, GroupObjectMapProcessor, GroupPushProposalOutputRequest, GroupRequestor, + GroupStartServiceOutputRequest, RPathDelegate, +}; struct RPathServiceRaw { rpath: GroupRPath, @@ -31,10 +34,10 @@ impl RPathService { // post http self.0 .requestor - .push_proposal( - GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), - proposal, - ) + .push_proposal(GroupPushProposalOutputRequest { + common: GroupRequestor::make_default_common(proposal.rpath().dec_id().clone()), + proposal: proposal.clone(), + }) .await .map(|resp| resp.object) } @@ -57,11 +60,11 @@ impl RPathService { // post create command self.0 .requestor - .start_service( - GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), - self.rpath().group_id(), - self.rpath().rpath(), - ) + .start_service(GroupStartServiceOutputRequest { + common: GroupRequestor::make_default_common(self.0.rpath.dec_id().clone()), + group_id: self.rpath().group_id().clone(), + rpath: self.rpath().rpath().to_string(), + }) .await .map(|_| {}) } diff --git a/src/component/cyfs-stack/src/group/processor.rs b/src/component/cyfs-stack/src/group/processor.rs index 8ee37ab63..bab6076a5 100644 --- a/src/component/cyfs-stack/src/group/processor.rs +++ b/src/component/cyfs-stack/src/group/processor.rs @@ -1,7 +1,6 @@ use cyfs_base::*; -use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, + GroupPushProposalInputRequest, GroupPushProposalInputResponse, GroupStartServiceInputRequest, GroupStartServiceInputResponse, }; @@ -11,14 +10,12 @@ use std::sync::Arc; pub(crate) trait GroupInputProcessor: Sync + Send { async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult; async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult; } diff --git a/src/component/cyfs-stack/src/group/transform.rs b/src/component/cyfs-stack/src/group/transform.rs index ce1ea5584..7b8f5cfea 100644 --- a/src/component/cyfs-stack/src/group/transform.rs +++ b/src/component/cyfs-stack/src/group/transform.rs @@ -2,8 +2,9 @@ use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ GroupInputRequestCommon, GroupOutputProcessor, GroupOutputProcessorRef, - GroupOutputRequestCommon, GroupPushProposalInputResponse, GroupPushProposalOutputResponse, - GroupStartServiceInputRequest, GroupStartServiceInputResponse, GroupStartServiceOutputRequest, + GroupOutputRequestCommon, GroupPushProposalInputRequest, GroupPushProposalInputResponse, + GroupPushProposalOutputRequest, GroupPushProposalOutputResponse, GroupStartServiceInputRequest, + GroupStartServiceInputResponse, GroupStartServiceOutputRequest, GroupStartServiceOutputResponse, }; use cyfs_lib::*; @@ -31,18 +32,15 @@ impl GroupInputTransformer { async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { let out_req = GroupStartServiceOutputRequest { group_id: req.group_id, rpath: req.rpath, + common: Self::convert_common(req.common), }; - let out_resp = self - .processor - .start_service(Self::convert_common(req_common), out_req) - .await?; + let out_resp = self.processor.start_service(out_req).await?; let resp = GroupStartServiceInputResponse {}; @@ -51,13 +49,14 @@ impl GroupInputTransformer { async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult { - let out_resp = self - .processor - .push_proposal(Self::convert_common(req_common), req) - .await?; + let out_req = GroupPushProposalOutputRequest { + proposal: req.proposal, + common: Self::convert_common(req.common), + }; + + let out_resp = self.processor.push_proposal(out_req).await?; let resp = GroupPushProposalInputResponse { object: out_resp.object, @@ -71,18 +70,16 @@ impl GroupInputTransformer { impl GroupInputProcessor for GroupInputTransformer { async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - GroupInputTransformer::start_service(self, req_common, req).await + GroupInputTransformer::start_service(self, req).await } async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult { - GroupInputTransformer::push_proposal(self, req_common, req).await + GroupInputTransformer::push_proposal(self, req).await } } @@ -99,9 +96,7 @@ impl GroupOutputTransformer { source.set_dec(dec_id); } - GroupInputRequestCommon { - source, - } + GroupInputRequestCommon { source } } pub fn new( @@ -114,13 +109,14 @@ impl GroupOutputTransformer { async fn push_proposal( &self, - req_common: GroupOutputRequestCommon, - req: GroupProposal, + req: GroupPushProposalOutputRequest, ) -> BuckyResult { - let in_resp = self - .processor - .push_proposal(self.convert_common(req_common), req) - .await?; + let in_req = GroupPushProposalInputRequest { + common: self.convert_common(req.common), + proposal: req.proposal, + }; + + let in_resp = self.processor.push_proposal(in_req).await?; let resp = GroupPushProposalOutputResponse { object: in_resp.object, @@ -131,18 +127,15 @@ impl GroupOutputTransformer { async fn start_service( &self, - req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult { let in_req = GroupStartServiceInputRequest { group_id: req.group_id, rpath: req.rpath, + common: self.convert_common(req.common), }; - let in_resp = self - .processor - .start_service(self.convert_common(req_common), in_req) - .await?; + let in_resp = self.processor.start_service(in_req).await?; let resp = GroupStartServiceOutputResponse {}; @@ -154,17 +147,15 @@ impl GroupOutputTransformer { impl GroupOutputProcessor for GroupOutputTransformer { async fn start_service( &self, - req_common: GroupOutputRequestCommon, req: GroupStartServiceOutputRequest, ) -> BuckyResult { - GroupOutputTransformer::start_service(self, req_common, req).await + GroupOutputTransformer::start_service(self, req).await } async fn push_proposal( &self, - req_common: GroupOutputRequestCommon, - req: GroupProposal, + req: GroupPushProposalOutputRequest, ) -> BuckyResult { - GroupOutputTransformer::push_proposal(self, req_common, req).await + GroupOutputTransformer::push_proposal(self, req).await } } diff --git a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs index 7698904d4..585394e6e 100644 --- a/src/component/cyfs-stack/src/group_api/acl/group_acl.rs +++ b/src/component/cyfs-stack/src/group_api/acl/group_acl.rs @@ -2,8 +2,8 @@ use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, - GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputRequest, GroupPushProposalInputResponse, + GroupStartServiceInputRequest, GroupStartServiceInputResponse, }; use cyfs_lib::*; @@ -44,19 +44,17 @@ impl GroupAclInnerInputProcessor { impl GroupInputProcessor for GroupAclInnerInputProcessor { async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - self.check_local_zone_permit("group.service", &req_common.source)?; - self.next.start_service(req_common, req).await + self.check_local_zone_permit("group.service", &req.common.source)?; + self.next.start_service(req).await } async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult { - self.check_local_zone_permit("group.proposal", &req_common.source)?; - self.next.push_proposal(req_common, req).await + self.check_local_zone_permit("group.proposal", &req.common.source)?; + self.next.push_proposal(req).await } } diff --git a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs index c61ad9d83..f9868ca2f 100644 --- a/src/component/cyfs-stack/src/group_api/router/group_service_router.rs +++ b/src/component/cyfs-stack/src/group_api/router/group_service_router.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use cyfs_base::{BuckyResult, DeviceId, ObjectId}; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupInputRequestCommon, GroupPushProposalInputResponse, GroupRequestor, - GroupStartServiceInputRequest, GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputRequest, GroupPushProposalInputResponse, + GroupRequestor, GroupStartServiceInputRequest, GroupStartServiceInputResponse, }; use crate::{ @@ -85,20 +85,18 @@ impl GroupServiceRouter { pub async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - let processor = self.get_processor(req_common.source.dec, None).await?; - processor.start_service(req_common, req).await + let processor = self.get_processor(req.common.source.dec, None).await?; + processor.start_service(req).await } pub async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult { - let processor = self.get_processor(req_common.source.dec, None).await?; - processor.push_proposal(req_common, req).await + let processor = self.get_processor(req.common.source.dec, None).await?; + processor.push_proposal(req).await } } @@ -106,19 +104,17 @@ impl GroupServiceRouter { impl GroupInputProcessor for GroupServiceRouter { async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { - let processor = self.get_processor(req_common.source.dec, None).await?; - processor.start_service(req_common, req).await + let processor = self.get_processor(req.common.source.dec, None).await?; + processor.start_service(req).await } async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult { - let processor = self.get_processor(req_common.source.dec, None).await?; - processor.push_proposal(req_common, req).await + let processor = self.get_processor(req.common.source.dec, None).await?; + processor.push_proposal(req).await } } diff --git a/src/component/cyfs-stack/src/group_api/router/local_service.rs b/src/component/cyfs-stack/src/group_api/router/local_service.rs index e7257a258..56caa8ac0 100644 --- a/src/component/cyfs-stack/src/group_api/router/local_service.rs +++ b/src/component/cyfs-stack/src/group_api/router/local_service.rs @@ -4,8 +4,8 @@ use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult, NamedObject, ObjectDesc use cyfs_core::{GroupProposal, GroupProposalObject}; use cyfs_group::GroupManager; use cyfs_group_lib::{ - GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, - GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputRequest, GroupPushProposalInputResponse, + GroupStartServiceInputRequest, GroupStartServiceInputResponse, }; use crate::group::{GroupInputProcessor, GroupInputProcessorRef}; @@ -29,13 +29,12 @@ impl LocalGroupService { impl GroupInputProcessor for LocalGroupService { async fn start_service( &self, - req_common: GroupInputRequestCommon, req: GroupStartServiceInputRequest, ) -> BuckyResult { self.group_manager .find_rpath_service( &req.group_id, - &req_common.source.dec, + &req.common.source.dec, req.rpath.as_str(), true, ) @@ -45,7 +44,7 @@ impl GroupInputProcessor for LocalGroupService { log::error!( "group start service {}-{}-{} failed {:?}", req.group_id, - req_common.source.dec, + req.common.source.dec, req.rpath, err ); @@ -55,19 +54,18 @@ impl GroupInputProcessor for LocalGroupService { async fn push_proposal( &self, - req_common: GroupInputRequestCommon, - req: GroupProposal, + req: GroupPushProposalInputRequest, ) -> BuckyResult { - let proposal_id = req.desc().object_id(); - let rpath = req.rpath().clone(); - if &req_common.source.dec != rpath.dec_id() { + let proposal_id = req.proposal.desc().object_id(); + let rpath = req.proposal.rpath().clone(); + if &req.common.source.dec != rpath.dec_id() { let msg = format!( "group push proposal {}-{}-{} {} failed: the source dec({}) should be same as that in GroupProposal object", rpath.group_id(), rpath.dec_id(), rpath.rpath(), proposal_id, - req_common.source.dec + req.common.source.dec ); log::error!("{}", msg); return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg)); @@ -76,8 +74,8 @@ impl GroupInputProcessor for LocalGroupService { let service = self .group_manager .find_rpath_service( - req.rpath().group_id(), - &req_common.source.dec, + rpath.group_id(), + &req.common.source.dec, rpath.rpath(), true, ) @@ -95,7 +93,7 @@ impl GroupInputProcessor for LocalGroupService { })?; service - .push_proposal(req) + .push_proposal(req.proposal) .await .map(|object| GroupPushProposalInputResponse { object }) .map_err(|err| { diff --git a/src/component/cyfs-stack/src/group_api/service/group_handler.rs b/src/component/cyfs-stack/src/group_api/service/group_handler.rs index 24d8eef54..017f401e0 100644 --- a/src/component/cyfs-stack/src/group_api/service/group_handler.rs +++ b/src/component/cyfs-stack/src/group_api/service/group_handler.rs @@ -1,8 +1,8 @@ use cyfs_base::*; use cyfs_core::GroupProposal; use cyfs_group_lib::{ - GroupInputRequestCommon, GroupPushProposalInputResponse, GroupStartServiceInputRequest, - GroupStartServiceInputResponse, + GroupInputRequestCommon, GroupPushProposalInputRequest, GroupPushProposalInputResponse, + GroupStartServiceInputRequest, GroupStartServiceInputResponse, }; use cyfs_lib::{NONRequestorHelper, RequestorHelper}; @@ -59,7 +59,7 @@ impl GroupRequestHandler { let req = GroupStartServiceInputRequest::decode_json(&body)?; - self.processor.start_service(common, req).await + self.processor.start_service(req).await } pub async fn process_push_proposal( @@ -106,6 +106,8 @@ impl GroupRequestHandler { info!("recv push proposal: {}", object.object_id); - self.processor.push_proposal(common, proposal).await + self.processor + .push_proposal(GroupPushProposalInputRequest { common, proposal }) + .await } }